#!/bin/sh set -eu . /usr/libexec/haproxy-manager/common.sh umask 077 LOCK_DIR=/var/lock/haproxy-manager.apply LOCK_BUSY_EXIT=75 TMP_CFG="/tmp/haproxy-manager-apply.$$" BACKUP_ID="" APPLIED=0 UHTTPD_CHANGED=0 if [ "${1:-}" = --backup ]; then BACKUP_ID="${2:-}" [ "$#" -eq 2 ] || { echo "Usage: apply [--backup YYYYMMDD-HHMMSS]" >&2; exit 1; } is_valid_backup_id "$BACKUP_ID" || { echo "Invalid backup identifier" >&2; exit 1; } elif [ "$#" -ne 0 ]; then echo "Usage: apply [--backup YYYYMMDD-HHMMSS]" >&2 exit 1 fi operation_lock_acquire "$LOCK_DIR" || { echo "Another HAProxy Manager operation is already running." >&2 exit "$LOCK_BUSY_EXIT" } cleanup_temp() { rm -f "$TMP_CFG" } release_lock() { operation_lock_release "$LOCK_DIR" } cleanup() { cleanup_temp release_lock } restore_on_error() { status=$? trap - EXIT if [ "$APPLIED" != 1 ] && [ -n "$BACKUP_ID" ]; then if [ "$UHTTPD_CHANGED" = 1 ]; then cleanup_temp ( sleep 2 if /usr/libexec/haproxy-manager/rollback --sync "$BACKUP_ID" >/dev/null 2>&1; then logger -t haproxy-manager "Apply failed; restored $BACKUP_ID" else logger -t haproxy-manager "Apply failed; could not restore $BACKUP_ID" fi release_lock ) >/dev/null 2>&1 & operation_lock_set_pid "$LOCK_DIR" "$!" exit "$status" fi if /usr/libexec/haproxy-manager/rollback --sync "$BACKUP_ID" >/dev/null 2>&1; then logger -t haproxy-manager "Apply failed; restored $BACKUP_ID" else logger -t haproxy-manager "Apply failed; could not restore $BACKUP_ID" fi fi cleanup exit "$status" } trap restore_on_error EXIT if [ -n "$BACKUP_ID" ]; then [ -d "$(backup_dir)/$BACKUP_ID" ] || { echo "Backup not found: $BACKUP_ID" >&2; exit 1; } else BACKUP_ID="$(basename "$(/usr/libexec/haproxy-manager/backup)")" fi /usr/libexec/haproxy-manager/migrate >/dev/null defer_disabled_reload() { APPLIED=1 trap - EXIT cleanup_temp ( sleep 2 if /etc/init.d/uhttpd reload >/dev/null 2>&1; then logger -t haproxy-manager "LuCI listener bindings restored" else if /usr/libexec/haproxy-manager/rollback --sync "$BACKUP_ID" >/dev/null 2>&1; then logger -t haproxy-manager "LuCI reload failed; restored $BACKUP_ID" else logger -t haproxy-manager "LuCI reload failed; could not restore $BACKUP_ID" fi fi release_lock ) >/dev/null 2>&1 & operation_lock_set_pid "$LOCK_DIR" "$!" } if [ "$(uci_get main enabled 0)" != 1 ]; then MODE="$(active_mode)" restore_uhttpd_bindings [ "$UHTTPD_CHANGED" != 1 ] || uci commit uhttpd /usr/libexec/haproxy-manager/firewall-sync --disable >/dev/null case "$MODE" in generated|raw) /etc/init.d/haproxy stop >/dev/null 2>&1 || true /etc/init.d/haproxy disable >/dev/null 2>&1 || true uci set "$CONFIG.main.active_mode=none" uci commit "$CONFIG" ;; esac if [ "$UHTTPD_CHANGED" = 1 ]; then defer_disabled_reload echo "Managed HAProxy service disabled. LuCI bindings will be restored shortly. Backup: $BACKUP_ID" exit 0 fi APPLIED=1 trap - EXIT cleanup echo "Managed HAProxy service disabled. Backup: $BACKUP_ID" exit 0 fi /usr/libexec/haproxy-manager/generate "$TMP_CFG" >/dev/null /usr/libexec/haproxy-manager/validate "$TMP_CFG" if [ "$(uci_get main manage_firewall 0)" = 1 ]; then /usr/libexec/haproxy-manager/firewall-sync --check >/dev/null fi MANAGE_UHTTPD="$(uci_get main manage_uhttpd_bind 0)" LAN_BIND_IP="$(lan_ip || true)" if [ "$MANAGE_UHTTPD" = 1 ]; then [ -n "$LAN_BIND_IP" ] || { echo "Cannot detect LAN IPv4 address. Set the LuCI LAN address manually." >&2; exit 1; } is_valid_ip_or_host "$LAN_BIND_IP" || { echo "Invalid LuCI LAN address: $LAN_BIND_IP" >&2; exit 1; } capture_uhttpd_bindings set_uhttpd_list listen_http "$LAN_BIND_IP:80" set_uhttpd_list listen_https "$LAN_BIND_IP:443" else restore_uhttpd_bindings fi [ "$UHTTPD_CHANGED" != 1 ] || uci commit uhttpd /usr/libexec/haproxy-manager/firewall-sync >/dev/null atomic_install_file "$TMP_CFG" "$HAPROXY_CFG" uci set "$CONFIG.main.active_mode=generated" uci commit "$CONFIG" /etc/init.d/haproxy enable >/dev/null 2>&1 || true if [ "$UHTTPD_CHANGED" = 1 ]; then APPLIED=1 trap - EXIT cleanup_temp ( sleep 2 if /etc/init.d/uhttpd reload >/dev/null 2>&1 && /etc/init.d/haproxy restart >/dev/null 2>&1; then logger -t haproxy-manager "LuCI and HAProxy reloaded successfully" else if /usr/libexec/haproxy-manager/rollback --sync "$BACKUP_ID" >/dev/null 2>&1; then logger -t haproxy-manager "Service reload failed; restored $BACKUP_ID" else logger -t haproxy-manager "Service reload failed; could not restore $BACKUP_ID" fi fi release_lock ) >/dev/null 2>&1 & operation_lock_set_pid "$LOCK_DIR" "$!" echo "Applied successfully. LuCI and HAProxy will reload shortly. Backup: $BACKUP_ID" exit 0 fi /etc/init.d/haproxy restart APPLIED=1 trap - EXIT cleanup echo "Applied successfully. Backup: $BACKUP_ID"