Files
certbot/docker/scripts/0-create-cert.sh
T
bitdeals 36e1865e37
Build docker image and push to registry.bitdeals.org / main-build-job (push) Successful in 30s
feat: CERTBOT_DOMAIN may name several domains
certbot's own -d already takes a comma-separated list and puts every name
in the certificate's Subject Alternative Names, so `-d "$CERTBOT_DOMAIN"`
needed no change at all. What assumed a single domain was everything that
treated the variable as a *file name*: --cert-name, and the two scripts
that address the lineage under /etc/letsencrypt/live. Certbot names a
lineage after the first domain of the list, so all three now take
${CERTBOT_DOMAIN%%,*} instead of the whole string -- otherwise a two-domain
value asks for a lineage literally called "a.org,b.org" and the renewal
pass looks for a directory nobody made.

One certificate with several names rather than several lineages: HAProxy
binds a single site.pem, and a second lineage would have nowhere to go.

Adding a domain to CERTBOT_DOMAIN on a machine that already holds a
certificate still needs one manual issuance -- `certbot renew` reads the
names off the certificate it has and never looks at the variable. The
README says so, and gives the command.
2026-08-20 11:53:12 +00:00

65 lines
2.3 KiB
Bash

#!/bin/sh
set -e
if [ ! -f /etc/certificates/site.pem ]; then
# Self-signed placeholder, so HAProxy can bind :443 before a real certificate
# exists. Built inside a subshell: this script is sourced, so a bare cd or
# umask would change the caller's shell too. Relative paths used to resolve
# against the working directory (/opt/certbot) and left the private key there
# for good; here they resolve against the volume the key belongs on, and the
# intermediates are removed before site.pem appears.
(
umask 077
cd /etc/certificates
openssl req -x509 -newkey rsa:2048 -nodes -days 365 -batch \
-subj "/CN=${CERTBOT_DOMAIN:-localhost}" \
-keyout site.key.tmp -out site.crt.tmp
cat site.key.tmp site.crt.tmp > site.pem.tmp
rm -f site.key.tmp site.crt.tmp
# Last and atomic: HAProxy reads site.pem at start-up and must never find
# it half-written.
mv site.pem.tmp site.pem
)
fi
# Wait for haproxy: Let's Encrypt reaches this container's challenge server only
# through it, so asking for a certificate first would just fail validation. The
# runtime API socket appearing is the signal — HAProxy creates it once the
# configuration has parsed and the binds have succeeded. Waiting on the socket
# rather than a TCP probe also means there is no port left to probe.
HAPROXY_SOCKET=/var/lib/haproxy/admin.sock
while [ ! -S "$HAPROXY_SOCKET" ]; do
echo "Waiting for $HAPROXY_SOCKET..."
sleep 7
done
if [ -n "$CERTBOT_DOMAIN" ]; then
# E-mail for Let's Encrypt expiry notices. Built with set -- so that the flag
# and its value stay two separate arguments: a single "$CERTBOT_OPTS" word
# reached certbot as one token ("--email you@example.org") and was rejected
# as an unknown argument, which failed every issuance with an address set.
# The entrypoint passes no positional parameters, so there are none to lose.
if [ -n "$CERTBOT_EMAIL" ]; then
set -- --email "$CERTBOT_EMAIL"
else
set -- --register-unsafely-without-email
fi
# Request certificate
certbot certonly --standalone \
--non-interactive --agree-tos --http-01-port=380 \
"$@" \
--cert-name "${CERTBOT_DOMAIN%%,*}" \
-d "$CERTBOT_DOMAIN"
# Concatenate certificates
. $(dirname $0)/2-concatenate-cert.sh
fi
# Update certificates in HAProxy
. $(dirname $0)/3-update-haproxy-cert.sh