ci: make TLS provisioning dynamic as domains are added
Adding a domain was a manual per-domain script run. With domains arriving continuously that does not hold, so certificate issuance is now automatic. HTTP already needed no work: the nginx catch-all serves any Host and the SPA resolves its tenant from that header. Only TLS needed a name-by-name step. Two mechanisms: - setup-wildcard-tls.sh issues one DNS-01 wildcard for *.<apex>, after which a new tenant subdomain is live over HTTPS with zero certificate work. - sync-domains.sh reconciles tenant-owned domains against a desired list on a 10-minute timer: issues what is missing, skips certificates with >30 days left, skips names already covered by the wildcard, waits out unpropagated DNS, and caps issuance per run so a bad source cannot burn the weekly ACME budget. Safety properties worth stating: a failed fetch of the desired list aborts the run rather than reading as "remove every domain"; removing a domain disables its server block but keeps the certificate, so re-adding is instant; malformed hostnames are rejected before reaching certbot or an nginx server_name. The source is pluggable - a file today, the Phase 9 domain registry once it exists, whose MarketplaceDomain statuses already match what this needs. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -29,7 +29,7 @@ done
|
||||
echo "==> packages"
|
||||
export DEBIAN_FRONTEND=noninteractive
|
||||
apt-get update -qq
|
||||
apt-get install -y -qq nginx certbot python3-certbot-nginx rsync ufw
|
||||
apt-get install -y -qq nginx certbot python3-certbot-nginx rsync ufw jq curl openssl
|
||||
|
||||
echo "==> deploy user: $DEPLOY_USER"
|
||||
if ! id -u "$DEPLOY_USER" >/dev/null 2>&1; then
|
||||
@@ -133,6 +133,45 @@ nginx -t
|
||||
systemctl enable --now nginx
|
||||
systemctl reload nginx
|
||||
|
||||
echo "==> dynamic domain reconciler"
|
||||
SRC_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
install -d -m 755 "$BASE/bin" /etc/marketplaces "/var/lib/marketplaces"
|
||||
if [[ -f "$SRC_DIR/sync-domains.sh" ]]; then
|
||||
install -m 755 "$SRC_DIR/sync-domains.sh" "$BASE/bin/sync-domains.sh"
|
||||
|
||||
if [[ ! -f /etc/marketplaces/domains.env ]]; then
|
||||
cat > /etc/marketplaces/domains.env <<'ENVFILE'
|
||||
# Where the desired domain list comes from.
|
||||
# file:/etc/marketplaces/domains.txt one hostname per line
|
||||
# https://api.example.com/api/admin/v2/domains JSON, once the backend exists
|
||||
DOMAINS_SOURCE=file:/etc/marketplaces/domains.txt
|
||||
|
||||
# Required: certbot expiry notices.
|
||||
CERTBOT_EMAIL=
|
||||
|
||||
# Cap per run so a bad source cannot burn the weekly ACME budget in one pass.
|
||||
MAX_ISSUE_PER_RUN=10
|
||||
|
||||
# Set by setup-wildcard-tls.sh. Subdomains of this apex skip per-domain issuance.
|
||||
#WILDCARD_APEX=
|
||||
ENVFILE
|
||||
chmod 600 /etc/marketplaces/domains.env
|
||||
fi
|
||||
touch /etc/marketplaces/domains.txt
|
||||
|
||||
if [[ -d "$SRC_DIR/systemd" ]]; then
|
||||
install -m 644 "$SRC_DIR/systemd/marketplaces-domains.service" /etc/systemd/system/
|
||||
install -m 644 "$SRC_DIR/systemd/marketplaces-domains.timer" /etc/systemd/system/
|
||||
systemctl daemon-reload
|
||||
# Not started yet: CERTBOT_EMAIL is still blank. Enable it after filling in
|
||||
# /etc/marketplaces/domains.env, or the first run just fails on every tick.
|
||||
echo " timer installed but NOT started - set CERTBOT_EMAIL first, then:"
|
||||
echo " systemctl enable --now marketplaces-domains.timer"
|
||||
fi
|
||||
else
|
||||
echo " sync-domains.sh not found next to this script - skipping"
|
||||
fi
|
||||
|
||||
echo "==> sudoers: let the deploy user reload nginx, nothing else"
|
||||
cat > /etc/sudoers.d/marketplaces-deploy <<SUDO
|
||||
$DEPLOY_USER ALL=(root) NOPASSWD: /bin/systemctl reload nginx
|
||||
|
||||
Reference in New Issue
Block a user