From e78baf4c37d91a04ab58fc8126a0126131fcd4af Mon Sep 17 00:00:00 2001 From: Henri Dwyer Date: Tue, 20 Sep 2016 21:12:59 -0400 Subject: [PATCH] use alpine base image --- Dockerfile | 25 +++++++++++++---------- README.md | 42 ++++++++++++++++++++++---------------- docker-compose.yml | 7 ++++--- scripts/run_certbot.sh | 21 +++++++++++++++++++ scripts/run_cron.sh | 1 - scripts/run_letsencrypt.sh | 18 ---------------- 6 files changed, 63 insertions(+), 51 deletions(-) create mode 100755 scripts/run_certbot.sh delete mode 100755 scripts/run_cron.sh delete mode 100755 scripts/run_letsencrypt.sh diff --git a/Dockerfile b/Dockerfile index 59e5743..e4de974 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,16 +1,19 @@ -FROM quay.io/letsencrypt/letsencrypt +FROM python:2-alpine MAINTAINER Henri Dwyer -RUN mkdir /certs - -# Add crontab file in the cron directory -ADD crontab /etc/cron.d/crontab - -# Give execution rights on the cron job -RUN chmod 0644 /etc/cron.d/crontab +VOLUME /certs -COPY ./scripts/ / +RUN apk add --no-cache --virtual .build-deps linux-headers gcc musl-dev\ + && apk add --no-cache libffi-dev openssl-dev\ + && pip install certbot\ + && apk del .build-deps\ + && mkdir /scripts -ENTRYPOINT ["/bin/sh", "-c"] +ADD crontab /etc/crontabs +RUN crontab /etc/crontabs/crontab -CMD ["/run_cron.sh"] +COPY ./scripts/ /scripts +RUN chmod +x /scripts/run_certbot.sh + +ENTRYPOINT [] +CMD ["crond", "-f"] diff --git a/README.md b/README.md index 6ac11c4..171181e 100644 --- a/README.md +++ b/README.md @@ -1,21 +1,20 @@ # docker-letsencrypt-cron -Create and automatically renew website certificates using the letsencrypt free CA. +Create and automatically renew website SSL certificates using the letsencrypt free certificate authority, and its client *certbot*. -This image will renew your certificates every 2 months, and place the lastest ones in the /certs folder on the host. - -Note: before letsencrypt becomes generally available, you will need to sign up for the private beta. +This image will renew your certificates every 2 months, and place the lastest ones in the /certs folder in the container, and in the ./certs folder on the host. # Setup In docker-compose.yml, change the environment variables: -- set the DOMAINS environment variable to a space separated list of domains for which you want to generate certificates. -- set the EMAIL environment variable for your account on the ACME server, and where you will receive updates from letsencrypt. - -If you want to use the certificates with nginx or apache, uncomment the relevant lines in scripts/run_letsencrypt.sh. +- DOMAINS: a space separated list of domains for which you want to generate certificates. +- EMAIL: where you will receive updates from letsencrypt. +- CONCAT: true or false on whether you want to concatenate the certificate's full chain with the private key (required for e.g. haproxy), or keep the two files separate (required for e.g. nginx or apache). # ACME Validation challenge -To authenticate the certificates, the you need to pass the ACME validation challenge. This requires requests made to on port 80 to example.com/.well-known/ to be forwarded to this image. +To authenticate the certificates, the you need to pass the ACME validation challenge. This requires requests made on port 80 to your.domain.com/.well-known/ to be forwarded to this container. + +The recommended way to use this image is to set up your reverse proxy to automatically forward requests for the ACME validation challenges to this container. ## Haproxy example @@ -26,10 +25,10 @@ frontend http bind *:80 acl letsencrypt_check path_beg /.well-known - use_backend letsencrypt if letsencrypt_check + use_backend certbot if letsencrypt_check -backend letsencrypt - server letsencrypt letsencrypt:80 maxconn 32 +backend certbot + server certbot certbot:80 maxconn 32 ``` ## Nginx example @@ -37,15 +36,15 @@ backend letsencrypt If you use nginx as a reverse proxy, you can add the following to your configuration file in order to pass the ACME challenge. ``` nginx -upstream letsencrypt_upstream{ - server letsencrypt:80; +upstream certbot_upstream{ + server certbot:80; } server { listen 80; location '/.well-known/acme-challenge' { default_type "text/plain"; - proxy_pass http://letsencrypt_upstream; + proxy_pass http://certbot_upstream; } } @@ -60,7 +59,7 @@ docker-compose up -d The first time you start it up, you may want to run the certificate generation script immediately: ```shell -docker exec letsencrypt sh -c "/run_letsencrypt.sh" +docker exec certbot sh -c "/run_certbot.sh" ``` At 3AM, on the 1st of every odd month, a cron job will start the script, renewing your certificates. @@ -69,6 +68,13 @@ At 3AM, on the 1st of every odd month, a cron job will start the script, renewin Find out more about letsencrypt: https://letsencrypt.org -Sign up for the private beta: https://letsencrypt.org/2015/11/12/public-beta-timing.html +Certbot github: https://github.com/certbot/certbot -Letsencrypt github: https://github.com/letsencrypt/letsencrypt +# Changelog + +### 0.2 +- Upgraded to use certbot client +- Changed image to use alpine linux + +### 0.1 +- Initial release diff --git a/docker-compose.yml b/docker-compose.yml index 6733f08..61e4cf4 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,11 +1,12 @@ -letsencrypt: +certbot: build: . - container_name: letsencrypt + container_name: certbot expose: - 80 volumes: - - /certs:/certs + - ./certs:/certs restart: always environment: - DOMAINS=domain1.com domain2.com - EMAIL=webmaster@domain1.com + - CONCAT=true diff --git a/scripts/run_certbot.sh b/scripts/run_certbot.sh new file mode 100755 index 0000000..d477856 --- /dev/null +++ b/scripts/run_certbot.sh @@ -0,0 +1,21 @@ +for d in $DOMAINS +do + echo "Running certbot for $d" + certbot --standalone --standalone-supported-challenges\ + http-01 --agree-dev-preview --agree-tos --renew-by-default\ + --email $EMAIL -d $d certonly + ec=$? + echo "certbot exit code $ec" + if [ $ec -eq 0 ] + then + if $CONCAT + then + # concat the full chain with the private key (e.g. for haproxy) + cat /etc/letsencrypt/live/$d/fullchain.pem /etc/letsencrypt/live/$d/privkey.pem > /certs/$d.pem + else + # keep full chain and private key in separate files (e.g. for nginx and apache) + cp /etc/letsencrypt/live/$d/fullchain.pem /certs/$d.pem + cp /etc/letsencrypt/live/$d/privkey.pem /certs/$d.key + fi + fi +done diff --git a/scripts/run_cron.sh b/scripts/run_cron.sh deleted file mode 100755 index 81853ed..0000000 --- a/scripts/run_cron.sh +++ /dev/null @@ -1 +0,0 @@ -cron -f diff --git a/scripts/run_letsencrypt.sh b/scripts/run_letsencrypt.sh deleted file mode 100755 index 9b50775..0000000 --- a/scripts/run_letsencrypt.sh +++ /dev/null @@ -1,18 +0,0 @@ -for d in $DOMAINS -do - echo "Running letsencrypt for $d" - letsencrypt --standalone --standalone-supported-challenges\ - http-01 --agree-dev-preview --agree-tos --renew-by-default\ - --server https://acme-v01.api.letsencrypt.org/directory\ - --email $EMAIL -d $d certonly - ec=$? - echo "letsencrypt exit code $ec" - if [ $ec -eq 0 ] - then - # For haproxy, you need to concatenate the full chain with the private key - cat /etc/letsencrypt/live/$d/fullchain.pem /etc/letsencrypt/live/$d/privkey.pem > /certs/$d.pem - # For nginx or apache, you need both separate files - # cp /etc/letsencrypt/live/$d/fullchain.pem /certs/$d.pem - # cp /etc/letsencrypt/live/$d/privkey.pem /certs/$d.key - fi -done