commit
61c3933e0e
3 changed files with 106 additions and 3 deletions
|
@ -21,7 +21,7 @@ RUN echo "daemon off;" >> /etc/nginx/nginx.conf \
|
|||
RUN wget -P /usr/local/bin https://godist.herokuapp.com/projects/ddollar/forego/releases/current/linux-amd64/forego \
|
||||
&& chmod u+x /usr/local/bin/forego
|
||||
|
||||
ENV DOCKER_GEN_VERSION 0.3.4
|
||||
ENV DOCKER_GEN_VERSION 0.3.6
|
||||
|
||||
RUN wget https://github.com/jwilder/docker-gen/releases/download/$DOCKER_GEN_VERSION/docker-gen-linux-amd64-$DOCKER_GEN_VERSION.tar.gz \
|
||||
&& tar -C /usr/local/bin -xvzf docker-gen-linux-amd64-$DOCKER_GEN_VERSION.tar.gz \
|
||||
|
@ -30,8 +30,9 @@ RUN wget https://github.com/jwilder/docker-gen/releases/download/$DOCKER_GEN_VER
|
|||
COPY . /app/
|
||||
WORKDIR /app/
|
||||
|
||||
|
||||
EXPOSE 80
|
||||
EXPOSE 80 443
|
||||
ENV DOCKER_HOST unix:///tmp/docker.sock
|
||||
|
||||
VOLUME ["/etc/nginx/certs"]
|
||||
|
||||
CMD ["forego", "start", "-r"]
|
||||
|
|
44
README.md
44
README.md
|
@ -51,3 +51,47 @@ $ docker run --volumes-from nginx \
|
|||
Finally, start your containers with `VIRTUAL_HOST` environment variables.
|
||||
|
||||
$ docker run -e VIRTUAL_HOST=foo.bar.com ...
|
||||
|
||||
### SSL Support
|
||||
|
||||
SSL is supported single host, wildcards and SNI certificates using naming conventions for
|
||||
certificates or optionally specify a cert name (for SNI) as an environment variable.
|
||||
|
||||
To enable SSL:
|
||||
|
||||
$ docker run -d -p 80:80 -p 443:443 -v /path/to/certs:/etc/nginx/certs -v /var/run/docker.sock:/tmp/docker.sock jwilder/nginx-proxy
|
||||
|
||||
The contents of `/path/to/certs` should contain the certificates and private keys for any virtual
|
||||
hosts in use. The certificate and keys should be named after the virtual host with a `.crt` and
|
||||
`.key` extension. For example, a container with `VIRTUAL_HOST=foo.bar.com` should have a
|
||||
`foo.bar.com.crt` and 'foo.bar.com.key' file in the certs directory.
|
||||
|
||||
#### Wildcard Certificates
|
||||
|
||||
Wildcard certificate and keys should be name after the domain name with a `.crt` and `.key` extension.
|
||||
For example `VIRTUAL_HOST=foo.bar.com` could also use cert name `bar.com.crt` and `bar.com.key`.
|
||||
|
||||
#### SNI
|
||||
|
||||
If your certificate(s) supports multiple domain names, you can start a container with `CERT_NAME=<name>`
|
||||
to identify the certificate to be used. For example, a certificate for `*.foo.com` and `*.bar.com`
|
||||
could be name `shared.crt` and `shared.key`. A container running with `VIRTUAL_HOST=foo.bar.com`
|
||||
and `CERT_NAME=shared` will then use this shared cert.
|
||||
|
||||
#### How SSL Support Works
|
||||
|
||||
The SSL cipher configuration is based on [mozilla nginx intermediate profile](https://wiki.mozilla.org/Security/Server_Side_TLS#Nginx) which
|
||||
should provide compatibility with clients back to Firefox 1, Chrome 1, IE 7, Opera 5, Safari 1,
|
||||
Windows XP IE8, Android 2.3, Java 7. The configuration also enables OCSP stapling, HSTS, and SSL
|
||||
session caches.
|
||||
|
||||
The behavior for the proxy when port 80 and 443 are exposed is as follows:
|
||||
|
||||
* If a container has a usable cert, port 80 will redirect to 443 for that container so that HTTPS
|
||||
is always preferred when available.
|
||||
* If the container does not have a usable cert, a 503 will be returned.
|
||||
|
||||
Note that in the latter case, a browser may get an connection error as no certificate is available
|
||||
to establish a connection. A self-signed or generic cert can be defined as "default.crt" and "default.key"
|
||||
which will allow a client browser to make a SSL connection (likely w/ a warning) and subsequently receive
|
||||
a 503.
|
58
nginx.tmpl
58
nginx.tmpl
|
@ -36,6 +36,7 @@ server {
|
|||
}
|
||||
|
||||
{{ range $host, $containers := groupByMulti $ "Env.VIRTUAL_HOST" "," }}
|
||||
|
||||
upstream {{ $host }} {
|
||||
{{ range $container := $containers }}
|
||||
{{ $addrLen := len $container.Addresses }}
|
||||
|
@ -65,6 +66,50 @@ upstream {{ $host }} {
|
|||
{{ end }}
|
||||
}
|
||||
|
||||
{{/* Get the first cert name defined by containers w/ the same vhost */}}
|
||||
{{ $certName := (first (groupByKeys $containers "Env.CERT_NAME")) }}
|
||||
|
||||
{{/* Get the best matching cert by name for the vhost. */}}
|
||||
{{ $vhostCert := (closest (dir "/etc/nginx/certs") (printf "%s.crt" $host))}}
|
||||
|
||||
{{/* vhostCert is actually a filename so remove any suffixes since they are added later */}}
|
||||
{{ $vhostCert := replace $vhostCert ".crt" "" -1 }}
|
||||
{{ $vhostCert := replace $vhostCert ".key" "" -1 }}
|
||||
|
||||
{{/* Use the cert specifid on the container or fallback to the best vhost match */}}
|
||||
{{ $cert := (coalesce $certName $vhostCert) }}
|
||||
|
||||
{{ if (ne $cert "") }}
|
||||
|
||||
server {
|
||||
server_name {{ $host }};
|
||||
rewrite ^(.*) https://{{ $host }}$1 permanent;
|
||||
}
|
||||
|
||||
server {
|
||||
server_name {{ $host }};
|
||||
listen 443 ssl;
|
||||
|
||||
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
|
||||
ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:AES:CAMELLIA:DES-CBC3-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!aECDH:!EDH-DSS-DES-CBC3-SHA:!EDH-RSA-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA;
|
||||
|
||||
ssl_prefer_server_ciphers on;
|
||||
ssl_session_timeout 5m;
|
||||
ssl_session_cache shared:SSL:50m;
|
||||
ssl_stapling on;
|
||||
ssl_stapling_verify on;
|
||||
|
||||
ssl_certificate /etc/nginx/certs/{{ (printf "%s.crt" $cert) }};
|
||||
ssl_certificate_key /etc/nginx/certs/{{ (printf "%s.key" $cert) }};
|
||||
|
||||
add_header Strict-Transport-Security "max-age=31536000; includeSubdomains";
|
||||
|
||||
location / {
|
||||
proxy_pass http://{{ $host }};
|
||||
}
|
||||
}
|
||||
{{ else }}
|
||||
|
||||
server {
|
||||
server_name {{ $host }};
|
||||
|
||||
|
@ -72,4 +117,17 @@ server {
|
|||
proxy_pass http://{{ $host }};
|
||||
}
|
||||
}
|
||||
|
||||
server {
|
||||
server_name {{ $host }};
|
||||
listen 443 ssl;
|
||||
return 503;
|
||||
|
||||
{{ if (and (exists "/etc/nginx/certs/default.crt") (exists "/etc/nginx/certs/default.key")) }}
|
||||
ssl_certificate /etc/nginx/certs/default.crt;
|
||||
ssl_certificate_key /etc/nginx/certs/default.key;
|
||||
{{ end }}
|
||||
}
|
||||
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
|
|
Reference in a new issue