From bc56da5224011f3336b67e796ded116c55786678 Mon Sep 17 00:00:00 2001 From: David Parrish Date: Mon, 16 Nov 2015 01:28:47 -0500 Subject: [PATCH 01/42] Add letsencryptclient and configuration file --- Dockerfile | 6 ++++++ letsencrypt.ini | 24 ++++++++++++++++++++++++ 2 files changed, 30 insertions(+) create mode 100644 letsencrypt.ini diff --git a/Dockerfile b/Dockerfile index 4111003..7d4aaeb 100644 --- a/Dockerfile +++ b/Dockerfile @@ -6,9 +6,15 @@ RUN apt-get update \ && apt-get install -y -q --no-install-recommends \ ca-certificates \ wget \ + git \ && apt-get clean \ && rm -r /var/lib/apt/lists/* +# Get Let's Encrypt client +RUN git -C /opt clone https://github.com/letsencrypt/letsencrypt +#RUN cd /opt/letsencrypt && ./letsencrypt-auto +COPY letsencrypt.ini /etc/letsencrypt/cli.ini + # Configure Nginx and apply fix for very long server names RUN echo "daemon off;" >> /etc/nginx/nginx.conf \ && sed -i 's/^http {/&\n server_names_hash_bucket_size 128;/g' /etc/nginx/nginx.conf diff --git a/letsencrypt.ini b/letsencrypt.ini new file mode 100644 index 0000000..52309f0 --- /dev/null +++ b/letsencrypt.ini @@ -0,0 +1,24 @@ +# This is an example of the kind of things you can do in a configuration file. +# All flags used by the client can be configured here. Run Let's Encrypt with +# "--help" to learn more about the available options. + +# Use a 4096 bit RSA key instead of 2048 +rsa-key-size = 4096 + +# Always use the staging/testing server +server = https://acme-staging.api.letsencrypt.org/directory + +# Uncomment and update to register with the specified e-mail address +# email = foo@example.com + +# Uncomment to use a text interface instead of ncurses +text = True + +# Uncomment to use the standalone authenticator on port 443 +# authenticator = standalone +# standalone-supported-challenges = tls-sni-01 + +# Uncomment to use the webroot authenticator. Replace webroot-path with the +# path to the public_html / webroot folder being served by your web server. +authenticator = webroot +webroot-path = /usr/share/nginx/html From 752687a6a6fb82e9613ccd761100126dfa4b4d31 Mon Sep 17 00:00:00 2001 From: David Parrish Date: Wed, 18 Nov 2015 15:42:21 -0500 Subject: [PATCH 02/42] Add letsencrypt service and configuration to access .well-known directory --- Dockerfile | 11 ++++++++--- Procfile | 1 + letsencrypt_service | 31 +++++++++++++++++++++++++++++++ nginx.tmpl | 20 ++++++++++++++++++++ 4 files changed, 60 insertions(+), 3 deletions(-) create mode 100755 letsencrypt_service diff --git a/Dockerfile b/Dockerfile index 7d4aaeb..29e4cec 100644 --- a/Dockerfile +++ b/Dockerfile @@ -10,10 +10,14 @@ RUN apt-get update \ && apt-get clean \ && rm -r /var/lib/apt/lists/* -# Get Let's Encrypt client +# Get Let's Encrypt client source RUN git -C /opt clone https://github.com/letsencrypt/letsencrypt -#RUN cd /opt/letsencrypt && ./letsencrypt-auto -COPY letsencrypt.ini /etc/letsencrypt/cli.ini +# Install letsencrypt +RUN cd /opt/letsencrypt && ./letsencrypt-auto --help + +# Testing directory +RUN mkdir -p /usr/share/nginx/html/.well-known \ + && touch /usr/share/nginx/html/.well-known/testing # Configure Nginx and apply fix for very long server names RUN echo "daemon off;" >> /etc/nginx/nginx.conf \ @@ -35,6 +39,7 @@ WORKDIR /app/ ENV DOCKER_HOST unix:///tmp/docker.sock VOLUME ["/etc/nginx/certs"] +VOLUME ["/etc/letsencrypt"] ENTRYPOINT ["/app/docker-entrypoint.sh"] CMD ["forego", "start", "-r"] diff --git a/Procfile b/Procfile index 8547156..24198b0 100644 --- a/Procfile +++ b/Procfile @@ -1,2 +1,3 @@ nginx: nginx dockergen: docker-gen -watch -only-exposed -notify "nginx -s reload" /app/nginx.tmpl /etc/nginx/conf.d/default.conf +letsencrypt: /app/letsencrypt_service diff --git a/letsencrypt_service b/letsencrypt_service new file mode 100755 index 0000000..5ea66a7 --- /dev/null +++ b/letsencrypt_service @@ -0,0 +1,31 @@ +#!/bin/bash + +echo 'Waiting' +sleep 10 + +# Wait some amount of time +seconds_to_wait=100; +while true; do + # for each configuration file, + for f in "/etc/letsencrypt/*.ini"; do + [[ -f "$f" ]] || continue + echo "letsencrypt ${f%.ini}" + domain="${f%.ini}" + # Wait until the threshold is reached for renewing certificate + # cat /etc/nginx/certs/ftl3.local.crt | openssl x509 -noout -dates + + # Or if the certificate doesn't exist + + /opt/letsencrypt/letsencrypt-auto certonly --authenticator webroot \ + --webroot-path /usr/share/nginx/html -d $domain + done + date + sleep $seconds_to_wait +done + +# Date difference in days +datediff() { + d1=$(date -d "$1" +%s) + d2=$(date -d "$2" +%s) + echo $(( (d1 - d2) / 86400 )) +} diff --git a/nginx.tmpl b/nginx.tmpl index 255cc35..a08ed36 100644 --- a/nginx.tmpl +++ b/nginx.tmpl @@ -143,7 +143,17 @@ server { include /etc/nginx/vhost.d/default; {{ end }} + location /.well-known/ { + root /usr/share/nginx/html; + try_files $uri @proxy_pass; + } + + # Redirect hack. See: http://stackoverflow.com/a/20694873/350221 location / { + error_page 418 = @proxy_pass; return 418; + } + + location @proxy_pass { proxy_pass {{ trim $proto }}://{{ trim $host }}; {{ if (exists (printf "/etc/nginx/htpasswd/%s" $host)) }} auth_basic "Restricted {{ $host }}"; @@ -169,7 +179,17 @@ server { include /etc/nginx/vhost.d/default; {{ end }} + location /.well-known/ { + root /usr/share/nginx/html; + try_files $uri @proxy_pass; + } + + # Redirect hack. See: http://stackoverflow.com/a/20694873/350221 location / { + error_page 418 = @proxy_pass; return 418; + } + + location @proxy_pass { proxy_pass {{ trim $proto }}://{{ trim $host }}; {{ if (exists (printf "/etc/nginx/htpasswd/%s" $host)) }} auth_basic "Restricted {{ $host }}"; From b89af421f6bf4610b4c02f5cf32477ac264c4148 Mon Sep 17 00:00:00 2001 From: David Parrish Date: Sat, 21 Nov 2015 00:27:45 -0500 Subject: [PATCH 03/42] Use simp_le client. Use docker-gen to gather data for simp_le --- Dockerfile | 11 +++++++-- Procfile | 1 + letsencrypt_service | 45 +++++++++++++++++++++-------------- letsencrypt_service_data.tmpl | 10 ++++++++ 4 files changed, 47 insertions(+), 20 deletions(-) create mode 100644 letsencrypt_service_data.tmpl diff --git a/Dockerfile b/Dockerfile index 29e4cec..eb65b94 100644 --- a/Dockerfile +++ b/Dockerfile @@ -11,9 +11,16 @@ RUN apt-get update \ && rm -r /var/lib/apt/lists/* # Get Let's Encrypt client source -RUN git -C /opt clone https://github.com/letsencrypt/letsencrypt +#RUN git -C /opt clone https://github.com/letsencrypt/letsencrypt +# Get Let's Encrypt simp_le client source +RUN git -C /opt clone https://github.com/kuba/simp_le.git # Install letsencrypt -RUN cd /opt/letsencrypt && ./letsencrypt-auto --help +#RUN cd /opt/letsencrypt && ./letsencrypt-auto --help +# Install simp_le +RUN cd /opt/simp_le && ./bootstrap.sh && ./venv.sh +#&& \ +#RUN /opt/simp_le/venv.sh +# . venv/bin/activate # Testing directory RUN mkdir -p /usr/share/nginx/html/.well-known \ diff --git a/Procfile b/Procfile index 24198b0..e18d1d3 100644 --- a/Procfile +++ b/Procfile @@ -1,3 +1,4 @@ nginx: nginx dockergen: docker-gen -watch -only-exposed -notify "nginx -s reload" /app/nginx.tmpl /etc/nginx/conf.d/default.conf +letsencrypt_dockergen: docker-gen -watch -only-exposed /app/letsencrypt_service_data.tmpl /app/letsencrypt_service_data letsencrypt: /app/letsencrypt_service diff --git a/letsencrypt_service b/letsencrypt_service index 5ea66a7..ab10618 100755 --- a/letsencrypt_service +++ b/letsencrypt_service @@ -1,31 +1,40 @@ #!/bin/bash +DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" echo 'Waiting' sleep 10 # Wait some amount of time -seconds_to_wait=100; +seconds_to_wait=10; while true; do - # for each configuration file, - for f in "/etc/letsencrypt/*.ini"; do - [[ -f "$f" ]] || continue - echo "letsencrypt ${f%.ini}" - domain="${f%.ini}" + # Load relevant conatiner settings + source $DIR/letsencrypt_service_data + + for lec in "${LETSENCRYPT_CONTAINERS[@]}"; do + host_varname="LETSENCRYPT_""$lec""_HOST" + # Array variable indirection hack: http://stackoverflow.com/a/25880676/350221 + hosts_array=$host_varname[@]; echo ${!hosts_array} + + email_varname="LETSENCRYPT_""$lec""_EMAIL"; echo ${!email_varname} # Wait until the threshold is reached for renewing certificate # cat /etc/nginx/certs/ftl3.local.crt | openssl x509 -noout -dates # Or if the certificate doesn't exist - /opt/letsencrypt/letsencrypt-auto certonly --authenticator webroot \ - --webroot-path /usr/share/nginx/html -d $domain - done - date - sleep $seconds_to_wait -done + domain_params="" + for domain in "${!hosts_array}"; do + domain_params+="-d $domain " + done -# Date difference in days -datediff() { - d1=$(date -d "$1" +%s) - d2=$(date -d "$2" +%s) - echo $(( (d1 - d2) / 86400 )) -} + /opt/simp_le/venv/bin/simp_le $domain_params -f fullchain.pem -f key.pem --email ${!email_varname} --default_root /usr/share/nginx/html/ + + # Copy certificates into /etc/nginx/certs + #cp /etc/letsencrypt/live/ + + unset $host_varname; unset $email_varname; unset $hosts_array + done + unset LETSENCRYPT_CONTAINERS + + date + echo "Waiting $seconds_to_wait seconds"; sleep $seconds_to_wait +done diff --git a/letsencrypt_service_data.tmpl b/letsencrypt_service_data.tmpl new file mode 100644 index 0000000..32133c1 --- /dev/null +++ b/letsencrypt_service_data.tmpl @@ -0,0 +1,10 @@ +LETSENCRYPT_CONTAINERS=({{ range $host, $containers := groupBy $ "Env.LETSENCRYPT_HOST" }}{{ range $container := $containers }} '{{ $container.ID }}' {{ end }}{{ end }}) + +{{ range $hosts, $containers := groupBy $ "Env.LETSENCRYPT_HOST" }} + +{{ range $container := $containers }} +LETSENCRYPT_{{ $container.ID }}_HOST=( {{ range $host := split $hosts " " }}'{{ $host }}' {{ end }}) +LETSENCRYPT_{{ $container.ID }}_EMAIL="{{ $container.Env.LETSENCRYPT_EMAIL }}" +{{ end }} + +{{ end }} From cca8c2d5cde3e61f05a5e6508af4e07afc387746 Mon Sep 17 00:00:00 2001 From: David Parrish Date: Sat, 21 Nov 2015 17:52:31 -0500 Subject: [PATCH 04/42] Use simp_le to update certificates and link them to the /etc/nginx/certs directory --- letsencrypt_service | 28 ++++++++++++++++++---------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/letsencrypt_service b/letsencrypt_service index ab10618..080a87e 100755 --- a/letsencrypt_service +++ b/letsencrypt_service @@ -5,31 +5,39 @@ echo 'Waiting' sleep 10 # Wait some amount of time -seconds_to_wait=10; +seconds_to_wait=3600; while true; do # Load relevant conatiner settings source $DIR/letsencrypt_service_data for lec in "${LETSENCRYPT_CONTAINERS[@]}"; do + # Derive host and email variable names host_varname="LETSENCRYPT_""$lec""_HOST" # Array variable indirection hack: http://stackoverflow.com/a/25880676/350221 - hosts_array=$host_varname[@]; echo ${!hosts_array} - - email_varname="LETSENCRYPT_""$lec""_EMAIL"; echo ${!email_varname} - # Wait until the threshold is reached for renewing certificate - # cat /etc/nginx/certs/ftl3.local.crt | openssl x509 -noout -dates - - # Or if the certificate doesn't exist + hosts_array=$host_varname[@] + email_varname="LETSENCRYPT_""$lec""_EMAIL" domain_params="" for domain in "${!hosts_array}"; do domain_params+="-d $domain " done + # Use the first domain to create the directory + primary_domain=${!host_varname} + mkdir -p /etc/nginx/certs/$primary_domain + cd /etc/nginx/certs/$primary_domain /opt/simp_le/venv/bin/simp_le $domain_params -f fullchain.pem -f key.pem --email ${!email_varname} --default_root /usr/share/nginx/html/ + simp_le_return=$? + cd /app - # Copy certificates into /etc/nginx/certs - #cp /etc/letsencrypt/live/ + # Symlink to created certificate and key. + for domain in "${!hosts_array}"; do + ln -s /etc/nginx/certs/$primary_domain/fullchain.pem /etc/nginx/certs/$domain".crt" + ln -s /etc/nginx/certs/$primary_domain/key.pem /etc/nginx/certs/$domain".key" + done + + # TODO: Regenerate nginx config if simp_le created a certificate and key + #if [ "$simp_le_return" -eq 0 ]; then nginx -s reload; fi unset $host_varname; unset $email_varname; unset $hosts_array done From dbafbd184fe183e06bb2e348a218e73f549d9f98 Mon Sep 17 00:00:00 2001 From: David Parrish Date: Sat, 21 Nov 2015 18:02:23 -0500 Subject: [PATCH 05/42] Update README.md Add Let's Encrypt documentation to README.md --- README.md | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/README.md b/README.md index 9d4bb40..6521fc1 100644 --- a/README.md +++ b/README.md @@ -121,6 +121,19 @@ to establish a connection. A self-signed or generic cert named `default.crt` an will allow a client browser to make a SSL connection (likely w/ a warning) and subsequently receive a 503. +#### Let's Encrypt + +Use the Let's Encrypt service to automatically create a valid certificate for a virtual host. + +Set the following environment variables to enable Let's Encrypt support. + +- `LETSENCRYPT_HOST` +- `LETSENCRYPT_EMAIL` + +The `LETSENCRYPT_HOST` variable most likely needs to be the same as the `VIRTUAL_HOSTS` variable and must be publicly reachable domains. Specify multiple hosts with a space delemiter. + +After the first start, the nginx-proxy will need to be restarted again. This is because the nginx configuration needs to be regenerated after downloading the Let's Encrypt certificate. + ### Basic Authentication Support In order to be able to secure your virtual host, you have to create a file named as its equivalent VIRTUAL_HOST variable on directory From 24d7fe08849ed0d919b77b523e7673ac2a17c3dc Mon Sep 17 00:00:00 2001 From: David Parrish Date: Sat, 21 Nov 2015 18:05:18 -0500 Subject: [PATCH 06/42] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 6521fc1..7fbe9c7 100644 --- a/README.md +++ b/README.md @@ -125,7 +125,7 @@ a 503. Use the Let's Encrypt service to automatically create a valid certificate for a virtual host. -Set the following environment variables to enable Let's Encrypt support. +Set the following environment variables to enable Let's Encrypt support for a container being proxied. - `LETSENCRYPT_HOST` - `LETSENCRYPT_EMAIL` From dafe85ac947954759c8bf07ea9a620b1f0af9179 Mon Sep 17 00:00:00 2001 From: David Parrish Date: Sat, 21 Nov 2015 18:05:59 -0500 Subject: [PATCH 07/42] Remove unneeded file --- letsencrypt.ini | 24 ------------------------ 1 file changed, 24 deletions(-) delete mode 100644 letsencrypt.ini diff --git a/letsencrypt.ini b/letsencrypt.ini deleted file mode 100644 index 52309f0..0000000 --- a/letsencrypt.ini +++ /dev/null @@ -1,24 +0,0 @@ -# This is an example of the kind of things you can do in a configuration file. -# All flags used by the client can be configured here. Run Let's Encrypt with -# "--help" to learn more about the available options. - -# Use a 4096 bit RSA key instead of 2048 -rsa-key-size = 4096 - -# Always use the staging/testing server -server = https://acme-staging.api.letsencrypt.org/directory - -# Uncomment and update to register with the specified e-mail address -# email = foo@example.com - -# Uncomment to use a text interface instead of ncurses -text = True - -# Uncomment to use the standalone authenticator on port 443 -# authenticator = standalone -# standalone-supported-challenges = tls-sni-01 - -# Uncomment to use the webroot authenticator. Replace webroot-path with the -# path to the public_html / webroot folder being served by your web server. -authenticator = webroot -webroot-path = /usr/share/nginx/html From 51920bef7ce4b311ebb0492c5f19e32ee9a9254c Mon Sep 17 00:00:00 2001 From: David Parrish Date: Sat, 21 Nov 2015 18:47:28 -0500 Subject: [PATCH 08/42] Remove unneeded VOLUME from Dockerfile --- Dockerfile | 1 - 1 file changed, 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index eb65b94..c274be2 100644 --- a/Dockerfile +++ b/Dockerfile @@ -46,7 +46,6 @@ WORKDIR /app/ ENV DOCKER_HOST unix:///tmp/docker.sock VOLUME ["/etc/nginx/certs"] -VOLUME ["/etc/letsencrypt"] ENTRYPOINT ["/app/docker-entrypoint.sh"] CMD ["forego", "start", "-r"] From 98f43a905a57341253156d8c1ec55e57b251313a Mon Sep 17 00:00:00 2001 From: David Parrish Date: Sat, 21 Nov 2015 18:50:32 -0500 Subject: [PATCH 09/42] Clean up Dockerfile. Remove comments --- Dockerfile | 7 ------- 1 file changed, 7 deletions(-) diff --git a/Dockerfile b/Dockerfile index c274be2..de9c7f0 100644 --- a/Dockerfile +++ b/Dockerfile @@ -10,17 +10,10 @@ RUN apt-get update \ && apt-get clean \ && rm -r /var/lib/apt/lists/* -# Get Let's Encrypt client source -#RUN git -C /opt clone https://github.com/letsencrypt/letsencrypt # Get Let's Encrypt simp_le client source RUN git -C /opt clone https://github.com/kuba/simp_le.git -# Install letsencrypt -#RUN cd /opt/letsencrypt && ./letsencrypt-auto --help # Install simp_le RUN cd /opt/simp_le && ./bootstrap.sh && ./venv.sh -#&& \ -#RUN /opt/simp_le/venv.sh -# . venv/bin/activate # Testing directory RUN mkdir -p /usr/share/nginx/html/.well-known \ From 7f85f7c4af15f2575dda678fe796de9507cf78b5 Mon Sep 17 00:00:00 2001 From: JrCs <90z7oey02@sneakemail.com> Date: Sun, 22 Nov 2015 10:04:15 +0100 Subject: [PATCH 10/42] Avoid displaying unecessary errors Avoid 'ln: failed to create symbolic link' errors --- letsencrypt_service | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/letsencrypt_service b/letsencrypt_service index 080a87e..a230f5f 100755 --- a/letsencrypt_service +++ b/letsencrypt_service @@ -32,8 +32,8 @@ while true; do # Symlink to created certificate and key. for domain in "${!hosts_array}"; do - ln -s /etc/nginx/certs/$primary_domain/fullchain.pem /etc/nginx/certs/$domain".crt" - ln -s /etc/nginx/certs/$primary_domain/key.pem /etc/nginx/certs/$domain".key" + ln -sf ./$primary_domain/fullchain.pem /etc/nginx/certs/$domain".crt" + ln -sf ./$primary_domain/key.pem /etc/nginx/certs/$domain".key" done # TODO: Regenerate nginx config if simp_le created a certificate and key From 1ee83cc0f651dff9ab2dbc0bfd4e31f55d753fdb Mon Sep 17 00:00:00 2001 From: JrCs <90z7oey02@sneakemail.com> Date: Sun, 22 Nov 2015 12:19:27 +0100 Subject: [PATCH 11/42] Get real production certificates Update server URL to use the production ready API URL. --- letsencrypt_service | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/letsencrypt_service b/letsencrypt_service index a230f5f..4c0f460 100755 --- a/letsencrypt_service +++ b/letsencrypt_service @@ -26,7 +26,9 @@ while true; do primary_domain=${!host_varname} mkdir -p /etc/nginx/certs/$primary_domain cd /etc/nginx/certs/$primary_domain - /opt/simp_le/venv/bin/simp_le $domain_params -f fullchain.pem -f key.pem --email ${!email_varname} --default_root /usr/share/nginx/html/ + /opt/simp_le/venv/bin/simp_le $domain_params -f fullchain.pem -f key.pem --email ${!email_varname} \ + --server=https://acme-v01.api.letsencrypt.org/directory \ + --default_root /usr/share/nginx/html/ simp_le_return=$? cd /app From b8b4d385beea1a79cdd1802dc9a80687e070a34b Mon Sep 17 00:00:00 2001 From: David Parrish Date: Sun, 22 Nov 2015 17:26:49 -0500 Subject: [PATCH 12/42] Remove semicolon. Spelling fix. Variable name change. --- letsencrypt_service | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/letsencrypt_service b/letsencrypt_service index 4c0f460..5ac5864 100755 --- a/letsencrypt_service +++ b/letsencrypt_service @@ -5,17 +5,17 @@ echo 'Waiting' sleep 10 # Wait some amount of time -seconds_to_wait=3600; +seconds_to_wait=3600 while true; do - # Load relevant conatiner settings + # Load relevant container settings source $DIR/letsencrypt_service_data - for lec in "${LETSENCRYPT_CONTAINERS[@]}"; do + for cid in "${LETSENCRYPT_CONTAINERS[@]}"; do # Derive host and email variable names - host_varname="LETSENCRYPT_""$lec""_HOST" + host_varname="LETSENCRYPT_${cid}_HOST" # Array variable indirection hack: http://stackoverflow.com/a/25880676/350221 hosts_array=$host_varname[@] - email_varname="LETSENCRYPT_""$lec""_EMAIL" + email_varname="LETSENCRYPT_${cid}_EMAIL" domain_params="" for domain in "${!hosts_array}"; do From 5bcb1956a80b48591463cadf88cab583f2abb32f Mon Sep 17 00:00:00 2001 From: JrCs <90z7oey02@sneakemail.com> Date: Sun, 22 Nov 2015 13:20:29 +0100 Subject: [PATCH 13/42] Fix multi-domain support --- letsencrypt_service | 49 +++++++++++++++++++++++---------------------- 1 file changed, 25 insertions(+), 24 deletions(-) diff --git a/letsencrypt_service b/letsencrypt_service index 5ac5864..17c74d3 100755 --- a/letsencrypt_service +++ b/letsencrypt_service @@ -1,4 +1,5 @@ #!/bin/bash + DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" echo 'Waiting' @@ -6,9 +7,10 @@ sleep 10 # Wait some amount of time seconds_to_wait=3600 + while true; do # Load relevant container settings - source $DIR/letsencrypt_service_data + source "$DIR"/letsencrypt_service_data for cid in "${LETSENCRYPT_CONTAINERS[@]}"; do # Derive host and email variable names @@ -17,31 +19,30 @@ while true; do hosts_array=$host_varname[@] email_varname="LETSENCRYPT_${cid}_EMAIL" - domain_params="" for domain in "${!hosts_array}"; do - domain_params+="-d $domain " + + # Create the domain directory + mkdir -p /etc/nginx/certs/$domain + cd /etc/nginx/certs/$domain + + /opt/simp_le/venv/bin/simp_le \ + -d "$domain" \ + -f fullchain.pem -f key.pem \ + --email "${!email_varname}" \ + --server=https://acme-v01.api.letsencrypt.org/directory \ + --default_root /usr/share/nginx/html/ + + simp_le_return=$? + + if [[ $simp_le_return -eq 0 ]]; then + # Symlink to created certificate and key. + ln -sf ./$domain/fullchain.pem /etc/nginx/certs/$domain".crt" + ln -sf ./$domain/key.pem /etc/nginx/certs/$domain".key" + fi + + # TODO: Regenerate nginx config if simp_le created a certificate and key + #if [ "$simp_le_return" -eq 0 ]; then nginx -s reload; fi done - - # Use the first domain to create the directory - primary_domain=${!host_varname} - mkdir -p /etc/nginx/certs/$primary_domain - cd /etc/nginx/certs/$primary_domain - /opt/simp_le/venv/bin/simp_le $domain_params -f fullchain.pem -f key.pem --email ${!email_varname} \ - --server=https://acme-v01.api.letsencrypt.org/directory \ - --default_root /usr/share/nginx/html/ - simp_le_return=$? - cd /app - - # Symlink to created certificate and key. - for domain in "${!hosts_array}"; do - ln -sf ./$primary_domain/fullchain.pem /etc/nginx/certs/$domain".crt" - ln -sf ./$primary_domain/key.pem /etc/nginx/certs/$domain".key" - done - - # TODO: Regenerate nginx config if simp_le created a certificate and key - #if [ "$simp_le_return" -eq 0 ]; then nginx -s reload; fi - - unset $host_varname; unset $email_varname; unset $hosts_array done unset LETSENCRYPT_CONTAINERS From 1a4422ecb37ecc10db351528783fce79f05c23f6 Mon Sep 17 00:00:00 2001 From: JrCs <90z7oey02@sneakemail.com> Date: Sun, 22 Nov 2015 16:34:28 +0100 Subject: [PATCH 14/42] Enhance update of certificates Update or create the certificates as soon as possible --- Procfile | 5 ++- letsencrypt_service | 78 ++++++++++++++++++++++++--------------------- update_certs | 3 ++ update_nginx | 8 +++++ 4 files changed, 55 insertions(+), 39 deletions(-) create mode 100755 update_certs create mode 100755 update_nginx diff --git a/Procfile b/Procfile index e18d1d3..e76aad9 100644 --- a/Procfile +++ b/Procfile @@ -1,4 +1,3 @@ -nginx: nginx -dockergen: docker-gen -watch -only-exposed -notify "nginx -s reload" /app/nginx.tmpl /etc/nginx/conf.d/default.conf -letsencrypt_dockergen: docker-gen -watch -only-exposed /app/letsencrypt_service_data.tmpl /app/letsencrypt_service_data +nginx: /usr/sbin/nginx +dockergen: /usr/local/bin/docker-gen -watch -only-exposed -notify "/app/update_nginx" /app/nginx.tmpl /etc/nginx/conf.d/default.conf letsencrypt: /app/letsencrypt_service diff --git a/letsencrypt_service b/letsencrypt_service index 17c74d3..b0f240b 100755 --- a/letsencrypt_service +++ b/letsencrypt_service @@ -2,50 +2,56 @@ DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" -echo 'Waiting' -sleep 10 - -# Wait some amount of time seconds_to_wait=3600 -while true; do - # Load relevant container settings - source "$DIR"/letsencrypt_service_data +update_certs() { + [[ ! -f "$DIR"/letsencrypt_service_data ]] && return - for cid in "${LETSENCRYPT_CONTAINERS[@]}"; do - # Derive host and email variable names - host_varname="LETSENCRYPT_${cid}_HOST" - # Array variable indirection hack: http://stackoverflow.com/a/25880676/350221 - hosts_array=$host_varname[@] - email_varname="LETSENCRYPT_${cid}_EMAIL" + # Load relevant container settings + source "$DIR"/letsencrypt_service_data - for domain in "${!hosts_array}"; do + for cid in "${LETSENCRYPT_CONTAINERS[@]}"; do + # Derive host and email variable names + host_varname="LETSENCRYPT_${cid}_HOST" + # Array variable indirection hack: http://stackoverflow.com/a/25880676/350221 + hosts_array=$host_varname[@] + email_varname="LETSENCRYPT_${cid}_EMAIL" - # Create the domain directory - mkdir -p /etc/nginx/certs/$domain - cd /etc/nginx/certs/$domain + for domain in "${!hosts_array}"; do - /opt/simp_le/venv/bin/simp_le \ - -d "$domain" \ - -f fullchain.pem -f key.pem \ - --email "${!email_varname}" \ - --server=https://acme-v01.api.letsencrypt.org/directory \ - --default_root /usr/share/nginx/html/ + # Create the domain directory + mkdir -p /etc/nginx/certs/$domain + cd /etc/nginx/certs/$domain - simp_le_return=$? + /opt/simp_le/venv/bin/simp_le \ + -d "$domain" \ + -f fullchain.pem -f key.pem \ + --email "${!email_varname}" \ + --server=https://acme-v01.api.letsencrypt.org/directory \ + --default_root /usr/share/nginx/html/ - if [[ $simp_le_return -eq 0 ]]; then - # Symlink to created certificate and key. - ln -sf ./$domain/fullchain.pem /etc/nginx/certs/$domain".crt" - ln -sf ./$domain/key.pem /etc/nginx/certs/$domain".key" - fi + simp_le_return=$? - # TODO: Regenerate nginx config if simp_le created a certificate and key - #if [ "$simp_le_return" -eq 0 ]; then nginx -s reload; fi + if [[ $simp_le_return -eq 0 ]]; then + # Symlink to created certificate and key. + ln -sf ./$domain/fullchain.pem /etc/nginx/certs/$domain".crt" + ln -sf ./$domain/key.pem /etc/nginx/certs/$domain".key" + fi + done done - done - unset LETSENCRYPT_CONTAINERS + unset LETSENCRYPT_CONTAINERS +} - date - echo "Waiting $seconds_to_wait seconds"; sleep $seconds_to_wait -done +pid= +trap '[[ $pid ]] && kill $pid; exec $0' EXIT +trap 'trap - EXIT' INT TERM + +echo 'Waiting 10s before updating certs...' +sleep 10 + +update_certs + +# Wait some amount of time +sleep $seconds_to_wait & pid=$! +wait +pid= diff --git a/update_certs b/update_certs new file mode 100755 index 0000000..40fc0e6 --- /dev/null +++ b/update_certs @@ -0,0 +1,3 @@ +#!/bin/bash + +pkill -f -SIGUSR1 /app/letsencrypt_service diff --git a/update_nginx b/update_nginx new file mode 100755 index 0000000..91c10e9 --- /dev/null +++ b/update_nginx @@ -0,0 +1,8 @@ +#!/bin/bash + +docker-gen \ + -only-exposed \ + -notify '/app/update_certs' \ + /app/letsencrypt_service_data.tmpl /app/letsencrypt_service_data + +nginx -s reload From 81fc6925120f35cb4fabd345b4609aa6bdefcea6 Mon Sep 17 00:00:00 2001 From: David Parrish Date: Mon, 23 Nov 2015 00:03:14 -0500 Subject: [PATCH 15/42] Update README.md Spelling --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 7fbe9c7..3627b65 100644 --- a/README.md +++ b/README.md @@ -130,7 +130,7 @@ Set the following environment variables to enable Let's Encrypt support for a co - `LETSENCRYPT_HOST` - `LETSENCRYPT_EMAIL` -The `LETSENCRYPT_HOST` variable most likely needs to be the same as the `VIRTUAL_HOSTS` variable and must be publicly reachable domains. Specify multiple hosts with a space delemiter. +The `LETSENCRYPT_HOST` variable most likely needs to be the same as the `VIRTUAL_HOSTS` variable and must be publicly reachable domains. Specify multiple hosts with a space delimiter. After the first start, the nginx-proxy will need to be restarted again. This is because the nginx configuration needs to be regenerated after downloading the Let's Encrypt certificate. From a610fb1e3978a99270c316032591fa7e5d2fca82 Mon Sep 17 00:00:00 2001 From: David Parrish Date: Mon, 23 Nov 2015 00:03:14 -0500 Subject: [PATCH 16/42] Use jwilder/nginx-proxy as base image and reduce final image size --- .dockerignore | 2 ++ Dockerfile | 43 +++---------------------------------------- build.sh | 28 ++++++++++++++++++++++++++++ docker-entrypoint.sh | 22 ---------------------- letsencrypt_service | 2 +- 5 files changed, 34 insertions(+), 63 deletions(-) create mode 100755 build.sh delete mode 100755 docker-entrypoint.sh diff --git a/.dockerignore b/.dockerignore index 8fafbb0..ded9598 100644 --- a/.dockerignore +++ b/.dockerignore @@ -1,6 +1,8 @@ .git .dockerignore circle.yml +Dockerfile +LICENSE Makefile README.md test diff --git a/Dockerfile b/Dockerfile index de9c7f0..b4c1c2f 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,44 +1,7 @@ -FROM nginx:1.9.6 -MAINTAINER Jason Wilder mail@jasonwilder.com +FROM jwilder/nginx-proxy -# Install wget and install/updates certificates -RUN apt-get update \ - && apt-get install -y -q --no-install-recommends \ - ca-certificates \ - wget \ - git \ - && apt-get clean \ - && rm -r /var/lib/apt/lists/* - -# Get Let's Encrypt simp_le client source -RUN git -C /opt clone https://github.com/kuba/simp_le.git -# Install simp_le -RUN cd /opt/simp_le && ./bootstrap.sh && ./venv.sh - -# Testing directory -RUN mkdir -p /usr/share/nginx/html/.well-known \ - && touch /usr/share/nginx/html/.well-known/testing - -# Configure Nginx and apply fix for very long server names -RUN echo "daemon off;" >> /etc/nginx/nginx.conf \ - && sed -i 's/^http {/&\n server_names_hash_bucket_size 128;/g' /etc/nginx/nginx.conf - -# Install Forego -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.4.2 - -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 \ - && rm /docker-gen-linux-amd64-$DOCKER_GEN_VERSION.tar.gz +MAINTAINER [ "Jason Wilder ", "Yves Blusseau <90z7oey02@sneakemail.com>" ] COPY . /app/ -WORKDIR /app/ -ENV DOCKER_HOST unix:///tmp/docker.sock - -VOLUME ["/etc/nginx/certs"] - -ENTRYPOINT ["/app/docker-entrypoint.sh"] -CMD ["forego", "start", "-r"] +RUN chmod +rx /app/build.sh && /app/build.sh && rm -f /app/build.sh diff --git a/build.sh b/build.sh new file mode 100755 index 0000000..194e16f --- /dev/null +++ b/build.sh @@ -0,0 +1,28 @@ +#!/bin/bash + +set -e + +apt-get update + +# Install python packages needed by simp_le +apt-get install -y -q --no-install-recommends python python-requests + +# Install python packages needed to build simp_le +apt-get install -y -q --no-install-recommends git gcc libssl-dev libffi-dev python-dev python-pip + +# Get Let's Encrypt simp_le client source +git -C /opt clone https://github.com/kuba/simp_le.git + +cd /opt/simp_le +# Upgrade setuptools +pip install -U setuptools +# Install simp_le in /usr/local/bin +python ./setup.py install + +# Make house cleaning +rm -rf /opt/simp_le + +apt-get autoremove -y git gcc libssl-dev libffi-dev python-dev python-pip + +apt-get clean all +rm -r /var/lib/apt/lists/* diff --git a/docker-entrypoint.sh b/docker-entrypoint.sh deleted file mode 100755 index 6353314..0000000 --- a/docker-entrypoint.sh +++ /dev/null @@ -1,22 +0,0 @@ -#!/bin/bash -set -e - -# Warn if the DOCKER_HOST socket does not exist -if [[ $DOCKER_HOST == unix://* ]]; then - socket_file=${DOCKER_HOST#unix://} - if ! [ -S $socket_file ]; then - cat >&2 <<-EOT - ERROR: you need to share your Docker host socket with a volume at $socket_file - Typically you should run your jwilder/nginx-proxy with: \`-v /var/run/docker.sock:$socket_file:ro\` - See the documentation at http://git.io/vZaGJ - EOT - socketMissing=1 - fi -fi - -# If the user has run the default command and the socket doesn't exist, fail -if [ "$socketMissing" = 1 -a "$1" = forego -a "$2" = start -a "$3" = '-r' ]; then - exit 1 -fi - -exec "$@" diff --git a/letsencrypt_service b/letsencrypt_service index b0f240b..f02339a 100755 --- a/letsencrypt_service +++ b/letsencrypt_service @@ -23,7 +23,7 @@ update_certs() { mkdir -p /etc/nginx/certs/$domain cd /etc/nginx/certs/$domain - /opt/simp_le/venv/bin/simp_le \ + /usr/local/bin/simp_le \ -d "$domain" \ -f fullchain.pem -f key.pem \ --email "${!email_varname}" \ From 4968fad44f333ecbd389f496e07ad5e2f604fc45 Mon Sep 17 00:00:00 2001 From: Hadrien Mary Date: Thu, 26 Nov 2015 10:21:20 +0100 Subject: [PATCH 17/42] Update README --- README.md | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index 3627b65..a7b42e9 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -![nginx 1.9.6](https://img.shields.io/badge/nginx-1.9.6-brightgreen.svg) ![License MIT](https://img.shields.io/badge/license-MIT-blue.svg) [![Build](https://circleci.com/gh/jwilder/nginx-proxy.svg?&style=shield&circle-token=2da3ee844076a47371bd45da81cf27409ca7306a)](https://circleci.com/gh/jwilder/nginx-proxy) +![nginx 1.9.6](https://img.shields.io/badge/nginx-1.9.6-brightgreen.svg) ![License MIT](https://img.shields.io/badge/license-MIT-blue.svg) [![Build](https://circleci.com/gh/dmp1ce/nginx-proxy-letsencrypt.svg?&style=shield&circle-token=2da3ee844076a47371bd45da81cf27409ca7306a)](https://circleci.com/gh/dmp1ce/nginx-proxy-letsencrypt) nginx-proxy sets up a container running nginx and [docker-gen][1]. docker-gen generates reverse proxy configs for nginx and reloads nginx when containers are started and stopped. @@ -8,7 +8,7 @@ See [Automated Nginx Reverse Proxy for Docker][2] for why you might want to use To run it: - $ docker run -d -p 80:80 -v /var/run/docker.sock:/tmp/docker.sock:ro jwilder/nginx-proxy + $ docker run -d -p 80:80 -v /var/run/docker.sock:/tmp/docker.sock:ro dmp1ce/nginx-proxy-letsencrypt Then start any containers you want proxied with an env var `VIRTUAL_HOST=subdomain.youdomain.com` @@ -41,7 +41,7 @@ If you would like to connect to your backend using HTTPS instead of HTTP, set `V To set the default host for nginx use the env var `DEFAULT_HOST=foo.bar.com` for example - $ docker run -d -p 80:80 -e DEFAULT_HOST=foo.bar.com -v /var/run/docker.sock:/tmp/docker.sock:ro jwilder/nginx-proxy + $ docker run -d -p 80:80 -e DEFAULT_HOST=foo.bar.com -v /var/run/docker.sock:/tmp/docker.sock:ro dmp1ce/nginx-proxy-letsencrypt ### Separate Containers @@ -51,7 +51,7 @@ image and the official [nginx](https://registry.hub.docker.com/_/nginx/) image. You may want to do this to prevent having the docker socket bound to a publicly exposed container service. -To run nginx proxy as a separate container you'll need to have [nginx.tmpl](https://github.com/jwilder/nginx-proxy/blob/master/nginx.tmpl) on your host system. +To run nginx proxy as a separate container you'll need to have [nginx.tmpl](https://github.com/dmp1ce/nginx-proxy-letsencrypt/blob/master/nginx.tmpl) on your host system. First start nginx with a volume: @@ -78,7 +78,7 @@ certificates or optionally specifying a cert name (for SNI) as an environment va 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 + $ 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 dmp1ce/nginx-proxy-letsencrypt 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 @@ -144,7 +144,7 @@ $ docker run -d -p 80:80 -p 443:443 \ -v /path/to/htpasswd:/etc/nginx/htpasswd \ -v /path/to/certs:/etc/nginx/certs \ -v /var/run/docker.sock:/tmp/docker.sock:ro \ - jwilder/nginx-proxy + dmp1ce/nginx-proxy-letsencrypt ``` You'll need apache2-utils on the machine where you plan to create the htpasswd file. Follow these [instructions](http://httpd.apache.org/docs/2.2/programs/htpasswd.html) @@ -179,7 +179,7 @@ To add settings on a proxy-wide basis, add your configuration file under `/etc/n This can be done in a derived image by creating the file in a `RUN` command or by `COPY`ing the file into `conf.d`: ```Dockerfile -FROM jwilder/nginx-proxy +FROM dmp1ce/nginx-proxy-letsencrypt RUN { \ echo 'server_tokens off;'; \ echo 'client_max_body_size 100m;'; \ @@ -188,7 +188,7 @@ RUN { \ Or it can be done by mounting in your custom configuration in your `docker run` command: - $ docker run -d -p 80:80 -p 443:443 -v /path/to/my_proxy.conf:/etc/nginx/conf.d/my_proxy.conf:ro -v /var/run/docker.sock:/tmp/docker.sock:ro jwilder/nginx-proxy + $ docker run -d -p 80:80 -p 443:443 -v /path/to/my_proxy.conf:/etc/nginx/conf.d/my_proxy.conf:ro -v /var/run/docker.sock:/tmp/docker.sock:ro dmp1ce/nginx-proxy-letsencrypt #### Per-VIRTUAL_HOST @@ -198,7 +198,7 @@ In order to allow virtual hosts to be dynamically configured as backends are add For example, if you have a virtual host named `app.example.com`, you could provide a custom configuration for that host as follows: - $ docker run -d -p 80:80 -p 443:443 -v /path/to/vhost.d:/etc/nginx/vhost.d:ro -v /var/run/docker.sock:/tmp/docker.sock:ro jwilder/nginx-proxy + $ docker run -d -p 80:80 -p 443:443 -v /path/to/vhost.d:/etc/nginx/vhost.d:ro -v /var/run/docker.sock:/tmp/docker.sock:ro dmp1ce/nginx-proxy-letsencrypt $ { echo 'server_tokens off;'; echo 'client_max_body_size 100m;'; } > /path/to/vhost.d/app.example.com If you are using multiple hostnames for a single container (e.g. `VIRTUAL_HOST=example.com,www.example.com`), the virtual host configuration file must exist for each hostname. If you would like to use the same configuration for multiple virtual host names, you can use a symlink: @@ -218,7 +218,7 @@ just like the previous section except with the suffix `_location`. For example, if you have a virtual host named `app.example.com` and you have configured a proxy_cache `my-cache` in another custom file, you could tell it to use a proxy cache as follows: - $ docker run -d -p 80:80 -p 443:443 -v /path/to/vhost.d:/etc/nginx/vhost.d:ro -v /var/run/docker.sock:/tmp/docker.sock:ro jwilder/nginx-proxy + $ docker run -d -p 80:80 -p 443:443 -v /path/to/vhost.d:/etc/nginx/vhost.d:ro -v /var/run/docker.sock:/tmp/docker.sock:ro dmp1ce/nginx-proxy-letsencrypt $ { echo 'proxy_cache my-cache;'; echo 'proxy_cache_valid 200 302 60m;'; echo 'proxy_cache_valid 404 1m;' } > /path/to/vhost.d/app.example.com_location If you are using multiple hostnames for a single container (e.g. `VIRTUAL_HOST=example.com,www.example.com`), the virtual host configuration file must exist for each hostname. If you would like to use the same configuration for multiple virtual host names, you can use a symlink: From 4337ca97e491dca50ebca998170cb4a6a2c761b4 Mon Sep 17 00:00:00 2001 From: Hadrien Mary Date: Thu, 26 Nov 2015 10:21:58 +0100 Subject: [PATCH 18/42] Remove build.sh (it makes the docker build process painfull) --- Dockerfile | 27 +++++++++++++++++++++++++-- build.sh | 28 ---------------------------- 2 files changed, 25 insertions(+), 30 deletions(-) delete mode 100755 build.sh diff --git a/Dockerfile b/Dockerfile index b4c1c2f..1a4623c 100644 --- a/Dockerfile +++ b/Dockerfile @@ -2,6 +2,29 @@ FROM jwilder/nginx-proxy MAINTAINER [ "Jason Wilder ", "Yves Blusseau <90z7oey02@sneakemail.com>" ] -COPY . /app/ +RUN apt-get update -RUN chmod +rx /app/build.sh && /app/build.sh && rm -f /app/build.sh +# Install python packages needed by simp_le +RUN apt-get install -y -q --no-install-recommends python python-requests + +# Install python packages needed to build simp_le +RUN apt-get install -y -q --no-install-recommends git gcc libssl-dev libffi-dev python-dev python-pip + +# Get Let's Encrypt simp_le client source +RUN git -C /opt clone https://github.com/kuba/simp_le.git + +WORKDIR /opt/simp_le +# Upgrade setuptools +RUN pip install -U setuptools +# Install simp_le in /usr/local/bin +RUN python ./setup.py install + +# Make house cleaning +RUN rm -rf /opt/simp_le + +RUN -get autoremove -y git gcc libssl-dev libffi-dev python-dev python-pip + +RUN apt-get clean all +RUN rm -r /var/lib/apt/lists/* + +COPY . /app/ diff --git a/build.sh b/build.sh deleted file mode 100755 index 194e16f..0000000 --- a/build.sh +++ /dev/null @@ -1,28 +0,0 @@ -#!/bin/bash - -set -e - -apt-get update - -# Install python packages needed by simp_le -apt-get install -y -q --no-install-recommends python python-requests - -# Install python packages needed to build simp_le -apt-get install -y -q --no-install-recommends git gcc libssl-dev libffi-dev python-dev python-pip - -# Get Let's Encrypt simp_le client source -git -C /opt clone https://github.com/kuba/simp_le.git - -cd /opt/simp_le -# Upgrade setuptools -pip install -U setuptools -# Install simp_le in /usr/local/bin -python ./setup.py install - -# Make house cleaning -rm -rf /opt/simp_le - -apt-get autoremove -y git gcc libssl-dev libffi-dev python-dev python-pip - -apt-get clean all -rm -r /var/lib/apt/lists/* From 007407f0c6344a2d82137732c5169bec33cd9255 Mon Sep 17 00:00:00 2001 From: Hadrien Mary Date: Thu, 26 Nov 2015 10:22:21 +0100 Subject: [PATCH 19/42] Fix Dockerfile --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 1a4623c..47532db 100644 --- a/Dockerfile +++ b/Dockerfile @@ -22,7 +22,7 @@ RUN python ./setup.py install # Make house cleaning RUN rm -rf /opt/simp_le -RUN -get autoremove -y git gcc libssl-dev libffi-dev python-dev python-pip +RUN apt-get autoremove -y git gcc libssl-dev libffi-dev python-dev python-pip RUN apt-get clean all RUN rm -r /var/lib/apt/lists/* From 1ff5e4e9fdcd2d9579db26f8a6759fa2511351cc Mon Sep 17 00:00:00 2001 From: Hadrien Mary Date: Thu, 26 Nov 2015 10:31:18 +0100 Subject: [PATCH 20/42] Fix Dockerfie (again) --- Dockerfile | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Dockerfile b/Dockerfile index 47532db..bd03f5d 100644 --- a/Dockerfile +++ b/Dockerfile @@ -28,3 +28,5 @@ RUN apt-get clean all RUN rm -r /var/lib/apt/lists/* COPY . /app/ + +WORKDIR /app/ From 8dd596c5830a61042bfa66202fb89abb7ea0c136 Mon Sep 17 00:00:00 2001 From: Hadrien Mary Date: Thu, 26 Nov 2015 10:31:34 +0100 Subject: [PATCH 21/42] Reload nginx when new certificates are added --- letsencrypt_service | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/letsencrypt_service b/letsencrypt_service index f02339a..35643a6 100755 --- a/letsencrypt_service +++ b/letsencrypt_service @@ -36,6 +36,10 @@ update_certs() { # Symlink to created certificate and key. ln -sf ./$domain/fullchain.pem /etc/nginx/certs/$domain".crt" ln -sf ./$domain/key.pem /etc/nginx/certs/$domain".key" + + # Update certificates configuration in nginx + /usr/local/bin/docker-gen -only-exposed /app/nginx.tmpl /etc/nginx/conf.d/default.conf + nginx -s reload fi done done @@ -47,11 +51,12 @@ trap '[[ $pid ]] && kill $pid; exec $0' EXIT trap 'trap - EXIT' INT TERM echo 'Waiting 10s before updating certs...' -sleep 10 +sleep 1s update_certs # Wait some amount of time +echo "Sleep for ${seconds_to_wait}s" sleep $seconds_to_wait & pid=$! wait pid= From 45d14386fa920f09210da8cb3b722683e97705e6 Mon Sep 17 00:00:00 2001 From: Hadrien Mary Date: Thu, 26 Nov 2015 10:46:51 +0100 Subject: [PATCH 22/42] Fix sleep --- letsencrypt_service | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/letsencrypt_service b/letsencrypt_service index 35643a6..762be82 100755 --- a/letsencrypt_service +++ b/letsencrypt_service @@ -51,7 +51,7 @@ trap '[[ $pid ]] && kill $pid; exec $0' EXIT trap 'trap - EXIT' INT TERM echo 'Waiting 10s before updating certs...' -sleep 1s +sleep 10s update_certs From 8ccffc5d2ed4e1f7c3b9b166bfc654cf6e03277e Mon Sep 17 00:00:00 2001 From: David Parrish Date: Thu, 26 Nov 2015 09:18:41 -0500 Subject: [PATCH 23/42] Add CircleCI badge --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index a7b42e9..be184bf 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -![nginx 1.9.6](https://img.shields.io/badge/nginx-1.9.6-brightgreen.svg) ![License MIT](https://img.shields.io/badge/license-MIT-blue.svg) [![Build](https://circleci.com/gh/dmp1ce/nginx-proxy-letsencrypt.svg?&style=shield&circle-token=2da3ee844076a47371bd45da81cf27409ca7306a)](https://circleci.com/gh/dmp1ce/nginx-proxy-letsencrypt) +![nginx 1.9.6](https://img.shields.io/badge/nginx-1.9.6-brightgreen.svg) ![License MIT](https://img.shields.io/badge/license-MIT-blue.svg) [![Build](https://circleci.com/gh/dmp1ce/nginx-proxy-letsencrypt.svg?&style=shield&circle-token=cd873b9ebad6424218c4dee8e8e2344366920dde)](https://circleci.com/gh/dmp1ce/nginx-proxy-letsencrypt) nginx-proxy sets up a container running nginx and [docker-gen][1]. docker-gen generates reverse proxy configs for nginx and reloads nginx when containers are started and stopped. From cf385fa0ff3c48965f34d818969cdc5ec52b21fa Mon Sep 17 00:00:00 2001 From: David Parrish Date: Thu, 26 Nov 2015 09:25:30 -0500 Subject: [PATCH 24/42] Update Dockerfile MAINTAINERs --- Dockerfile | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Dockerfile b/Dockerfile index bd03f5d..8e34333 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,6 +1,5 @@ FROM jwilder/nginx-proxy - -MAINTAINER [ "Jason Wilder ", "Yves Blusseau <90z7oey02@sneakemail.com>" ] +MAINTAINER [ "David Parrish ", "Hadrien Mary " ] RUN apt-get update From 02af7cd3c100d6d21d62fadcfc52b045c3341d17 Mon Sep 17 00:00:00 2001 From: David Parrish Date: Thu, 26 Nov 2015 09:49:25 -0500 Subject: [PATCH 25/42] Update README.md with fork explination --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index be184bf..82e15b8 100644 --- a/README.md +++ b/README.md @@ -4,6 +4,8 @@ nginx-proxy sets up a container running nginx and [docker-gen][1]. docker-gen g See [Automated Nginx Reverse Proxy for Docker][2] for why you might want to use this. +nginx-proxy-letsencrypt is a fork of nginx-proxy which adds Let's Encrypt support. Let's Encrypt allows multiple virtual hosts to have TLS certificates automatically created and renewed! The reason the jwilder/nginx-proxy was forked is because it seemed unlikely that the specific Let's Encrypt use case world be added to the more generic nginx-proxy project and the Let's Encrypt client does add some storage overhead. See [pull request](https://github.com/jwilder/nginx-proxy/pull/300) for details about fork. See [Let's Encrypt section](#lets-encrypt) for configuration details. + ### Usage To run it: From a4b00222abed1849b0bdc8d52e410328356a9a23 Mon Sep 17 00:00:00 2001 From: David Parrish Date: Mon, 23 Nov 2015 00:03:14 -0500 Subject: [PATCH 26/42] Use jwilder/nginx-proxy as base image and reduce final image size --- Dockerfile | 30 ++++-------------------------- install_simp_le.sh | 28 ++++++++++++++++++++++++++++ 2 files changed, 32 insertions(+), 26 deletions(-) create mode 100755 install_simp_le.sh diff --git a/Dockerfile b/Dockerfile index 8e34333..d3ebba3 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,31 +1,9 @@ FROM jwilder/nginx-proxy -MAINTAINER [ "David Parrish ", "Hadrien Mary " ] -RUN apt-get update - -# Install python packages needed by simp_le -RUN apt-get install -y -q --no-install-recommends python python-requests - -# Install python packages needed to build simp_le -RUN apt-get install -y -q --no-install-recommends git gcc libssl-dev libffi-dev python-dev python-pip - -# Get Let's Encrypt simp_le client source -RUN git -C /opt clone https://github.com/kuba/simp_le.git - -WORKDIR /opt/simp_le -# Upgrade setuptools -RUN pip install -U setuptools -# Install simp_le in /usr/local/bin -RUN python ./setup.py install - -# Make house cleaning -RUN rm -rf /opt/simp_le - -RUN apt-get autoremove -y git gcc libssl-dev libffi-dev python-dev python-pip - -RUN apt-get clean all -RUN rm -r /var/lib/apt/lists/* +MAINTAINER David Parrish +MAINTAINER Yves Blusseau <90z7oey02@sneakemail.com> COPY . /app/ -WORKDIR /app/ +# Install simp_le program +RUN chmod +rx /app/install_simp_le.sh && /app/install_simp_le.sh && rm -f /app/install_simp_le.sh diff --git a/install_simp_le.sh b/install_simp_le.sh new file mode 100755 index 0000000..194e16f --- /dev/null +++ b/install_simp_le.sh @@ -0,0 +1,28 @@ +#!/bin/bash + +set -e + +apt-get update + +# Install python packages needed by simp_le +apt-get install -y -q --no-install-recommends python python-requests + +# Install python packages needed to build simp_le +apt-get install -y -q --no-install-recommends git gcc libssl-dev libffi-dev python-dev python-pip + +# Get Let's Encrypt simp_le client source +git -C /opt clone https://github.com/kuba/simp_le.git + +cd /opt/simp_le +# Upgrade setuptools +pip install -U setuptools +# Install simp_le in /usr/local/bin +python ./setup.py install + +# Make house cleaning +rm -rf /opt/simp_le + +apt-get autoremove -y git gcc libssl-dev libffi-dev python-dev python-pip + +apt-get clean all +rm -r /var/lib/apt/lists/* From 109017566a8fcd7df85d15fb093211a159ce3ffe Mon Sep 17 00:00:00 2001 From: JrCs <90z7oey02@sneakemail.com> Date: Fri, 27 Nov 2015 12:45:40 +0100 Subject: [PATCH 27/42] Add Hadrien Mary as maintainer --- Dockerfile | 1 + 1 file changed, 1 insertion(+) diff --git a/Dockerfile b/Dockerfile index d3ebba3..27ced08 100644 --- a/Dockerfile +++ b/Dockerfile @@ -2,6 +2,7 @@ FROM jwilder/nginx-proxy MAINTAINER David Parrish MAINTAINER Yves Blusseau <90z7oey02@sneakemail.com> +MAINTAINER Hadrien Mary COPY . /app/ From 7b40ad970f351dacbd86314cf84b9b381b96f45e Mon Sep 17 00:00:00 2001 From: JrCs <90z7oey02@sneakemail.com> Date: Fri, 27 Nov 2015 12:46:12 +0100 Subject: [PATCH 28/42] Reload nginx if certificates has been created/updated --- letsencrypt_service | 10 ++++++---- update_nginx | 4 ++-- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/letsencrypt_service b/letsencrypt_service index 762be82..f290b70 100755 --- a/letsencrypt_service +++ b/letsencrypt_service @@ -10,6 +10,7 @@ update_certs() { # Load relevant container settings source "$DIR"/letsencrypt_service_data + reload_nginx='false' for cid in "${LETSENCRYPT_CONTAINERS[@]}"; do # Derive host and email variable names host_varname="LETSENCRYPT_${cid}_HOST" @@ -36,14 +37,15 @@ update_certs() { # Symlink to created certificate and key. ln -sf ./$domain/fullchain.pem /etc/nginx/certs/$domain".crt" ln -sf ./$domain/key.pem /etc/nginx/certs/$domain".key" - - # Update certificates configuration in nginx - /usr/local/bin/docker-gen -only-exposed /app/nginx.tmpl /etc/nginx/conf.d/default.conf - nginx -s reload + reload_nginx='true' fi done done unset LETSENCRYPT_CONTAINERS + if [[ "$reload_nginx" == 'true' ]]; then + /usr/local/bin/docker-gen -only-exposed /app/nginx.tmpl /etc/nginx/conf.d/default.conf + nginx -s reload + fi } pid= diff --git a/update_nginx b/update_nginx index 91c10e9..3a2df5b 100755 --- a/update_nginx +++ b/update_nginx @@ -1,8 +1,8 @@ #!/bin/bash +nginx -s reload + docker-gen \ -only-exposed \ -notify '/app/update_certs' \ /app/letsencrypt_service_data.tmpl /app/letsencrypt_service_data - -nginx -s reload From 573aa7e82e46338829934867f97d6bd1f3c5dc5a Mon Sep 17 00:00:00 2001 From: JrCs <90z7oey02@sneakemail.com> Date: Fri, 27 Nov 2015 13:03:30 +0100 Subject: [PATCH 29/42] Add badge with image size --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 82e15b8..f70eb48 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -![nginx 1.9.6](https://img.shields.io/badge/nginx-1.9.6-brightgreen.svg) ![License MIT](https://img.shields.io/badge/license-MIT-blue.svg) [![Build](https://circleci.com/gh/dmp1ce/nginx-proxy-letsencrypt.svg?&style=shield&circle-token=cd873b9ebad6424218c4dee8e8e2344366920dde)](https://circleci.com/gh/dmp1ce/nginx-proxy-letsencrypt) +![nginx 1.9.6](https://img.shields.io/badge/nginx-1.9.6-brightgreen.svg) ![License MIT](https://img.shields.io/badge/license-MIT-blue.svg) [![Build](https://circleci.com/gh/dmp1ce/nginx-proxy-letsencrypt.svg?&style=shield&circle-token=cd873b9ebad6424218c4dee8e8e2344366920dde)](https://circleci.com/gh/dmp1ce/nginx-proxy-letsencrypt) [![](https://badge.imagelayers.io/dmp1ce/nginx-proxy-letsencrypt:latest.svg)](https://imagelayers.io/?images=dmp1ce/nginx-proxy-letsencrypt:latest 'Get your own badge on imagelayers.io') nginx-proxy sets up a container running nginx and [docker-gen][1]. docker-gen generates reverse proxy configs for nginx and reloads nginx when containers are started and stopped. From bc81ac69035c04bc5d4ffd67b7c7bf4c42b34a7e Mon Sep 17 00:00:00 2001 From: David Parrish Date: Fri, 27 Nov 2015 12:34:34 -0500 Subject: [PATCH 30/42] Change LETSENCRYPT_HOST delimiter to a comma --- README.md | 2 +- letsencrypt_service_data.tmpl | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 82e15b8..c37733e 100644 --- a/README.md +++ b/README.md @@ -132,7 +132,7 @@ Set the following environment variables to enable Let's Encrypt support for a co - `LETSENCRYPT_HOST` - `LETSENCRYPT_EMAIL` -The `LETSENCRYPT_HOST` variable most likely needs to be the same as the `VIRTUAL_HOSTS` variable and must be publicly reachable domains. Specify multiple hosts with a space delimiter. +The `LETSENCRYPT_HOST` variable most likely needs to be the same as the `VIRTUAL_HOST` variable and must be publicly reachable domains. Specify multiple hosts with a comma delimiter. After the first start, the nginx-proxy will need to be restarted again. This is because the nginx configuration needs to be regenerated after downloading the Let's Encrypt certificate. diff --git a/letsencrypt_service_data.tmpl b/letsencrypt_service_data.tmpl index 32133c1..7c2933f 100644 --- a/letsencrypt_service_data.tmpl +++ b/letsencrypt_service_data.tmpl @@ -3,7 +3,7 @@ LETSENCRYPT_CONTAINERS=({{ range $host, $containers := groupBy $ "Env.LETSENCRYP {{ range $hosts, $containers := groupBy $ "Env.LETSENCRYPT_HOST" }} {{ range $container := $containers }} -LETSENCRYPT_{{ $container.ID }}_HOST=( {{ range $host := split $hosts " " }}'{{ $host }}' {{ end }}) +LETSENCRYPT_{{ $container.ID }}_HOST=( {{ range $host := split $hosts "," }}'{{ $host }}' {{ end }}) LETSENCRYPT_{{ $container.ID }}_EMAIL="{{ $container.Env.LETSENCRYPT_EMAIL }}" {{ end }} From 76a279e4d3fd3ad132029c81fa39121b94d08d2c Mon Sep 17 00:00:00 2001 From: David Parrish Date: Fri, 27 Nov 2015 12:36:07 -0500 Subject: [PATCH 31/42] Update Let's Encrypt section with an example. Remove old and incorrect help text about restarting. --- README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index c37733e..15fd270 100644 --- a/README.md +++ b/README.md @@ -134,7 +134,9 @@ Set the following environment variables to enable Let's Encrypt support for a co The `LETSENCRYPT_HOST` variable most likely needs to be the same as the `VIRTUAL_HOST` variable and must be publicly reachable domains. Specify multiple hosts with a comma delimiter. -After the first start, the nginx-proxy will need to be restarted again. This is because the nginx configuration needs to be regenerated after downloading the Let's Encrypt certificate. +For example + + $ docker run -d -e VIRTUAL_HOST="foo.bar.com,bar.com" -e LETSENCRYPT_HOST="foo.bar.com,bar.com" -e LETSENCRYPT_EMAIL="foo@bar.com" dmp1ce/nginx-proxy-letsencrypt ### Basic Authentication Support From 476af6cd49410b2acd4d5d5e99225eda56c43f3a Mon Sep 17 00:00:00 2001 From: David Parrish Date: Fri, 27 Nov 2015 12:47:05 -0500 Subject: [PATCH 32/42] Update Let's Encrypt example with ports and docker.sock volume --- README.md | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 15fd270..c41da9e 100644 --- a/README.md +++ b/README.md @@ -136,7 +136,14 @@ The `LETSENCRYPT_HOST` variable most likely needs to be the same as the `VIRTUAL For example - $ docker run -d -e VIRTUAL_HOST="foo.bar.com,bar.com" -e LETSENCRYPT_HOST="foo.bar.com,bar.com" -e LETSENCRYPT_EMAIL="foo@bar.com" dmp1ce/nginx-proxy-letsencrypt +``` +$ docker run -d -p 80:80 -p 443:443 \ + -e VIRTUAL_HOST="foo.bar.com,bar.com" \ + -e LETSENCRYPT_HOST="foo.bar.com,bar.com" \ + -e LETSENCRYPT_EMAIL="foo@bar.com" \ + -v /var/run/docker.sock:/tmp/docker.sock:ro \ + dmp1ce/nginx-proxy-letsencrypt +``` ### Basic Authentication Support From a05aaa8b0055838fbf567287ac02e46e6979c79d Mon Sep 17 00:00:00 2001 From: David Parrish Date: Fri, 27 Nov 2015 20:26:08 -0500 Subject: [PATCH 33/42] Add 'sync' to Dockerfile to avoid 'Text file busy' error when building image --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 27ced08..22dd65e 100644 --- a/Dockerfile +++ b/Dockerfile @@ -7,4 +7,4 @@ MAINTAINER Hadrien Mary COPY . /app/ # Install simp_le program -RUN chmod +rx /app/install_simp_le.sh && /app/install_simp_le.sh && rm -f /app/install_simp_le.sh +RUN chmod +rx /app/install_simp_le.sh && sync && /app/install_simp_le.sh && rm -f /app/install_simp_le.sh From 2f65681c1a7d4533dd2985fbf008cfdc6819557b Mon Sep 17 00:00:00 2001 From: JrCs <90z7oey02@sneakemail.com> Date: Sat, 5 Dec 2015 12:06:58 +0100 Subject: [PATCH 34/42] Some little improvements --- Dockerfile | 5 +++-- letsencrypt_service | 1 + 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/Dockerfile b/Dockerfile index 22dd65e..252e906 100644 --- a/Dockerfile +++ b/Dockerfile @@ -4,7 +4,8 @@ MAINTAINER David Parrish MAINTAINER Yves Blusseau <90z7oey02@sneakemail.com> MAINTAINER Hadrien Mary -COPY . /app/ - # Install simp_le program +COPY /install_simp_le.sh /app/install_simp_le.sh RUN chmod +rx /app/install_simp_le.sh && sync && /app/install_simp_le.sh && rm -f /app/install_simp_le.sh + +COPY letsencrypt_service letsencrypt_service_data.tmpl nginx.tmpl Procfile update_certs update_nginx /app/ diff --git a/letsencrypt_service b/letsencrypt_service index f290b70..816b555 100755 --- a/letsencrypt_service +++ b/letsencrypt_service @@ -24,6 +24,7 @@ update_certs() { mkdir -p /etc/nginx/certs/$domain cd /etc/nginx/certs/$domain + echo "Creating/renewal $domain certificates..." /usr/local/bin/simp_le \ -d "$domain" \ -f fullchain.pem -f key.pem \ From 49ed239d573d2a7ad477376529a56f145e581296 Mon Sep 17 00:00:00 2001 From: JrCs <90z7oey02@sneakemail.com> Date: Wed, 9 Dec 2015 12:16:20 +0100 Subject: [PATCH 35/42] Update to use the new simp_le API --- letsencrypt_service | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/letsencrypt_service b/letsencrypt_service index 816b555..a1a24e2 100755 --- a/letsencrypt_service +++ b/letsencrypt_service @@ -27,7 +27,7 @@ update_certs() { echo "Creating/renewal $domain certificates..." /usr/local/bin/simp_le \ -d "$domain" \ - -f fullchain.pem -f key.pem \ + -f account_key.json -f key.pem -f fullchain.pem \ --email "${!email_varname}" \ --server=https://acme-v01.api.letsencrypt.org/directory \ --default_root /usr/share/nginx/html/ From 8e58255bdb1f46ef06f5a02d237e6afd50a3716b Mon Sep 17 00:00:00 2001 From: daditto Date: Thu, 10 Dec 2015 13:17:40 +0200 Subject: [PATCH 36/42] Add support for alternative names --- letsencrypt_service | 40 ++++++++++++++++++++++++---------------- 1 file changed, 24 insertions(+), 16 deletions(-) diff --git a/letsencrypt_service b/letsencrypt_service index a1a24e2..bbb7f88 100755 --- a/letsencrypt_service +++ b/letsencrypt_service @@ -18,29 +18,37 @@ update_certs() { hosts_array=$host_varname[@] email_varname="LETSENCRYPT_${cid}_EMAIL" + params_d_str="" + hosts_array_expanded=("${!hosts_array}") + # First domain will be our base domain + base_domain="${hosts_array_expanded[0]}" + + # Create directorty for the first domain + mkdir -p /etc/nginx/certs/$base_domain + cd /etc/nginx/certs/$base_domain + for domain in "${!hosts_array}"; do - - # Create the domain directory - mkdir -p /etc/nginx/certs/$domain - cd /etc/nginx/certs/$domain - - echo "Creating/renewal $domain certificates..." - /usr/local/bin/simp_le \ - -d "$domain" \ + # Add all the domains to certificate + params_d_str+=" -d $domain" + done + echo "Creating/renewal $base_domain certificates... (${hosts_array_expanded[*]})" + /usr/local/bin/simp_le \ -f account_key.json -f key.pem -f fullchain.pem \ + $params_d_str \ --email "${!email_varname}" \ --server=https://acme-v01.api.letsencrypt.org/directory \ --default_root /usr/share/nginx/html/ - simp_le_return=$? + simp_le_return=$? - if [[ $simp_le_return -eq 0 ]]; then - # Symlink to created certificate and key. - ln -sf ./$domain/fullchain.pem /etc/nginx/certs/$domain".crt" - ln -sf ./$domain/key.pem /etc/nginx/certs/$domain".key" - reload_nginx='true' - fi - done + if [[ $simp_le_return -eq 0 ]]; then + for domain in "${!hosts_array}"; do + # Symlink all alternative names to base domain certificate + ln -sf ./$base_domain/fullchain.pem /etc/nginx/certs/$domain".crt" + ln -sf ./$base_domain/key.pem /etc/nginx/certs/$domain".key" + done + reload_nginx='true' + fi done unset LETSENCRYPT_CONTAINERS if [[ "$reload_nginx" == 'true' ]]; then From 3a16eee5f72c2d06ec172a37cd4ca505e8bb506e Mon Sep 17 00:00:00 2001 From: David Parrish Date: Sun, 13 Dec 2015 19:54:18 -0500 Subject: [PATCH 37/42] Update tests for 'nginx-proxy-letsencrypt'. Cleanup test containers when possible during tests. Add 'test-clean' make target for remaining bat-* containers. --- Makefile | 7 +++++-- test/README.md | 6 +++--- test/cleanup_test_containers.sh | 8 ++++++++ test/docker.bats | 3 +-- test/lib/docker_helpers.bash | 7 ++++++- test/test_helpers.bash | 6 +++--- 6 files changed, 26 insertions(+), 11 deletions(-) create mode 100755 test/cleanup_test_containers.sh diff --git a/Makefile b/Makefile index 4eaf98a..9c57706 100644 --- a/Makefile +++ b/Makefile @@ -7,8 +7,11 @@ update-dependencies: docker pull python:3 docker pull rancher/socat-docker:latest docker pull appropriate/curl:latest - docker pull docker:1.7 + docker pull docker:1.9.1 test: - docker build -t jwilder/nginx-proxy:bats . + docker build -t dmp1ce/nginx-proxy-letsencrypt:bats . bats test + +test-clean: + ./test/cleanup_test_containers.sh diff --git a/test/README.md b/test/README.md index 721d436..c4fa6e8 100644 --- a/test/README.md +++ b/test/README.md @@ -3,12 +3,12 @@ Test suite This test suite is implemented on top of the [Bats](https://github.com/sstephenson/bats/blob/master/README.md) test framework. -It is intended to verify the correct behavior of the Docker image `jwilder/nginx-proxy:bats`. +It is intended to verify the correct behavior of the Docker image `dmp1ce/nginx-proxy-letsencrypt:bats`. Running the test suite ---------------------- Make sure you have Bats installed, then run: - docker build -t jwilder/nginx-proxy:bats . - bats test/ \ No newline at end of file + docker build -t jwilder/nginx-proxy-letsencrypt:bats . + bats test/ diff --git a/test/cleanup_test_containers.sh b/test/cleanup_test_containers.sh new file mode 100755 index 0000000..f4e0a3f --- /dev/null +++ b/test/cleanup_test_containers.sh @@ -0,0 +1,8 @@ +#!/bin/bash + +# Remove "bats-*" containers +function teardown { + docker rm -f $(docker ps -aq -f name=bats-*) +} + +teardown diff --git a/test/docker.bats b/test/docker.bats index f4ec665..1de063d 100644 --- a/test/docker.bats +++ b/test/docker.bats @@ -62,7 +62,7 @@ load test_helpers -v /etc/nginx/certs/ \ nginx:latest assert_success - run retry 5 1s docker run appropriate/curl --silent --fail --head http://$(docker_ip bats-nginx)/ + run retry 5 1s docker run --rm appropriate/curl --silent --fail --head http://$(docker_ip bats-nginx)/ assert_output -l 0 $'HTTP/1.1 200 OK\r' # WHEN docker-gen runs on our docker host @@ -114,4 +114,3 @@ function assert_nginxproxy_behaves { run curl_container $container /data --header "Host: webFOO.bats" --head assert_output -l 0 $'HTTP/1.1 503 Service Temporarily Unavailable\r' } - diff --git a/test/lib/docker_helpers.bash b/test/lib/docker_helpers.bash index b5165af..fe09c49 100644 --- a/test/lib/docker_helpers.bash +++ b/test/lib/docker_helpers.bash @@ -56,5 +56,10 @@ function docker_tcp { --expose 2375 \ -v /var/run/docker.sock:/var/run/docker.sock \ rancher/socat-docker - docker run --link "$container_name:docker" docker:1.7 version + docker run --rm --link "$container_name:docker" docker:1.9.1 version } + +# Remove "bats-*" containers after each test +#function teardown { + #docker rm -f $(docker ps -aq -f name=bats-*) +#} diff --git a/test/test_helpers.bash b/test/test_helpers.bash index 5890677..15d82bd 100644 --- a/test/test_helpers.bash +++ b/test/test_helpers.bash @@ -5,7 +5,7 @@ # set a few global variables -SUT_IMAGE=jwilder/nginx-proxy:bats +SUT_IMAGE=dmp1ce/nginx-proxy-letsencrypt:bats TEST_FILE=$(basename $BATS_TEST_FILENAME .bats) @@ -66,7 +66,7 @@ function curl_container { local -r container=$1 local -r path=$2 shift 2 - docker run appropriate/curl --silent \ + docker run --rm appropriate/curl --silent \ --connect-timeout 5 \ --max-time 20 \ "$@" \ @@ -128,7 +128,7 @@ function prepare_web_container { # THEN querying directly port works IFS=$' \t\n' # See https://github.com/sstephenson/bats/issues/89 for port in $ports; do - run retry 5 1s docker run appropriate/curl --silent --fail http://$(docker_ip $container_name):$port/data + run retry 5 1s docker run --rm appropriate/curl --silent --fail http://$(docker_ip $container_name):$port/data assert_output "answer from port $port" done } From 9644c311beec29e03f82273f7b7cd420da784b62 Mon Sep 17 00:00:00 2001 From: David Parrish Date: Sun, 13 Dec 2015 20:10:40 -0500 Subject: [PATCH 38/42] Update docker verision for circleci --- circle.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/circle.yml b/circle.yml index 424084c..455718c 100644 --- a/circle.yml +++ b/circle.yml @@ -1,7 +1,7 @@ machine: pre: - # install docker 1.7.1 - - sudo curl -L -o /usr/bin/docker 'https://s3-external-1.amazonaws.com/circle-downloads/docker-1.7.1-circleci'; sudo chmod 0755 /usr/bin/docker; true + # install docker 1.9.1 + - sudo curl -L -o /usr/bin/docker 'https://s3-external-1.amazonaws.com/circle-downloads/docker-1.9.1-circleci'; sudo chmod 0755 /usr/bin/docker; true services: - docker From 35c68ba7f73cf67c95c4213fdc183b32a6dc6be5 Mon Sep 17 00:00:00 2001 From: David Parrish Date: Sun, 13 Dec 2015 21:19:13 -0500 Subject: [PATCH 39/42] Fix CircleCI build - Specify assert lines for tests to avoid btrfs errors with CircleCI - Update Docker version to 1.9.1 in CircleCI --- circle.yml | 4 +++- test/docker.bats | 4 ++-- test/multiple-hosts.bats | 4 ++-- test/multiple-ports.bats | 2 +- test/test_helpers.bash | 2 +- 5 files changed, 9 insertions(+), 7 deletions(-) diff --git a/circle.yml b/circle.yml index 455718c..82a0a08 100644 --- a/circle.yml +++ b/circle.yml @@ -1,7 +1,9 @@ machine: pre: - # install docker 1.9.1 + # install docker 1.9.1 with some CircleCI suggestions: + # https://discuss.circleci.com/t/how-use-a-different-docker-version/298/8 - sudo curl -L -o /usr/bin/docker 'https://s3-external-1.amazonaws.com/circle-downloads/docker-1.9.1-circleci'; sudo chmod 0755 /usr/bin/docker; true + - sudo sed -i -e 's/ --userland-proxy=false//' /etc/default/docker services: - docker diff --git a/test/docker.bats b/test/docker.bats index 1de063d..f705432 100644 --- a/test/docker.bats +++ b/test/docker.bats @@ -105,10 +105,10 @@ function assert_nginxproxy_behaves { # Querying the proxy with Host header → 200 run curl_container $container /data --header "Host: web1.bats" - assert_output "answer from port 81" + assert_output -l 0 "answer from port 81" run curl_container $container /data --header "Host: web2.bats" - assert_output "answer from port 82" + assert_output -l 0 "answer from port 82" # Querying the proxy with unknown Host header → 503 run curl_container $container /data --header "Host: webFOO.bats" --head diff --git a/test/multiple-hosts.bats b/test/multiple-hosts.bats index 695aec1..40c3a39 100644 --- a/test/multiple-hosts.bats +++ b/test/multiple-hosts.bats @@ -32,9 +32,9 @@ function setup { # THEN run curl_container $SUT_CONTAINER /data --header 'Host: multiple-hosts-1-A.bats' - assert_output "answer from port 80" + assert_output -l 0 "answer from port 80" # THEN run curl_container $SUT_CONTAINER /data --header 'Host: multiple-hosts-1-B.bats' - assert_output "answer from port 80" + assert_output -l 0 "answer from port 80" } diff --git a/test/multiple-ports.bats b/test/multiple-ports.bats index a520571..8e0d9ae 100644 --- a/test/multiple-ports.bats +++ b/test/multiple-ports.bats @@ -52,6 +52,6 @@ function setup { function assert_response_is_from_port { local -r port=$1 run curl_container $SUT_CONTAINER /data --header "Host: web.bats" - assert_output "answer from port $port" + assert_output -l 0 "answer from port $port" } diff --git a/test/test_helpers.bash b/test/test_helpers.bash index 15d82bd..73f1105 100644 --- a/test/test_helpers.bash +++ b/test/test_helpers.bash @@ -129,6 +129,6 @@ function prepare_web_container { IFS=$' \t\n' # See https://github.com/sstephenson/bats/issues/89 for port in $ports; do run retry 5 1s docker run --rm appropriate/curl --silent --fail http://$(docker_ip $container_name):$port/data - assert_output "answer from port $port" + assert_output -l 0 "answer from port $port" done } From 8f1256ab3fb4bf76b92d77a90a468e9da1237d91 Mon Sep 17 00:00:00 2001 From: AdminJack Date: Tue, 15 Dec 2015 13:38:08 +0100 Subject: [PATCH 40/42] eliminate confusion in example of Let's Encrypt We don't need a connection over a proxy to a proxy. --- README.md | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 7afdad6..6f07184 100644 --- a/README.md +++ b/README.md @@ -137,12 +137,10 @@ The `LETSENCRYPT_HOST` variable most likely needs to be the same as the `VIRTUAL For example ``` -$ docker run -d -p 80:80 -p 443:443 \ +$ docker run -d -p 80:80 \ -e VIRTUAL_HOST="foo.bar.com,bar.com" \ -e LETSENCRYPT_HOST="foo.bar.com,bar.com" \ - -e LETSENCRYPT_EMAIL="foo@bar.com" \ - -v /var/run/docker.sock:/tmp/docker.sock:ro \ - dmp1ce/nginx-proxy-letsencrypt + -e LETSENCRYPT_EMAIL="foo@bar.com" ... ``` ### Basic Authentication Support From 819df6ef28ca114f72a90277d902bfa557b47e53 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Darius=20Kri=C5=A1tapavi=C4=8Dius?= Date: Wed, 16 Dec 2015 21:58:00 +0200 Subject: [PATCH 41/42] ACME CA API endpoint URI as env parameter --- README.md | 16 ++++++++++++++++ letsencrypt_service | 3 ++- 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 6f07184..4a52e86 100644 --- a/README.md +++ b/README.md @@ -143,6 +143,22 @@ $ docker run -d -p 80:80 \ -e LETSENCRYPT_EMAIL="foo@bar.com" ... ``` +##### Optional container environment variables + +Optional nginx-proxy-letsencrypt container environment variables for custom configuration. + +- `ACME_CA_URI` - Directory URI for the CA ACME API endpoint (default: ``https://acme-v01.api.letsencrypt.org/directory``) + +For example + +``` +$ docker run -d -p 80:80 -p 443:443 \ + -e ACME_CA_URI="https://acme-staging.api.letsencrypt.org/directory" \ + -v /path/to/certs:/etc/nginx/certs \ + -v /var/run/docker.sock:/tmp/docker.sock:ro \ + dmp1ce/nginx-proxy-letsencrypt +``` + ### Basic Authentication Support In order to be able to secure your virtual host, you have to create a file named as its equivalent VIRTUAL_HOST variable on directory diff --git a/letsencrypt_service b/letsencrypt_service index bbb7f88..22f2ad1 100755 --- a/letsencrypt_service +++ b/letsencrypt_service @@ -3,6 +3,7 @@ DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" seconds_to_wait=3600 +acme_ca_uri="${ACME_CA_URI:-https://acme-v01.api.letsencrypt.org/directory}" update_certs() { [[ ! -f "$DIR"/letsencrypt_service_data ]] && return @@ -36,7 +37,7 @@ update_certs() { -f account_key.json -f key.pem -f fullchain.pem \ $params_d_str \ --email "${!email_varname}" \ - --server=https://acme-v01.api.letsencrypt.org/directory \ + --server=$acme_ca_uri \ --default_root /usr/share/nginx/html/ simp_le_return=$? From e95be1995026db473ba49f10eb146738805499ce Mon Sep 17 00:00:00 2001 From: David Parrish Date: Sat, 9 Jan 2016 19:09:19 -0500 Subject: [PATCH 42/42] Update README.md Notify users that development has moved to https://github.com/JrCs/docker-letsencrypt-nginx-proxy-companion --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 4a52e86..8488ea2 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,5 @@ +**Development efforts have moved to the [docker-letsencrypt-nginx-proxy-companion](https://github.com/JrCs/docker-letsencrypt-nginx-proxy-companion) project. docker-letsencrypt-nginx-proxy-companion doesn't require a fork of nginx-proxy in order to register Let's Encrypt certificates.** + ![nginx 1.9.6](https://img.shields.io/badge/nginx-1.9.6-brightgreen.svg) ![License MIT](https://img.shields.io/badge/license-MIT-blue.svg) [![Build](https://circleci.com/gh/dmp1ce/nginx-proxy-letsencrypt.svg?&style=shield&circle-token=cd873b9ebad6424218c4dee8e8e2344366920dde)](https://circleci.com/gh/dmp1ce/nginx-proxy-letsencrypt) [![](https://badge.imagelayers.io/dmp1ce/nginx-proxy-letsencrypt:latest.svg)](https://imagelayers.io/?images=dmp1ce/nginx-proxy-letsencrypt:latest 'Get your own badge on imagelayers.io') nginx-proxy sets up a container running nginx and [docker-gen][1]. docker-gen generates reverse proxy configs for nginx and reloads nginx when containers are started and stopped.