Files
homelab/ansible/playbooks/roles/haproxy/templates/certbot-post-hook.sh.j2
2026-02-25 20:36:50 -06:00

108 lines
3.4 KiB
Django/Jinja

#!/bin/bash
# {{ ansible_managed }}
# Certbot post-renewal hook for HAProxy
# Combines certificate and private key for HAProxy consumption
set -euo pipefail
# Configuration
LETSENCRYPT_LIVE="/etc/letsencrypt/live"
HAPROXY_CERT_DIR="{{ haproxy_ssl_cert_dir }}/live"
HAPROXY_USER="{{ haproxy_user }}"
HAPROXY_GROUP="{{ haproxy_group }}"
LOG_FILE="{{ haproxy_log_dir }}/certbot-hook.log"
# Ensure HAProxy cert directory exists
mkdir -p "$HAPROXY_CERT_DIR"
# Logging function
log() {
echo "[$(date '+%Y-%m-%d %H:%M:%S')] $*" | tee -a "$LOG_FILE"
}
log "Starting certificate deployment for HAProxy"
# Track if any certificates were updated
CERTS_UPDATED=false
# Process each certificate in Let's Encrypt live directory
for cert_dir in "$LETSENCRYPT_LIVE"/*; do
if [ ! -d "$cert_dir" ] || [ "$(basename "$cert_dir")" = "README" ]; then
continue
fi
CERT_NAME=$(basename "$cert_dir")
# Check if certificate files exist
if [ ! -f "$cert_dir/fullchain.pem" ] || [ ! -f "$cert_dir/privkey.pem" ]; then
log "WARNING: Missing certificate files for $CERT_NAME, skipping"
continue
fi
log "Processing certificate: $CERT_NAME"
# Create combined PEM file (fullchain + privkey)
# HAProxy requires the certificate chain and private key in a single file
COMBINED_PEM="$HAPROXY_CERT_DIR/${CERT_NAME}.pem"
# Combine certificates
cat "$cert_dir/fullchain.pem" "$cert_dir/privkey.pem" > "$COMBINED_PEM.tmp"
# Check if certificate actually changed
if [ -f "$COMBINED_PEM" ] && cmp -s "$COMBINED_PEM" "$COMBINED_PEM.tmp"; then
log "Certificate $CERT_NAME unchanged, skipping"
rm "$COMBINED_PEM.tmp"
continue
fi
# Move new certificate into place
mv "$COMBINED_PEM.tmp" "$COMBINED_PEM"
# Set proper permissions
chown "$HAPROXY_USER:$HAPROXY_GROUP" "$COMBINED_PEM"
chmod 600 "$COMBINED_PEM"
log "Created/Updated: $COMBINED_PEM"
CERTS_UPDATED=true
done
# Create/update default certificate symlink
# Use the first wildcard cert or the first available cert as default
DEFAULT_CERT="{{ haproxy_ssl_default_crt }}"
WILDCARD_CERT="$HAPROXY_CERT_DIR/local.mk-labs.cloud.pem"
if [ -f "$WILDCARD_CERT" ]; then
ln -sf "$WILDCARD_CERT" "$DEFAULT_CERT"
log "Updated default certificate symlink to wildcard cert"
elif [ -n "$(ls -A "$HAPROXY_CERT_DIR" 2>/dev/null)" ]; then
FIRST_CERT=$(ls "$HAPROXY_CERT_DIR"/*.pem 2>/dev/null | head -n1)
ln -sf "$FIRST_CERT" "$DEFAULT_CERT"
log "Updated default certificate symlink to $FIRST_CERT"
fi
# Only reload HAProxy if certificates were actually updated
if [ "$CERTS_UPDATED" = true ]; then
log "Certificates updated, validating HAProxy configuration"
# Validate HAProxy configuration
if haproxy -c -f {{ haproxy_config_dir }}/haproxy.cfg >/dev/null 2>&1; then
log "HAProxy configuration valid, reloading service"
if systemctl reload haproxy; then
log "HAProxy reloaded successfully"
else
log "ERROR: Failed to reload HAProxy"
exit 1
fi
else
log "ERROR: HAProxy configuration validation failed"
haproxy -c -f {{ haproxy_config_dir }}/haproxy.cfg 2>&1 | tee -a "$LOG_FILE"
exit 1
fi
else
log "No certificates were updated, skipping HAProxy reload"
fi
log "Certificate deployment complete"
exit 0