#!/bin/sh # HAProxy ACME Certificate Background Processor # Processes pending ACME certificate requests via cron # Copyright (C) 2025 CyberMind.fr LOCK_FILE="/var/run/haproxy-acme-cron.lock" LOG_TAG="haproxy-acme-cron" CERTS_PATH="/srv/haproxy/certs" log_info() { logger -t "$LOG_TAG" "$*"; } log_error() { logger -t "$LOG_TAG" -p err "$*"; } # Prevent concurrent execution if [ -f "$LOCK_FILE" ]; then pid=$(cat "$LOCK_FILE" 2>/dev/null) if [ -n "$pid" ] && kill -0 "$pid" 2>/dev/null; then exit 0 fi rm -f "$LOCK_FILE" fi echo $$ > "$LOCK_FILE" trap "rm -f $LOCK_FILE" EXIT # Check if haproxyctl exists [ -x /usr/sbin/haproxyctl ] || exit 0 # Load UCI functions . /lib/functions.sh # Find vhosts that need ACME certificates process_pending_certs() { local pending_domains="" # Callback to check each vhost check_vhost() { local section="$1" local domain acme ssl enabled cert_file config_get domain "$section" domain "" config_get acme "$section" acme "0" config_get ssl "$section" ssl "0" config_get enabled "$section" enabled "1" # Skip if not enabled, no SSL, or no ACME [ "$enabled" != "1" ] && return [ "$ssl" != "1" ] && return [ "$acme" != "1" ] && return [ -z "$domain" ] && return # Check if certificate exists and is valid cert_file="$CERTS_PATH/$domain.pem" if [ ! -f "$cert_file" ]; then log_info "Certificate missing for $domain - queuing for ACME" pending_domains="$pending_domains $domain" elif ! openssl x509 -checkend 604800 -noout -in "$cert_file" 2>/dev/null; then # Certificate expires in less than 7 days log_info "Certificate expiring soon for $domain - queuing for renewal" pending_domains="$pending_domains $domain" fi } config_load haproxy config_foreach check_vhost vhost # Process pending domains for domain in $pending_domains; do log_info "Processing ACME certificate for: $domain" /usr/sbin/haproxyctl cert add "$domain" >/dev/null 2>&1 if [ $? -eq 0 ]; then log_info "Certificate issued successfully for: $domain" else log_error "Failed to issue certificate for: $domain" fi # Small delay between certificate requests sleep 5 done } # Run the processor process_pending_certs