From 5e927d4ac308a5d7bc0f5176f3503d94bcf43723 Mon Sep 17 00:00:00 2001 From: David Li Date: Tue, 29 Sep 2015 18:05:56 -0400 Subject: [PATCH] feat(ssl): Allow using .pem for public key file Try using $cert.pem as the certificate before falling back to $cert.crt, as .pem is the standard file extension for certificates. (RFC1421, RFC1424). This is different from the current behaviour, where only the .crt is used. NOTE: This could cause a regression if users have both a .pem and a .crt file in the /etc/nginx/certs directory. In that situation, the .pem will be used instead of the .crt, which can be problematic if the files contain different information (i.e. one contains the entire certificate chain, while the other does not). If this is an issue, the order can be changed so that the current behaviour is default. Signed-off-by: David Li --- README.md | 19 +++++++++++-------- nginx.tmpl | 30 +++++++++++++++++++++++------- 2 files changed, 34 insertions(+), 15 deletions(-) diff --git a/README.md b/README.md index b4b1df7..da83108 100644 --- a/README.md +++ b/README.md @@ -81,9 +81,10 @@ 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:ro 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. +hosts in use. The certificate and keys should be named after the virtual host with either a `.pem` or +`.crt` extension for certificates, and a `.key` extension for keys. If both `.pem` and `.crt` files +exist, then the `.pem` file is used. For example, a container with `VIRTUAL_HOST=foo.bar.com` should have either a +`foo.bar.com.pem` or `foo.bar.com.crt` file, and a `foo.bar.com.key` file in the certs directory. #### Diffie-Hellman Groups @@ -93,14 +94,16 @@ should have a `foo.bar.com.dhparam.pem` file in the certs directory. #### Wildcard Certificates -Wildcard certificates and keys should be name after the domain name with a `.crt` and `.key` extension. -For example `VIRTUAL_HOST=foo.bar.com` would use cert name `bar.com.crt` and `bar.com.key`. +Wildcard certificates and keys should be name after the domain name with either a `.pem` or +`.crt` extension for certificates, and a `.key` extension for keys. If both `.pem` and `.crt` files +exist, then the `.pem` file is used. For example `VIRTUAL_HOST=foo.bar.com` would use cert name `bar.com.pem` +and `bar.com.key`. #### SNI If your certificate(s) supports multiple domain names, you can start a container with `CERT_NAME=` to identify the certificate to be used. For example, a certificate for `*.foo.com` and `*.bar.com` -could be named `shared.crt` and `shared.key`. A container running with `VIRTUAL_HOST=foo.bar.com` +could be named `shared.pem` (or `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 @@ -117,9 +120,9 @@ 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 named `default.crt` and `default.key` +to establish a connection. A self-signed or generic cert named `default.pem` and `default.key` will allow a client browser to make a SSL connection (likely w/ a warning) and subsequently receive -a 503. +a 503. A `default.crt` file will be used if `default.pem` is not found. ### Basic Authentication Support diff --git a/nginx.tmpl b/nginx.tmpl index 08f6c01..4377237 100644 --- a/nginx.tmpl +++ b/nginx.tmpl @@ -58,13 +58,18 @@ server { return 503; } -{{ if (and (exists "/etc/nginx/certs/default.crt") (exists "/etc/nginx/certs/default.key")) }} +{{ if (and (or (exists "/etc/nginx/certs/default.pem") (exists "/etc/nginx/certs/default.crt")) (exists "/etc/nginx/certs/default.key")) }} server { server_name _; # This is just an invalid value which will never trigger on a real hostname. listen 443 ssl spdy; return 503; - ssl_certificate /etc/nginx/certs/default.crt; + {{ if (exists "/etc/nginx/certs/default.pem") }} + ssl_certificate /etc/nginx/certs/default.pem; + {{ else }} + ssl_certificate /etc/nginx/certs/default.crt; + {{ end }} + ssl_certificate_key /etc/nginx/certs/default.key; } {{ end }} @@ -97,16 +102,17 @@ upstream {{ $host }} { {{ $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 := (closest (dir "/etc/nginx/certs") (printf "%s.key" $host))}} -{{/* vhostCert is actually a filename so remove any suffixes since they are added later */}} +{{/* vhostCert is actually a filename so remove any suffixes since they are added later. */}} {{ $vhostCert := replace $vhostCert ".crt" "" -1 }} +{{ $vhostCert := replace $vhostCert ".pem" "" -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 (and (ne $cert "") (exists (printf "/etc/nginx/certs/%s.crt" $cert)) (exists (printf "/etc/nginx/certs/%s.key" $cert))) }} +{{ if (and (ne $cert "") (or (exists (printf "/etc/nginx/certs/%s.pem" $cert)) (exists (printf "/etc/nginx/certs/%s.crt" $cert))) (exists (printf "/etc/nginx/certs/%s.key" $cert))) }} server { server_name {{ $host }}; @@ -127,7 +133,12 @@ server { ssl_session_timeout 5m; ssl_session_cache shared:SSL:50m; + {{ if (exists (printf "/etc/nginx/certs/%s.pem" $cert)) }} + ssl_certificate /etc/nginx/certs/{{ (printf "%s.pem" $cert) }}; + {{ else }} ssl_certificate /etc/nginx/certs/{{ (printf "%s.crt" $cert) }}; + {{ end }} + ssl_certificate_key /etc/nginx/certs/{{ (printf "%s.key" $cert) }}; {{ if (exists (printf "/etc/nginx/certs/%s.dhparam.pem" $cert)) }} @@ -182,14 +193,19 @@ server { } } -{{ if (and (exists "/etc/nginx/certs/default.crt") (exists "/etc/nginx/certs/default.key")) }} +{{ if (and (or (exists "/etc/nginx/certs/default.pem") (exists "/etc/nginx/certs/default.crt")) (exists "/etc/nginx/certs/default.key")) }} server { server_name {{ $host }}; listen 443 ssl spdy {{ $default_server }}; access_log /var/log/nginx/access.log vhost; return 503; - ssl_certificate /etc/nginx/certs/default.crt; + {{ if (exists "/etc/nginx/certs/default.pem") }} + ssl_certificate /etc/nginx/certs/default.pem; + {{ else }} + ssl_certificate /etc/nginx/certs/default.crt; + {{ end }} + ssl_certificate_key /etc/nginx/certs/default.key; } {{ end }}