From 7ea305424c02f09ff81ad44560f2e64b689b4b0b Mon Sep 17 00:00:00 2001
From: Justin Palpant <jpalpant@varmour.com>
Date: Tue, 22 Aug 2017 12:29:44 -0700
Subject: [PATCH 1/9] Initial cut on switching to traefik and docker stack

A basic traefik image with customization is defined under /traefik.

The docker-compose file describes a registry and traefik proxy. The
registry exposes :5000 and is insecure. It has to come up first, and
then other images can be pulled from it.
---
 Dockerfile           |  2 --
 README.md            |  1 -
 README.rst           |  9 ++++++
 docker-compose.yml   | 76 ++++++++++++++++++++++++++++++++++++++++++++
 traefik/Dockerfile   |  4 +++
 traefik/static.toml  | 40 +++++++++++++++++++++++
 traefik/traefik.toml | 69 ++++++++++++++++++++++++++++++++++++++++
 7 files changed, 198 insertions(+), 3 deletions(-)
 delete mode 100644 Dockerfile
 delete mode 100644 README.md
 create mode 100644 README.rst
 create mode 100644 docker-compose.yml
 create mode 100644 traefik/Dockerfile
 create mode 100644 traefik/static.toml
 create mode 100644 traefik/traefik.toml

diff --git a/Dockerfile b/Dockerfile
deleted file mode 100644
index 765bbe3..0000000
--- a/Dockerfile
+++ /dev/null
@@ -1,2 +0,0 @@
-FROM jwilder/nginx-proxy:alpine
-LABEL maintainer Justin Palpant <justin@palpant.us>
diff --git a/README.md b/README.md
deleted file mode 100644
index c9598b3..0000000
--- a/README.md
+++ /dev/null
@@ -1 +0,0 @@
-Initial commit with README for what will be come the lab NGINX configuration
diff --git a/README.rst b/README.rst
new file mode 100644
index 0000000..0a4d887
--- /dev/null
+++ b/README.rst
@@ -0,0 +1,9 @@
+What Is It?
+-----------
+This project will hold the files I use to describe the infrastructure for hosting applications in my homelab.
+
+Copyright and License
+---------------------
+Copyright 2017 Justin Palpant
+
+All rights reserved.
diff --git a/docker-compose.yml b/docker-compose.yml
new file mode 100644
index 0000000..a81f935
--- /dev/null
+++ b/docker-compose.yml
@@ -0,0 +1,76 @@
+version: '3.3'
+services:
+  registry:
+    image: registry:latest
+    networks:
+      - registry-net
+    ports:
+      - 5000:5000
+    volumes:
+      - swarm-registry:/var/lib/registry
+    deploy:
+      mode: replicated
+      replicas: 1
+      placement:
+        constraints:
+          - node.labels.persist-registry == true
+
+  traefik:
+    image: registry.palpant.us/traefik-public
+    networks:
+      - traefik-net
+    deploy:
+      mode: replicated
+      replicas: 1
+      labels:
+        - "traefik.port=8080"
+        - "traefik.docker.network=traefik-net"
+        - "traefik.frontend.rule=Host:traefik.palpant.us"
+        - "traefik.enable=true"
+      placement:
+        constraints:
+          - node.role == manager
+    ports:
+      - 9080:80
+    volumes:
+      - /var/run/docker.sock:/var/run/docker.sock
+          
+  visualizer:
+    image: dockersamples/visualizer:stable
+    volumes:
+      - "/var/run/docker.sock:/var/run/docker.sock"
+    deploy:
+      mode: replicated
+      replicas: 1
+      placement:
+        constraints:
+          - node.role == manager
+      labels:
+        - "traefik.port=8080"
+        - "traefik.docker.network=traefik-net"
+        - "traefik.frontend.rule=Host:visualizer.palpant.us"
+        - "traefik.enable=true"
+    networks:
+      - traefik-net
+
+  test:
+    image: appropriate/nc:latest
+    command: sleep 10000
+    networks:
+      - traefik-net
+    deploy:
+      mode: replicated
+      replicas: 1
+      placement:
+        constraints:
+          - node.role == manager
+
+networks:
+  traefik-net:
+    external: true
+  registry-net:
+    external: true  
+
+volumes:
+  swarm-registry:
+    external: true
diff --git a/traefik/Dockerfile b/traefik/Dockerfile
new file mode 100644
index 0000000..4ed5a95
--- /dev/null
+++ b/traefik/Dockerfile
@@ -0,0 +1,4 @@
+FROM traefik
+LABEL maintainer justin@palpant.us
+
+COPY traefik.toml /etc/traefik/traefik.toml
diff --git a/traefik/static.toml b/traefik/static.toml
new file mode 100644
index 0000000..621fef3
--- /dev/null
+++ b/traefik/static.toml
@@ -0,0 +1,40 @@
+# static.toml
+[backends]
+  [backends.backend1]
+    [backends.backend1.circuitbreaker]
+      expression = "NetworkErrorRatio() > 0.5"
+    [backends.backend1.servers.server1]
+    url = "http://172.17.0.2:80"
+    weight = 10
+    [backends.backend1.servers.server2]
+    url = "http://172.17.0.3:80"
+    weight = 1
+  [backends.backend2]
+    [backends.backend1.maxconn]
+      amount = 10
+      extractorfunc = "request.host"
+    [backends.backend2.LoadBalancer]
+      method = "drr"
+    [backends.backend2.servers.server1]
+    url = "http://172.17.0.4:80"
+    weight = 1
+    [backends.backend2.servers.server2]
+    url = "http://172.17.0.5:80"
+    weight = 2
+
+[frontends]
+  [frontends.frontend1]
+  backend = "backend2"
+    [frontends.frontend1.routes.test_1]
+    rule = "Host:test.localhost"
+  [frontends.frontend2]
+  backend = "backend1"
+  passHostHeader = true
+  priority = 10
+  entrypoints = ["https"] # overrides defaultEntryPoints
+    [frontends.frontend2.routes.test_1]
+    rule = "Host:{subdomain:[a-z]+}.localhost"
+  [frontends.frontend3]
+  entrypoints = ["http", "https"] # overrides defaultEntryPoints
+  backend = "backend2"
+    rule = "Path:/test"
\ No newline at end of file
diff --git a/traefik/traefik.toml b/traefik/traefik.toml
new file mode 100644
index 0000000..f935375
--- /dev/null
+++ b/traefik/traefik.toml
@@ -0,0 +1,69 @@
+# traefik.toml
+logLevel = "DEBUG"
+defaultEntryPoints = ["http"]
+[entryPoints]
+  [entryPoints.http]
+  address = ":80"
+
+[web]
+address = ":8080"
+
+# [file]
+# filename = "static.toml"
+
+################################################################
+# Docker configuration backend
+################################################################
+
+# Enable Docker configuration backend
+#
+# Optional
+#
+[docker]
+
+# Docker server endpoint. Can be a tcp or a unix socket endpoint.
+#
+# Required
+#
+endpoint = "unix:///var/run/docker.sock"
+
+# Default domain used.
+# Can be overridden by setting the "traefik.domain" label on a container.
+#
+# Required
+#
+domain = "palpant.us"
+
+# Enable watch docker changes
+#
+# Optional
+#
+watch = true
+
+# Override default configuration template. For advanced users :)
+#
+# Optional
+#
+# filename = "docker.tmpl"
+
+# Expose containers by default in traefik
+# If set to false, containers that don't have `traefik.enable=true` will be ignored
+#
+# Optional
+# Default: true
+#
+exposedbydefault = false
+
+# Use the IP address from the binded port instead of the inner network one. For specific use-case :)
+
+#
+# Optional
+# Default: false
+#
+# usebindportip = false
+# Use Swarm Mode services as data provider
+#
+# Optional
+# Default: false
+#
+swarmmode = true
\ No newline at end of file
-- 
GitLab


From 97b2ec0ca4fe2b6a81cb1a2b492ad25f7a503767 Mon Sep 17 00:00:00 2001
From: Justin Palpant <jpalpant@varmour.com>
Date: Tue, 22 Aug 2017 12:44:57 -0700
Subject: [PATCH 2/9] Update to use non-overlapping resource names

---
 docker-compose.yml | 18 +++++++++---------
 1 file changed, 9 insertions(+), 9 deletions(-)

diff --git a/docker-compose.yml b/docker-compose.yml
index a81f935..e06ed1a 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -3,7 +3,7 @@ services:
   registry:
     image: registry:latest
     networks:
-      - registry-net
+      - registry-public
     ports:
       - 5000:5000
     volumes:
@@ -13,18 +13,18 @@ services:
       replicas: 1
       placement:
         constraints:
-          - node.labels.persist-registry == true
+          - node.labels.registry == true
 
   traefik:
     image: registry.palpant.us/traefik-public
     networks:
-      - traefik-net
+      - traefik-public
     deploy:
       mode: replicated
       replicas: 1
       labels:
         - "traefik.port=8080"
-        - "traefik.docker.network=traefik-net"
+        - "traefik.docker.network=traefik-public"
         - "traefik.frontend.rule=Host:traefik.palpant.us"
         - "traefik.enable=true"
       placement:
@@ -47,17 +47,17 @@ services:
           - node.role == manager
       labels:
         - "traefik.port=8080"
-        - "traefik.docker.network=traefik-net"
+        - "traefik.docker.network=traefik-public"
         - "traefik.frontend.rule=Host:visualizer.palpant.us"
         - "traefik.enable=true"
     networks:
-      - traefik-net
+      - traefik-public
 
   test:
     image: appropriate/nc:latest
     command: sleep 10000
     networks:
-      - traefik-net
+      - traefik-public
     deploy:
       mode: replicated
       replicas: 1
@@ -66,9 +66,9 @@ services:
           - node.role == manager
 
 networks:
-  traefik-net:
+  traefik-public:
     external: true
-  registry-net:
+  registry-public:
     external: true  
 
 volumes:
-- 
GitLab


From beef9c6d29b4ad2c9a4cc22ecb36fd70e3e8c468 Mon Sep 17 00:00:00 2001
From: Justin Palpant <jpalpant@varmour.com>
Date: Tue, 22 Aug 2017 13:05:01 -0700
Subject: [PATCH 3/9] Change port to avoid conflict with previous service

---
 docker-compose.yml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/docker-compose.yml b/docker-compose.yml
index e06ed1a..b668f8d 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -31,7 +31,7 @@ services:
         constraints:
           - node.role == manager
     ports:
-      - 9080:80
+      - 11080:80
     volumes:
       - /var/run/docker.sock:/var/run/docker.sock
           
-- 
GitLab


From 48651c43160f56f05a8b15296f1252a9a7b3ff69 Mon Sep 17 00:00:00 2001
From: Justin Palpant <jpalpant@varmour.com>
Date: Tue, 22 Aug 2017 16:55:03 -0700
Subject: [PATCH 4/9] Secure the registry with LDAP and break up compose files

---
 registry/docker-compose.yml                   | 35 ++++++++
 registry/registry-ldap-auth/Dockerfile        |  5 ++
 registry/registry-ldap-auth/ldap.conf         |  6 ++
 registry/registry-ldap-auth/nginx.conf        | 83 +++++++++++++++++++
 spaceshooter/docker-compose.yml               | 18 ++++
 timpalpantus/docker-compose.yml               | 18 ++++
 .../docker-compose.yml                        | 33 --------
 7 files changed, 165 insertions(+), 33 deletions(-)
 create mode 100644 registry/docker-compose.yml
 create mode 100644 registry/registry-ldap-auth/Dockerfile
 create mode 100644 registry/registry-ldap-auth/ldap.conf
 create mode 100644 registry/registry-ldap-auth/nginx.conf
 create mode 100644 spaceshooter/docker-compose.yml
 create mode 100644 timpalpantus/docker-compose.yml
 rename docker-compose.yml => traefik/docker-compose.yml (63%)

diff --git a/registry/docker-compose.yml b/registry/docker-compose.yml
new file mode 100644
index 0000000..4f605b4
--- /dev/null
+++ b/registry/docker-compose.yml
@@ -0,0 +1,35 @@
+version: '3.3'
+services:
+  registry:
+    image: registry:latest
+    networks:
+      - registry-public
+    volumes:
+      - swarm-registry:/var/lib/registry
+    deploy:
+      mode: replicated
+      replicas: 1
+      placement:
+        constraints:
+          - node.labels.registry == true
+
+  registry-ldap-auth:
+    image: palpantlab-registry-ldap
+    networks:
+      - registry-public
+    ports:
+      - 12080:80
+    deploy:
+      mode: replicated
+      replicas: 1
+      placement:
+        constraints:
+          - node.labels.registry == true
+
+networks:
+  registry-public:
+    external: true  
+
+volumes:
+  swarm-registry:
+    external: true
diff --git a/registry/registry-ldap-auth/Dockerfile b/registry/registry-ldap-auth/Dockerfile
new file mode 100644
index 0000000..cdebea9
--- /dev/null
+++ b/registry/registry-ldap-auth/Dockerfile
@@ -0,0 +1,5 @@
+FROM h3nrik/registry-ldap-auth
+LABEL maintainer Justin Palpant <justin@palpant.us>
+
+COPY nginx.conf /etc/nginx/nginx.conf
+COPY ldap.conf /etc/nginx/ldap.conf
diff --git a/registry/registry-ldap-auth/ldap.conf b/registry/registry-ldap-auth/ldap.conf
new file mode 100644
index 0000000..74fbab0
--- /dev/null
+++ b/registry/registry-ldap-auth/ldap.conf
@@ -0,0 +1,6 @@
+url "ldaps://ldap.palpant.us/DC=palpant,DC=us?uid?sub?(&(objectClass=person))";
+group_attribute member;
+group_attribute_is_dn on;
+require valid_user;
+satisfy all;
+ssl_check_cert on;
\ No newline at end of file
diff --git a/registry/registry-ldap-auth/nginx.conf b/registry/registry-ldap-auth/nginx.conf
new file mode 100644
index 0000000..036039e
--- /dev/null
+++ b/registry/registry-ldap-auth/nginx.conf
@@ -0,0 +1,83 @@
+worker_processes  1;
+
+events {
+    worker_connections  1024;
+}
+
+http {
+    upstream docker-registry {
+        server registry:5000;
+    }
+
+    ## Set a variable to help us decide if we need to add the
+    ## 'Docker-Distribution-Api-Version' header.
+    ## The registry always sets this header.
+    ## In the case of nginx performing auth, the header will be unset
+    ## since nginx is auth-ing before proxying.
+    map $upstream_http_docker_distribution_api_version $docker_distribution_api_version {
+        'registry/2.0' '';
+        default registry/2.0;
+    }
+
+    ldap_server ldapserver {
+        include ldap.conf;
+    }
+
+    server {
+        listen 80;
+        server_name docker-registry-proxy;
+
+        # disable any limits to avoid HTTP 413 for large image uploads
+        client_max_body_size 0;
+
+        # required to avoid HTTP 411: see Issue #1486 (https://github.com/docker/docker/issues/1486)
+        chunked_transfer_encoding on;
+
+        # For possible locations have a look at https://docs.docker.com/registry/spec/api/#detail
+
+        location /v2/_catalog {
+            include docker-client.conf;
+            include docker-registry.conf;
+        }
+
+        location ~* /v2/(?<namespace>([^/]*))/ {
+
+            include docker-client.conf;
+
+            auth_ldap "Forbidden";
+            auth_ldap_servers ldapserver; 
+
+            set $deny_write_request "";
+            if ($request_method = PUT) {
+                set $deny_write_request "W";
+            }           
+            if ($request_method = POST) {
+                set $deny_write_request "W";
+            }           
+            if ($request_method = PATCH) {
+                set $deny_write_request "W";
+            }           
+            if ($request_method = DELETE) { 
+                set $deny_write_request "W";
+            }           
+            if ($remote_user != $namespace) {
+                set $deny_write_request "${deny_write_request}A";
+            }           
+            if ($deny_write_request = 'WA') {
+                return 401;     
+            }           
+
+            include docker-registry.conf;
+
+        }  
+
+        location /v2/ {
+            include docker-client.conf;
+            auth_ldap "Forbidden";
+            auth_ldap_servers ldapserver;
+            include docker-registry.conf;
+        }
+
+    }
+
+}
\ No newline at end of file
diff --git a/spaceshooter/docker-compose.yml b/spaceshooter/docker-compose.yml
new file mode 100644
index 0000000..87b5bae
--- /dev/null
+++ b/spaceshooter/docker-compose.yml
@@ -0,0 +1,18 @@
+version: '3.3'
+services:
+  spaceshooter:
+    image: registry.palpant.us/spaceshooter
+    networks:
+      - traefik-public
+    deploy:
+      mode: replicated
+      replicas: 1
+      labels:
+        - "traefik.port=80"
+        - "traefik.docker.network=traefik-public"
+        - "traefik.frontend.rule=Host:spaceshooter.palpant.us"
+        - "traefik.enable=true"
+
+networks:
+  traefik-public:
+    external: true
diff --git a/timpalpantus/docker-compose.yml b/timpalpantus/docker-compose.yml
new file mode 100644
index 0000000..64ceb2f
--- /dev/null
+++ b/timpalpantus/docker-compose.yml
@@ -0,0 +1,18 @@
+version: '3.3'
+services:
+  timpalpantus:
+    image: registry.palpant.us/timpalpant-website
+    networks:
+      - traefik-public
+    deploy:
+      mode: replicated
+      replicas: 1
+      labels:
+        - "traefik.port=80"
+        - "traefik.docker.network=traefik-public"
+        - "traefik.frontend.rule=Host:tim.palpant.us"
+        - "traefik.enable=true"
+
+networks:
+  traefik-public:
+    external: true
diff --git a/docker-compose.yml b/traefik/docker-compose.yml
similarity index 63%
rename from docker-compose.yml
rename to traefik/docker-compose.yml
index b668f8d..1088aa5 100644
--- a/docker-compose.yml
+++ b/traefik/docker-compose.yml
@@ -1,20 +1,5 @@
 version: '3.3'
 services:
-  registry:
-    image: registry:latest
-    networks:
-      - registry-public
-    ports:
-      - 5000:5000
-    volumes:
-      - swarm-registry:/var/lib/registry
-    deploy:
-      mode: replicated
-      replicas: 1
-      placement:
-        constraints:
-          - node.labels.registry == true
-
   traefik:
     image: registry.palpant.us/traefik-public
     networks:
@@ -53,24 +38,6 @@ services:
     networks:
       - traefik-public
 
-  test:
-    image: appropriate/nc:latest
-    command: sleep 10000
-    networks:
-      - traefik-public
-    deploy:
-      mode: replicated
-      replicas: 1
-      placement:
-        constraints:
-          - node.role == manager
-
 networks:
   traefik-public:
     external: true
-  registry-public:
-    external: true  
-
-volumes:
-  swarm-registry:
-    external: true
-- 
GitLab


From 7d6f61db07ca3ecc559cc9d0790cc9addb9697ec Mon Sep 17 00:00:00 2001
From: Justin Palpant <jpalpant@varmour.com>
Date: Tue, 22 Aug 2017 19:04:38 -0700
Subject: [PATCH 5/9] Switch to private network

---
 registry/docker-compose.yml | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/registry/docker-compose.yml b/registry/docker-compose.yml
index 4f605b4..92615e1 100644
--- a/registry/docker-compose.yml
+++ b/registry/docker-compose.yml
@@ -3,7 +3,7 @@ services:
   registry:
     image: registry:latest
     networks:
-      - registry-public
+      - registry-private
     volumes:
       - swarm-registry:/var/lib/registry
     deploy:
@@ -14,11 +14,11 @@ services:
           - node.labels.registry == true
 
   registry-ldap-auth:
-    image: palpantlab-registry-ldap
+    image: palpantlab-registry-ldap # not a registry image! Must be built without registry on registry host
     networks:
-      - registry-public
+      - registry-private
     ports:
-      - 12080:80
+      - 12080:80 # not a Traefik port! Must run before traefik
     deploy:
       mode: replicated
       replicas: 1
@@ -27,7 +27,7 @@ services:
           - node.labels.registry == true
 
 networks:
-  registry-public:
+  registry-private:
     external: true  
 
 volumes:
-- 
GitLab


From 9a3c2b693c3860414ffe660b1f571ce35c7f5258 Mon Sep 17 00:00:00 2001
From: Justin Palpant <jpalpant@varmour.com>
Date: Tue, 22 Aug 2017 19:34:21 -0700
Subject: [PATCH 6/9] Remove registry LDAP authenticator and expose registry

---
 registry/docker-compose.yml | 26 ++++++++++++++------------
 1 file changed, 14 insertions(+), 12 deletions(-)

diff --git a/registry/docker-compose.yml b/registry/docker-compose.yml
index 92615e1..f1cef98 100644
--- a/registry/docker-compose.yml
+++ b/registry/docker-compose.yml
@@ -6,19 +6,8 @@ services:
       - registry-private
     volumes:
       - swarm-registry:/var/lib/registry
-    deploy:
-      mode: replicated
-      replicas: 1
-      placement:
-        constraints:
-          - node.labels.registry == true
-
-  registry-ldap-auth:
-    image: palpantlab-registry-ldap # not a registry image! Must be built without registry on registry host
-    networks:
-      - registry-private
     ports:
-      - 12080:80 # not a Traefik port! Must run before traefik
+      - 12080:5000
     deploy:
       mode: replicated
       replicas: 1
@@ -26,6 +15,19 @@ services:
         constraints:
           - node.labels.registry == true
 
+  # registry-ldap-auth:
+  #   image: palpantlab-registry-ldap # not a registry image! Must be built without registry on registry host
+  #   networks:
+  #     - registry-private
+  #   ports:
+  #     - 12080:80 # not a Traefik port! Must run before traefik
+  #   deploy:
+  #     mode: replicated
+  #     replicas: 1
+  #     placement:
+  #       constraints:
+  #         - node.labels.registry == true
+
 networks:
   registry-private:
     external: true  
-- 
GitLab


From 64f169870c37ef2d9f1eb180e70f548ae29a3758 Mon Sep 17 00:00:00 2001
From: Justin Palpant <jpalpant@varmour.com>
Date: Fri, 25 Aug 2017 22:37:05 -0700
Subject: [PATCH 7/9] Traefik doesn't support SSL Passthrough

To get around this I will expose one more port and server any services
that require SSL passthrough with SNI behind that port, using
docker-flow-proxy as my dynamically reconfiguring
proxy. docker-flow-proxy listens to swarm and updates HAProxy, and
supports SNI-based SSL passthrough. For now, I will use
docker-flow-proxy for registry and auth server, and traefik for http
services or services where I want https termination.
---
 auth/Dockerfile                        |  9 +++
 auth/config/auth_config.yml            | 54 +++++++++++++++++
 auth/docker-compose.yml                | 32 ++++++++++
 auth/start.sh                          | 17 ++++++
 flowproxy/Dockerfile                   |  3 +
 flowproxy/docker-compose.yml           | 36 +++++++++++
 registry/Dockerfile                    |  4 ++
 registry/conf/config.yml               | 30 ++++++++++
 registry/docker-compose.yml            | 35 +++++------
 registry/registry-ldap-auth/Dockerfile |  5 --
 registry/registry-ldap-auth/ldap.conf  |  6 --
 registry/registry-ldap-auth/nginx.conf | 83 --------------------------
 12 files changed, 201 insertions(+), 113 deletions(-)
 create mode 100644 auth/Dockerfile
 create mode 100644 auth/config/auth_config.yml
 create mode 100644 auth/docker-compose.yml
 create mode 100644 auth/start.sh
 create mode 100644 flowproxy/Dockerfile
 create mode 100644 flowproxy/docker-compose.yml
 create mode 100644 registry/Dockerfile
 create mode 100644 registry/conf/config.yml
 delete mode 100644 registry/registry-ldap-auth/Dockerfile
 delete mode 100644 registry/registry-ldap-auth/ldap.conf
 delete mode 100644 registry/registry-ldap-auth/nginx.conf

diff --git a/auth/Dockerfile b/auth/Dockerfile
new file mode 100644
index 0000000..865bf32
--- /dev/null
+++ b/auth/Dockerfile
@@ -0,0 +1,9 @@
+FROM cesanta/docker_auth
+LABEL maintainer Justin Palpant <justin@palpant.us>
+
+COPY start.sh /start.sh
+RUN chmod +x /start.sh
+RUN chmod 777 /start.sh
+COPY config /config
+
+ENTRYPOINT /start.sh
diff --git a/auth/config/auth_config.yml b/auth/config/auth_config.yml
new file mode 100644
index 0000000..c8a9035
--- /dev/null
+++ b/auth/config/auth_config.yml
@@ -0,0 +1,54 @@
+# . See reference.yml for explanation for explanation of all options.
+#
+#  auth:
+#    token:
+#      realm: "https://127.0.0.1:5001/auth"
+#      service: "Docker registry"
+#      issuer: "Acme auth server"
+#      rootcertbundle: "/path/to/server.pem"
+
+server:
+  addr: ":5001"
+  certificate: "/run/secrets/auth-cert"
+  key: "/run/secrets/auth-key"
+
+token:
+  issuer: "Acme auth server"  # Must match issuer in the Registry config.
+  expiration: 900
+
+# LDAP authentication.
+# Authentication is performed by first binding to the server, looking up the user entry
+# by using the specified filter, and then re-binding using the matched DN and the password provided.
+# ldap_auth:
+#   addr: "ldaps://ldap.palpant.us"
+#   #tls: true
+#   # In case bind DN and password is required for querying user information,
+#   # specify them here. Plain text password is read from the file.
+#   base: "dc=palpant,dc=us"
+#   filter: "(&(uid=${account})(objectClass=organizationalPerson))"
+
+users:
+  # Password is specified as a BCrypt hash. Use htpasswd -B to generate.
+  "admin":
+    password: "$2y$05$LO.vzwpWC5LZGqThvEfznu8qhb5SGqvBSWY1J3yZ4AxtMRZ3kN5jC"  # badmin
+  "test":
+    password: "$2y$05$WuwBasGDAgr.QCbGIjKJaep4dhxeai9gNZdmBnQXqpKly57oNutya"  # 123
+  
+acl:
+  # Admin has full access to everything.
+  - match: {account: "admin"}
+    actions: ["*"]
+  
+  # User "user" can pull stuff.
+  - match: {account: "test"}
+    actions: ["pull"]
+    
+  # This will allow authenticated users to pull/push
+  - match:
+      account: /.+/
+    actions: ['*']
+  
+  # The user "serviceaccount" (from LDAP) may not perform any docker actions
+  # like push or pull.
+  - match: {account: "serviceaccount"}
+    actions: []
diff --git a/auth/docker-compose.yml b/auth/docker-compose.yml
new file mode 100644
index 0000000..cee03b2
--- /dev/null
+++ b/auth/docker-compose.yml
@@ -0,0 +1,32 @@
+version: '3.3'
+services:
+  auth:
+    image: palpantlab-auth
+    # ports:
+    #   - 5001:5001
+    networks:
+      - flowproxy
+    secrets:
+      - auth-cert
+      - auth-key
+    deploy:
+      mode: replicated
+      replicas: 1
+      labels:
+        - com.df.notify=true
+        - com.df.distribute=true
+        - com.df.serviceDomain=auth.palpant.us
+        - com.df.port=5001
+        - com.df.srcPort=9669
+        - com.df.reqMode=sni
+
+networks:
+  flowproxy:
+    external: true
+
+secrets:
+  auth-cert:
+    external: true
+  auth-key:
+    external: true
+  
diff --git a/auth/start.sh b/auth/start.sh
new file mode 100644
index 0000000..5d17626
--- /dev/null
+++ b/auth/start.sh
@@ -0,0 +1,17 @@
+#!/bin/sh
+
+# Copy over certificates to correct place and update certificate storage
+# find "/config/ldap_certificates" -type f -exec cp -fv {} /usr/local/share/ca-certificates/ \;
+# update-ca-certificates
+
+# # Replace newline and carriage returns in password file
+# cat /config/ldap_password.txt | tr -d '\r\n' > /tmp/ldap_password.txt.clean
+
+# # If we see a custom config file, we load that instead of the default one
+CONF_PATH=/config/auth_config.yml
+if [ -f $CONF_PATH.custom ]; then
+  CONF_PATH=$CONF_PATH.custom
+fi
+
+# Start the auth server
+/docker_auth/auth_server -v=5 $CONF_PATH
diff --git a/flowproxy/Dockerfile b/flowproxy/Dockerfile
new file mode 100644
index 0000000..1929676
--- /dev/null
+++ b/flowproxy/Dockerfile
@@ -0,0 +1,3 @@
+FROM vfarcic/docker-flow-proxy:beta
+
+HEALTHCHECK --interval=5s --timeout=5s CMD wget -qO- "http://localhost:8080/v1/docker-flow-proxy/ping"
diff --git a/flowproxy/docker-compose.yml b/flowproxy/docker-compose.yml
new file mode 100644
index 0000000..ff1381e
--- /dev/null
+++ b/flowproxy/docker-compose.yml
@@ -0,0 +1,36 @@
+version: "3.3"
+services:
+  proxy:
+    image: palpantlab-flowproxy
+    ports:
+      - 8080:8080
+      - 9669:9669
+    networks:
+      - flowproxy
+    environment:
+      - LISTENER_ADDRESS=swarm-listener
+      - MODE=swarm
+      - DEBUG=true
+    deploy:
+      replicas: 1
+
+  swarm-listener:
+    image: vfarcic/docker-flow-swarm-listener
+    networks:
+      - flowproxy
+    environment:
+      - DF_NOTIFY_CREATE_SERVICE_URL=http://proxy:8080/v1/docker-flow-proxy/reconfigure
+      - DF_NOTIFY_REMOVE_SERVICE_URL=http://proxy:8080/v1/docker-flow-proxy/remove
+      - DF_INTERVAL=1
+    volumes:
+      - /var/run/docker.sock:/var/run/docker.sock
+    deploy:
+      mode: replicated
+      replicas: 1
+      placement:
+        constraints:
+          - node.role == manager
+
+networks:
+  flowproxy:
+    external: true
diff --git a/registry/Dockerfile b/registry/Dockerfile
new file mode 100644
index 0000000..73ce35a
--- /dev/null
+++ b/registry/Dockerfile
@@ -0,0 +1,4 @@
+FROM registry:latest
+LABEL maintainer Justin Palpant <justin@palpant.us>
+
+COPY conf /etc/docker/registry
diff --git a/registry/conf/config.yml b/registry/conf/config.yml
new file mode 100644
index 0000000..2adac53
--- /dev/null
+++ b/registry/conf/config.yml
@@ -0,0 +1,30 @@
+version: 0.1
+log:
+  fields:
+    service: registry
+storage:
+    cache:
+        blobdescriptor: inmemory
+    filesystem:
+        rootdirectory: /var/lib/registry
+http:
+    addr: :5000
+    host: https://registry.palpant.us
+    headers:
+        X-Content-Type-Options: [nosniff]
+    tls:
+      certificate: /run/secrets/registry_cert
+      key: /run/secrets/registry_key
+    http2:
+      disabled: false
+health:
+  storagedriver:
+    enabled: true
+    interval: 10s
+    threshold: 3
+auth:
+  token:
+    realm: "https://auth.palpant.us/auth"
+    service: "registry.palpant.us"
+    issuer: "Acme auth server"
+    rootcertbundle: /run/secrets/auth_cert
diff --git a/registry/docker-compose.yml b/registry/docker-compose.yml
index f1cef98..e6b4a94 100644
--- a/registry/docker-compose.yml
+++ b/registry/docker-compose.yml
@@ -1,35 +1,32 @@
 version: '3.3'
 services:
   registry:
-    image: registry:latest
-    networks:
-      - registry-private
+    image: palpantlab-registry
     volumes:
       - swarm-registry:/var/lib/registry
-    ports:
-      - 12080:5000
+    networks:
+      - flowproxy
+    # ports:
+    #   - 5000:5000
+    secrets:
+      - registry_cert
+      - registry_key
     deploy:
+      labels:
+        - com.df.notify=true
+        - com.df.distribute=true
+        - com.df.serviceDomain=registry.palpant.us
+        - com.df.port=5000
+        - com.df.srcPort=9669
+        - com.df.reqMode=sni
       mode: replicated
       replicas: 1
       placement:
         constraints:
           - node.labels.registry == true
 
-  # registry-ldap-auth:
-  #   image: palpantlab-registry-ldap # not a registry image! Must be built without registry on registry host
-  #   networks:
-  #     - registry-private
-  #   ports:
-  #     - 12080:80 # not a Traefik port! Must run before traefik
-  #   deploy:
-  #     mode: replicated
-  #     replicas: 1
-  #     placement:
-  #       constraints:
-  #         - node.labels.registry == true
-
 networks:
-  registry-private:
+  flowproxy:
     external: true  
 
 volumes:
diff --git a/registry/registry-ldap-auth/Dockerfile b/registry/registry-ldap-auth/Dockerfile
deleted file mode 100644
index cdebea9..0000000
--- a/registry/registry-ldap-auth/Dockerfile
+++ /dev/null
@@ -1,5 +0,0 @@
-FROM h3nrik/registry-ldap-auth
-LABEL maintainer Justin Palpant <justin@palpant.us>
-
-COPY nginx.conf /etc/nginx/nginx.conf
-COPY ldap.conf /etc/nginx/ldap.conf
diff --git a/registry/registry-ldap-auth/ldap.conf b/registry/registry-ldap-auth/ldap.conf
deleted file mode 100644
index 74fbab0..0000000
--- a/registry/registry-ldap-auth/ldap.conf
+++ /dev/null
@@ -1,6 +0,0 @@
-url "ldaps://ldap.palpant.us/DC=palpant,DC=us?uid?sub?(&(objectClass=person))";
-group_attribute member;
-group_attribute_is_dn on;
-require valid_user;
-satisfy all;
-ssl_check_cert on;
\ No newline at end of file
diff --git a/registry/registry-ldap-auth/nginx.conf b/registry/registry-ldap-auth/nginx.conf
deleted file mode 100644
index 036039e..0000000
--- a/registry/registry-ldap-auth/nginx.conf
+++ /dev/null
@@ -1,83 +0,0 @@
-worker_processes  1;
-
-events {
-    worker_connections  1024;
-}
-
-http {
-    upstream docker-registry {
-        server registry:5000;
-    }
-
-    ## Set a variable to help us decide if we need to add the
-    ## 'Docker-Distribution-Api-Version' header.
-    ## The registry always sets this header.
-    ## In the case of nginx performing auth, the header will be unset
-    ## since nginx is auth-ing before proxying.
-    map $upstream_http_docker_distribution_api_version $docker_distribution_api_version {
-        'registry/2.0' '';
-        default registry/2.0;
-    }
-
-    ldap_server ldapserver {
-        include ldap.conf;
-    }
-
-    server {
-        listen 80;
-        server_name docker-registry-proxy;
-
-        # disable any limits to avoid HTTP 413 for large image uploads
-        client_max_body_size 0;
-
-        # required to avoid HTTP 411: see Issue #1486 (https://github.com/docker/docker/issues/1486)
-        chunked_transfer_encoding on;
-
-        # For possible locations have a look at https://docs.docker.com/registry/spec/api/#detail
-
-        location /v2/_catalog {
-            include docker-client.conf;
-            include docker-registry.conf;
-        }
-
-        location ~* /v2/(?<namespace>([^/]*))/ {
-
-            include docker-client.conf;
-
-            auth_ldap "Forbidden";
-            auth_ldap_servers ldapserver; 
-
-            set $deny_write_request "";
-            if ($request_method = PUT) {
-                set $deny_write_request "W";
-            }           
-            if ($request_method = POST) {
-                set $deny_write_request "W";
-            }           
-            if ($request_method = PATCH) {
-                set $deny_write_request "W";
-            }           
-            if ($request_method = DELETE) { 
-                set $deny_write_request "W";
-            }           
-            if ($remote_user != $namespace) {
-                set $deny_write_request "${deny_write_request}A";
-            }           
-            if ($deny_write_request = 'WA') {
-                return 401;     
-            }           
-
-            include docker-registry.conf;
-
-        }  
-
-        location /v2/ {
-            include docker-client.conf;
-            auth_ldap "Forbidden";
-            auth_ldap_servers ldapserver;
-            include docker-registry.conf;
-        }
-
-    }
-
-}
\ No newline at end of file
-- 
GitLab


From 6fe8bf10e2e2a64376692bd386e5345c950200cc Mon Sep 17 00:00:00 2001
From: Justin Palpant <jpalpant@varmour.com>
Date: Sat, 26 Aug 2017 18:19:17 -0700
Subject: [PATCH 8/9] Manually configure HAProxy to support registry, auth, and
 NAS

---
 auth/config/auth_config.yml   | 10 ++--
 auth/docker-compose.yml       |  7 ---
 flowproxy/Dockerfile          |  6 +--
 flowproxy/docker-compose.yml  | 25 +---------
 flowproxy/haproxy.cfg         | 94 +++++++++++++++++++++++++++++++++++
 registry/conf/config.yml      |  6 +--
 registry/docker-compose.yml   | 20 ++++----
 traefik/docker-compose.yml    | 18 -------
 visualizer/docker-compose.yml | 23 +++++++++
 9 files changed, 141 insertions(+), 68 deletions(-)
 create mode 100644 flowproxy/haproxy.cfg
 create mode 100644 visualizer/docker-compose.yml

diff --git a/auth/config/auth_config.yml b/auth/config/auth_config.yml
index c8a9035..a400bea 100644
--- a/auth/config/auth_config.yml
+++ b/auth/config/auth_config.yml
@@ -21,11 +21,11 @@ token:
 # by using the specified filter, and then re-binding using the matched DN and the password provided.
 # ldap_auth:
 #   addr: "ldaps://ldap.palpant.us"
-#   #tls: true
+#   tls: true
 #   # In case bind DN and password is required for querying user information,
 #   # specify them here. Plain text password is read from the file.
 #   base: "dc=palpant,dc=us"
-#   filter: "(&(uid=${account})(objectClass=organizationalPerson))"
+#   filter: "(&(uid=${uid})(objectClass=person))"
 
 users:
   # Password is specified as a BCrypt hash. Use htpasswd -B to generate.
@@ -44,9 +44,9 @@ acl:
     actions: ["pull"]
     
   # This will allow authenticated users to pull/push
-  - match:
-      account: /.+/
-    actions: ['*']
+  # - match:
+  #     account: /.+/
+  #   actions: ['*']
   
   # The user "serviceaccount" (from LDAP) may not perform any docker actions
   # like push or pull.
diff --git a/auth/docker-compose.yml b/auth/docker-compose.yml
index cee03b2..010f3fa 100644
--- a/auth/docker-compose.yml
+++ b/auth/docker-compose.yml
@@ -12,13 +12,6 @@ services:
     deploy:
       mode: replicated
       replicas: 1
-      labels:
-        - com.df.notify=true
-        - com.df.distribute=true
-        - com.df.serviceDomain=auth.palpant.us
-        - com.df.port=5001
-        - com.df.srcPort=9669
-        - com.df.reqMode=sni
 
 networks:
   flowproxy:
diff --git a/flowproxy/Dockerfile b/flowproxy/Dockerfile
index 1929676..5d3e2dc 100644
--- a/flowproxy/Dockerfile
+++ b/flowproxy/Dockerfile
@@ -1,3 +1,3 @@
-FROM vfarcic/docker-flow-proxy:beta
-
-HEALTHCHECK --interval=5s --timeout=5s CMD wget -qO- "http://localhost:8080/v1/docker-flow-proxy/ping"
+FROM haproxy:1.7-alpine
+LABEL maintainer Justin Palpant <justin@palpant.us>
+COPY haproxy.cfg /usr/local/etc/haproxy/haproxy.cfg
diff --git a/flowproxy/docker-compose.yml b/flowproxy/docker-compose.yml
index ff1381e..01eefe0 100644
--- a/flowproxy/docker-compose.yml
+++ b/flowproxy/docker-compose.yml
@@ -1,35 +1,14 @@
 version: "3.3"
 services:
   proxy:
-    image: palpantlab-flowproxy
+    image: palpantlab-haproxy
     ports:
-      - 8080:8080
-      - 9669:9669
+      - 443:443
     networks:
       - flowproxy
-    environment:
-      - LISTENER_ADDRESS=swarm-listener
-      - MODE=swarm
-      - DEBUG=true
-    deploy:
-      replicas: 1
-
-  swarm-listener:
-    image: vfarcic/docker-flow-swarm-listener
-    networks:
-      - flowproxy
-    environment:
-      - DF_NOTIFY_CREATE_SERVICE_URL=http://proxy:8080/v1/docker-flow-proxy/reconfigure
-      - DF_NOTIFY_REMOVE_SERVICE_URL=http://proxy:8080/v1/docker-flow-proxy/remove
-      - DF_INTERVAL=1
-    volumes:
-      - /var/run/docker.sock:/var/run/docker.sock
     deploy:
       mode: replicated
       replicas: 1
-      placement:
-        constraints:
-          - node.role == manager
 
 networks:
   flowproxy:
diff --git a/flowproxy/haproxy.cfg b/flowproxy/haproxy.cfg
new file mode 100644
index 0000000..00c1f84
--- /dev/null
+++ b/flowproxy/haproxy.cfg
@@ -0,0 +1,94 @@
+# Adjust the timeout to your needs
+global
+    pidfile /var/run/haproxy.pid
+    tune.ssl.default-dh-param 2048
+    log 127.0.0.1:1514 local0
+
+    # disable sslv3, prefer modern ciphers
+    ssl-default-bind-options no-sslv3
+    ssl-default-bind-ciphers ECDH+AESGCM:DH+AESGCM:ECDH+AES256:DH+AES256:ECDH+AES128:DH+AES:RSA+AESGCM:RSA+AES:!aNULL:!MD5:!DSS
+
+    ssl-default-server-options no-sslv3
+    ssl-default-server-ciphers ECDH+AESGCM:DH+AESGCM:ECDH+AES256:DH+AES256:ECDH+AES128:DH+AES:RSA+AESGCM:RSA+AES:!aNULL:!MD5:!DSS
+
+resolvers docker
+    nameserver dns 127.0.0.11:53
+
+defaults
+    balance roundrobin
+    
+    maxconn 5000
+    timeout connect 5s
+    timeout client  20s
+    timeout server  20s
+    timeout queue   30s
+    timeout tunnel  3600s
+
+frontend sni_redirect
+    bind *:443
+    mode tcp
+
+    option tcplog
+    log global
+
+    tcp-request inspect-delay 5s
+    tcp-request content accept if { req_ssl_hello_type 1 }
+
+    acl registry_sni req.ssl_sni -i registry.palpant.us
+    use_backend registry_backend if registry_sni
+
+    acl auth_sni req.ssl_sni -i auth.palpant.us
+    use_backend auth_backend if auth_sni
+
+    default_backend bk_ssl_default
+
+backend registry_backend
+    mode tcp	
+    # maximum SSL session ID length is 32 bytes.
+    stick-table type binary len 32 size 30k expire 30m
+    
+    acl clienthello req_ssl_hello_type 1
+    acl serverhello rep_ssl_hello_type 2
+    
+    # use tcp content accepts to detects ssl client and server hello.
+    tcp-request inspect-delay 5s
+    tcp-request content accept if clienthello
+    
+    # no timeout on response inspect delay by default.
+    tcp-response content accept if serverhello
+    
+    stick on payload_lv(43,1) if clienthello
+    
+    # Learn on response if server hello.
+    stick store-response payload_lv(43,1) if serverhello
+    
+    server registry registry:5000
+    
+backend auth_backend
+    mode tcp	
+
+    # maximum SSL session ID length is 32 bytes.
+    stick-table type binary len 32 size 30k expire 30m
+   
+    acl clienthello req_ssl_hello_type 1
+    acl serverhello rep_ssl_hello_type 2
+   
+    # use tcp content accepts to detects ssl client and server hello.
+    tcp-request inspect-delay 5s
+    tcp-request content accept if clienthello
+   
+    # no timeout on response inspect delay by default.
+    tcp-response content accept if serverhello
+   
+    stick on payload_lv(43,1) if clienthello
+   
+    # Learn on response if server hello.
+    stick store-response payload_lv(43,1) if serverhello
+   
+    option ssl-hello-chk
+    server auth auth:5001
+
+backend bk_ssl_default
+    mode tcp
+
+    server nas_rproxy nas.sfo.palpant.us:443
\ No newline at end of file
diff --git a/registry/conf/config.yml b/registry/conf/config.yml
index 2adac53..dace61c 100644
--- a/registry/conf/config.yml
+++ b/registry/conf/config.yml
@@ -13,8 +13,8 @@ http:
     headers:
         X-Content-Type-Options: [nosniff]
     tls:
-      certificate: /run/secrets/registry_cert
-      key: /run/secrets/registry_key
+      certificate: /run/secrets/registry-cert
+      key: /run/secrets/registry-key
     http2:
       disabled: false
 health:
@@ -27,4 +27,4 @@ auth:
     realm: "https://auth.palpant.us/auth"
     service: "registry.palpant.us"
     issuer: "Acme auth server"
-    rootcertbundle: /run/secrets/auth_cert
+    rootcertbundle: /run/secrets/auth-cert
diff --git a/registry/docker-compose.yml b/registry/docker-compose.yml
index e6b4a94..cd99e8b 100644
--- a/registry/docker-compose.yml
+++ b/registry/docker-compose.yml
@@ -9,16 +9,10 @@ services:
     # ports:
     #   - 5000:5000
     secrets:
-      - registry_cert
-      - registry_key
+      - registry-cert
+      - registry-key
+      - auth-cert
     deploy:
-      labels:
-        - com.df.notify=true
-        - com.df.distribute=true
-        - com.df.serviceDomain=registry.palpant.us
-        - com.df.port=5000
-        - com.df.srcPort=9669
-        - com.df.reqMode=sni
       mode: replicated
       replicas: 1
       placement:
@@ -32,3 +26,11 @@ networks:
 volumes:
   swarm-registry:
     external: true
+
+secrets:
+  registry-cert:
+    external: true
+  registry-key:
+    external: true
+  auth-cert:
+    external: true
diff --git a/traefik/docker-compose.yml b/traefik/docker-compose.yml
index 1088aa5..f0f487e 100644
--- a/traefik/docker-compose.yml
+++ b/traefik/docker-compose.yml
@@ -20,24 +20,6 @@ services:
     volumes:
       - /var/run/docker.sock:/var/run/docker.sock
           
-  visualizer:
-    image: dockersamples/visualizer:stable
-    volumes:
-      - "/var/run/docker.sock:/var/run/docker.sock"
-    deploy:
-      mode: replicated
-      replicas: 1
-      placement:
-        constraints:
-          - node.role == manager
-      labels:
-        - "traefik.port=8080"
-        - "traefik.docker.network=traefik-public"
-        - "traefik.frontend.rule=Host:visualizer.palpant.us"
-        - "traefik.enable=true"
-    networks:
-      - traefik-public
-
 networks:
   traefik-public:
     external: true
diff --git a/visualizer/docker-compose.yml b/visualizer/docker-compose.yml
new file mode 100644
index 0000000..7821e88
--- /dev/null
+++ b/visualizer/docker-compose.yml
@@ -0,0 +1,23 @@
+version: '3.3'
+services:
+  visualizer:
+    image: dockersamples/visualizer:stable
+    volumes:
+      - "/var/run/docker.sock:/var/run/docker.sock"
+    deploy:
+      mode: replicated
+      replicas: 1
+      placement:
+        constraints:
+          - node.role == manager
+      labels:
+        - "traefik.port=8080"
+        - "traefik.docker.network=traefik-public"
+        - "traefik.frontend.rule=Host:visualizer.palpant.us"
+        - "traefik.enable=true"
+    networks:
+      - traefik-public
+
+networks:
+  traefik-public:
+    external: true
-- 
GitLab


From cd9f02630fe4b791b35b289b426d868d93ea3c38 Mon Sep 17 00:00:00 2001
From: Justin Palpant <jpalpant@varmour.com>
Date: Sat, 26 Aug 2017 19:39:18 -0700
Subject: [PATCH 9/9] Constraint auth and haproxy to nodes where those images
 are built.

---
 auth/docker-compose.yml      | 3 +++
 flowproxy/docker-compose.yml | 3 +++
 2 files changed, 6 insertions(+)

diff --git a/auth/docker-compose.yml b/auth/docker-compose.yml
index 010f3fa..3dd4b21 100644
--- a/auth/docker-compose.yml
+++ b/auth/docker-compose.yml
@@ -12,6 +12,9 @@ services:
     deploy:
       mode: replicated
       replicas: 1
+      placement:
+        constraints:
+          - node.labels.auth == true
 
 networks:
   flowproxy:
diff --git a/flowproxy/docker-compose.yml b/flowproxy/docker-compose.yml
index 01eefe0..4ecb3cb 100644
--- a/flowproxy/docker-compose.yml
+++ b/flowproxy/docker-compose.yml
@@ -9,6 +9,9 @@ services:
     deploy:
       mode: replicated
       replicas: 1
+      placement:
+        constraints:
+          - node.labels.haproxy == true
 
 networks:
   flowproxy:
-- 
GitLab