From f6d02a7ec9d85304082d8e3de92b4070f445c1c7 Mon Sep 17 00:00:00 2001 From: Elliot Saba Date: Sun, 12 Jan 2020 23:54:12 -0800 Subject: [PATCH] Enable templating! Eliminate unnecessary customization! --- README.md | 66 ++++++++++++++++++++++++++++++--------- src/scripts/entrypoint.sh | 2 +- src/scripts/util.sh | 14 ++++++--- 3 files changed, 63 insertions(+), 19 deletions(-) diff --git a/README.md b/README.md index 9dc73c7..1bada07 100644 --- a/README.md +++ b/README.md @@ -1,19 +1,14 @@ # docker-nginx-certbot -Create and automatically renew website SSL certificates using the letsencrypt free certificate authority, and its client *certbot*, built on top of the nginx server. +Create and automatically renew website SSL certificates using the free [letsencrypt](https://letsencrypt.org/) certificate authority, and its client [*certbot*](https://certbot.eff.org/), built on top of the [nginx](https://www.nginx.com/) webserver. -# More information - -Find out more about letsencrypt: https://letsencrypt.org - -Certbot github: https://github.com/certbot/certbot - -This repository was originally forked from `@henridwyer`, many thanks to him for the good idea. I've rewritten about 90% of this repository, so it bears almost no resemblance to the original. This repository is _much_ more opinionated about the structure of your webservers/containers, however it is easier to use as long as all of your webservers follow that pattern. +This repository was originally forked from `@henridwyer`, many thanks to him for the good idea. It has since been completely rewritten, and bears almost no resemblance to the original. This repository is _much_ more opinionated about the structure of your webservers/containers, however it is easier to use as long as all of your webservers follow the given pattern. # Usage Create a config directory for your custom configs: -``` -mkdir conf.d + +```bash +$ mkdir conf.d ``` And a `.conf` in that directory: @@ -36,19 +31,62 @@ version: '3' services: frontend: restart: unless-stopped - build: frontend + image: staticfloat/nginx-certbot ports: - 80:80/tcp - 443:443/tcp environment: - - CERTBOT_EMAIL=owner@company.com + CERTBOT_EMAIL: owner@company.com volumes: - - ./conf.d:/etc/nginx/user.conf.d :ro - ... + - ./conf.d:/etc/nginx/user.conf.d:ro + - letsencrypt:/etc/letsencrypt +volumes: + letsencrypt: +``` + +Launch that docker-compose file, and you're good to go; `certbot` will automatically request an SSL certificate for any `nginx` sites that look for SSL certificates in `/etc/letsencrypt/live`, and will automatically renew them over time. + +## Templating + +You may wish to template your configurations, e.g. passing in a hostname so as to be able to run multiple identical copies of this container; one per website. The docker container will use [`envsubst`](https://www.gnu.org/software/gettext/manual/html_node/envsubst-Invocation.html) to template all mounted user configs with a user-provided list of environment variables. Example: + +```nginx +# In conf.d/nginx_template.conf +server { + listen 443 ssl; + server_name ${FQDN}; + ssl_certificate /etc/letsencrypt/live/${FQDN}/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/${FQDN}/privkey.pem; + + ... +} +``` + +```yml +version: '3' +services: + frontend: + restart: unless-stopped + image: staticfloat/nginx-certbot + ports: + - 80:80/tcp + - 443:443/tcp + environment: + CERTBOT_EMAIL: owner@company.com + ENVSUBST_VARS: FQDN + FQDN: server.company.com + volumes: + - ./conf.d:/etc/nginx/user.conf.d:ro + - letsencrypt:/etc/letsencrypt +volumes: + letsencrypt: ``` # Changelog +### 1.0 +- Many improvements thanks to contributors from across the globe. Together, we have drastically reduced the amount of customization needed; configs can be mounted directly into a prebuilt image, and the configurations can even be templated. + ### 0.8 - Ditch cron, it never liked me anway. Just use `sleep` and a `while` loop instead. diff --git a/src/scripts/entrypoint.sh b/src/scripts/entrypoint.sh index b2f5fc4..abeb2c1 100644 --- a/src/scripts/entrypoint.sh +++ b/src/scripts/entrypoint.sh @@ -8,7 +8,7 @@ trap "kill 0" EXIT . $(cd $(dirname $0); pwd)/util.sh # first include any user configs if they've been mounted -link_user_configs +template_user_configs # Immediately run auto_enable_configs so that nginx is in a runnable state auto_enable_configs diff --git a/src/scripts/util.sh b/src/scripts/util.sh index 00d576b..6dd7b6d 100644 --- a/src/scripts/util.sh +++ b/src/scripts/util.sh @@ -93,20 +93,26 @@ is_renewal_required() { [ $is_finshed_week_sec -lt 0 ] } -# symlinks any *.conf files in /etc/nginx/user.conf.d +# copies any *.conf files in /etc/nginx/user.conf.d # to /etc/nginx/conf.d so they are included as configs # this allows a user to easily mount their own configs -link_user_configs() { +# We make use of `envsubst` to allow for on-the-fly templating +# of the user configs. +template_user_configs() { SOURCE_DIR="${1-/etc/nginx/user.conf.d}" TARGET_DIR="${2-/etc/nginx/conf.d}" - echo "symlinking scripts from ${SOURCE_DIR} to ${TARGET_DIR}" + # envsubst needs dollar signs in front of all variable names + DENV=$(echo ${ENVSUBST_VARS} | sed -E 's/\$*([^ ]+)/\$\1/g') + + echo "templating scripts from ${SOURCE_DIR} to ${TARGET_DIR}" + echo "Substituting variables ${DENV}" if [ ! -d "$SOURCE_DIR" ]; then echo "no ${SOURCE_DIR}, nothing to do." else for conf in ${SOURCE_DIR}/*.conf; do - ln -sv "${conf}" "${TARGET_DIR}/$(basename ${conf})" + envsubst "${DENV}" <"${conf}" > "${TARGET_DIR}/$(basename ${conf})" done fi }