Fix certificate renewal to properly update HAProxy combined certificate files
All checks were successful
HAProxy Manager Build and Push / Build-and-Push (push) Successful in 1m4s

After certbot renews certificates, the separate fullchain.pem and privkey.pem
files must be combined into a single .pem file for HAProxy. The renewal script
was missing this critical step, causing HAProxy to continue using old certificates.

Changes:
- Add update_combined_certificates() function to renew-certificates.sh
- Query database for all SSL-enabled domains
- Combine Let's Encrypt cert + key files using cat (matches haproxy_manager.py pattern)
- Always update combined certs after renewal, even if certbot says no renewal needed
- Add new sync-certificates.sh script for syncing all existing certificates
- Smart update detection in sync script (only updates when source is newer)

This ensures HAProxy always gets properly formatted certificate files after renewal.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2025-11-11 20:10:58 -08:00
parent 7eeba0d718
commit 8d732318b4
2 changed files with 297 additions and 5 deletions

View File

@@ -9,6 +9,8 @@ set -e
LOG_FILE="${LOG_FILE:-/var/log/haproxy-manager.log}"
ERROR_LOG_FILE="${ERROR_LOG_FILE:-/var/log/haproxy-manager-errors.log}"
HAPROXY_SOCKET="${HAPROXY_SOCKET:-/tmp/haproxy-cli}"
DB_FILE="${DB_FILE:-/etc/haproxy/haproxy_config.db}"
SSL_CERTS_DIR="${SSL_CERTS_DIR:-/etc/haproxy/certs}"
MAX_RETRIES=3
RETRY_DELAY=5
@@ -74,6 +76,80 @@ reload_haproxy() {
return 1
}
# Update combined certificate files for HAProxy
update_combined_certificates() {
log_info "Updating combined certificate files for HAProxy"
# Check if database exists
if [ ! -f "$DB_FILE" ]; then
log_error "Database file not found at $DB_FILE"
return 1
fi
# Check if sqlite3 is available
if ! command -v sqlite3 &> /dev/null; then
log_error "sqlite3 command not found"
return 1
fi
# Ensure SSL certs directory exists
mkdir -p "$SSL_CERTS_DIR"
# Get all domains with SSL enabled from database
local domains
domains=$(sqlite3 "$DB_FILE" "SELECT domain, ssl_cert_path FROM domains WHERE ssl_enabled = 1;" 2>/dev/null)
if [ -z "$domains" ]; then
log_info "No SSL-enabled domains found in database"
return 0
fi
local updated_count=0
local error_count=0
# Process each domain
while IFS='|' read -r domain cert_path; do
if [ -z "$domain" ] || [ -z "$cert_path" ]; then
continue
fi
log_info "Processing certificate for domain: $domain"
local letsencrypt_cert="/etc/letsencrypt/live/${domain}/fullchain.pem"
local letsencrypt_key="/etc/letsencrypt/live/${domain}/privkey.pem"
# Check if Let's Encrypt certificate files exist
if [ ! -f "$letsencrypt_cert" ]; then
log_warning "Certificate not found for $domain at $letsencrypt_cert"
error_count=$((error_count + 1))
continue
fi
if [ ! -f "$letsencrypt_key" ]; then
log_warning "Private key not found for $domain at $letsencrypt_key"
error_count=$((error_count + 1))
continue
fi
# Combine certificate and key into single file for HAProxy
if cat "$letsencrypt_cert" "$letsencrypt_key" > "$cert_path"; then
log_info "Updated combined certificate for $domain at $cert_path"
updated_count=$((updated_count + 1))
else
log_error "Failed to combine certificate files for $domain"
error_count=$((error_count + 1))
fi
done <<< "$domains"
log_info "Certificate update completed: $updated_count updated, $error_count errors"
if [ $error_count -gt 0 ]; then
return 1
fi
return 0
}
# Main renewal process
log_info "Starting certificate renewal process"
@@ -84,17 +160,29 @@ if certbot renew --quiet --no-random-sleep-on-renew 2>&1 | tee -a "$LOG_FILE"; t
if [ $RENEWAL_EXIT_CODE -eq 0 ]; then
log_info "Certificate renewal completed successfully"
# Check if any certificates were actually renewed
if grep -q "Cert not yet due for renewal" "$LOG_FILE" 2>/dev/null; then
log_info "No certificates needed renewal at this time"
else
log_info "Certificates were renewed, reloading HAProxy"
# Always update combined certificate files after renewal
# (certbot may have renewed some certificates even if the message says otherwise)
log_info "Updating combined certificate files for HAProxy"
if update_combined_certificates; then
log_info "Combined certificates updated successfully"
# Reload HAProxy to pick up the updated certificates
log_info "Reloading HAProxy"
if reload_haproxy; then
log_info "Certificate renewal and HAProxy reload completed successfully"
else
log_error "Certificate renewal succeeded but HAProxy reload failed"
exit 1
fi
else
log_warning "Certificate update completed with some errors, but attempting HAProxy reload"
# Still try to reload HAProxy even if some certificates failed
if reload_haproxy; then
log_warning "HAProxy reloaded successfully despite certificate update errors"
else
log_error "Certificate update had errors and HAProxy reload failed"
exit 1
fi
fi
else
log_error "Certificate renewal failed with exit code $RENEWAL_EXIT_CODE"