#!/bin/bash # Obtain or renew certificates from letsencrypt, to be used with nginx # webroot verification. # # A certificate will be issued for all server names defined in server # blocks that contain 'include letsencrypt'. set -o errexit opts=$(getopt -o hn --long help,test -n 'nginx-letsencrypt' -- "$@") eval set --"$opts" extra_flags=() while true; do case "$1" in -h|--help) shift echo "Usage: $0 [-n|--test]" exit 0 ;; -n|--test) shift extra_flags+=("--test-cert") ;; --) shift; break ;; *) echo "Internal error!" exit 1 ;; esac done # Any site configuration files that use letsencrypt sites_enabled=($( find /etc/nginx/sites-enabled/ \ -not -type d \ -exec grep -q -e '^[^#]*include letsencrypt' {} \; \ -print)) if [[ ${#sites_enabled[@]} -eq 0 ]]; then # no sites use ssl, exit immediately exit 0 fi # Extract server names from enabled sites host_lines=($(sed --quiet \ 's/^[^#]*server_name \([^_].*\);/\1/p' \ "${sites_enabled[@]}")) hosts=$(echo -n "${host_lines[@]}" | tr "[:space:]" ",") # Make sure that *any* certificate exists so that nginx can start. If # a certificate or key is missing, copy snakeoil certificates instead. function ensure_certificate() { mkdir --parents /etc/letsencrypt/live/nginx cp --no-clobber \ /etc/ssl/private/ssl-cert-snakeoil.key \ /etc/letsencrypt/live/nginx/privkey.pem cp --no-clobber \ /etc/ssl/certs/ssl-cert-snakeoil.pem \ /etc/letsencrypt/live/nginx/fullchain.pem service nginx reload } # Ensure that a certificate exists if this script is encounters an # error. trap ensure_certificate ERR # Issue letsencrypt certificates. Snakeoil certificates that are # required to bootstrap nginx configurations (nginx fails to start # without ssl certificates) are removed. The explicit removal is # required because certbot does not overwrite foreign certificates, as # described in this issue # https://github.com/certbot/certbot/issues/3396 ensure_certificate if ! (openssl x509 -in /etc/letsencrypt/live/nginx/fullchain.pem -noout -text \ | grep --quiet letsencrypt); then rm -r /etc/letsencrypt/live/nginx fi mkdir --parents /var/www/letsencrypt certbot certonly "${extra_flags[@]}" \ --noninteractive \ --agree-tos \ --cert-name nginx \ --webroot --webroot-path /var/www/letsencrypt \ -d "$hosts" ensure_certificate