#!/bin/sh if test -z "${NODES}" && test -z "${SINGLE_NODE}"; then echo "The env var NODES is empty, if you don't want to synchronize to other servers, set SINGLE_NODE=true" >&2 exit 1 fi lock=/tmp/certbot.lck updated=/tmp/certbot.updated ensure() { test -n "$1" && echo "$1 received, exiting gracefully..." rm -f "${lock}" test -f "${updated}" || exit 0 rm -f "${updated}" # Fix permissions, users in group ssl have read access find /etc/letsencrypt -type d | xargs -r chmod 2750 find /etc/letsencrypt -type f | xargs -r chmod 640 chgrp -R ssl /etc/letsencrypt ${SINGLE_NODE:-false} && exit 0 # Push certificates to nodes, we use SSH as a secure transport # but this means we're synchronizing from container to host which is # awkward. A restricted rsync treats / as the remote location for the # certificates. for NODE in ${NODES}; do rsync -avHAXL --delete-after /etc/letsencrypt/live/ ${NODE}/ done } for SIG in TERM QUIT INT HUP; do trap "ensure ${SIG}" ${SIG} done set -e case $1 in # Renew certificates, trust in certbot's algorithms renew) /usr/bin/certbot renew --quiet --agree-tos || true touch "${updated}" ;; bootstrap) test -d "/etc/letsencrypt/live/${SUTTY}" && exit 0 # Get a single certificate for the whole domain /usr/bin/certbot \ certonly \ --non-interactive \ --authenticator "dns-standalone" \ --email "certbot@${SUTTY}" \ --agree-tos \ -d "${SUTTY}" \ -d "*.${SUTTY}" \ -d "*.testing.${SUTTY}" touch "${updated}" ;; prune) comm -13 <(realpath /etc/letsencrypt/live/*/*.pem | sort) <(find /etc/letsencrypt/archive/ -name "*.pem" | sort) | xargs rm -v touch "${updated}" ;; # Generate certificates *) # Only one instance can run at a time if test -f "${lock}" ; then echo "There's a certbotd instance already running, doing nothing..." >&2 echo "If the problem persists, you may need to remove ${lock} manually." >&2 exit 1 fi touch "${lock}" # Save headers here headers=/tmp/headers # Gets ETag from previous headers test -f "${headers}" \ && etag="$(grep "^ Etag: " "${headers}" | cut -d : -f 2)" # Get site list from the API and transform to a list. Save headers # for next run. Use ETag to avoid running when nothing changed wget --user="${HTTP_BASIC_USER}" --password="${HTTP_BASIC_PASSWORD}" \ --header="If-None-Match:${etag}" -qSO - \ "https://api.${SUTTY}/v1/sites.json" \ 2>"${headers}" \ | jq --raw-output .[] \ | while read domain; do # Skip already existing domains test -d "/etc/letsencrypt/live/${domain}" && continue # Ignore non local domains if ! nslookup "${domain}" 8.8.8.8 | grep -qE "(${SUTTY_ADDRESSES// /|})" ; then echo "${domain} is not configured to any Sutty node or DNS records are still cached, ignoring for now" continue fi # Get the certificate for the domain, the webserver will need # access to this directory /usr/bin/certbot certonly --email "certbot@${SUTTY}" \ -n \ --webroot \ --agree-tos \ --webroot-path /var/lib/letsencrypt \ -d "${domain}" touch "${updated}" done esac ensure