Commit Graph

3 Commits

Author SHA1 Message Date
Debian
1d06b28064 feat: HA-Cluster v1.2.x — Split-Brain, TOTP, Enterprise-FW, Drift-Fix, VIP-Recovery
- keepalived: pg_role='standby' hat Vorrang vor role für BACKUP-Bestimmung
- keepalived-master.sh: gecrasht Dienste beim MASTER-Übergang starten (nicht nur reload)
- confighash: ip_addresses per Interface-Name hashen statt per FK (Cross-Node-Drift-Fix)
- TOTP/2FA: RFC 6238 — Setup-Flow, QR-Code, Admin-Disable; two-step Login
- Firewall-UI: Enterprise-Design — auto-Beschreibung, icon-only Actions, zero-hit Indikator
- fe80-Filter: Link-local IPv6 aus NTP/DNS Listen-Dropdowns entfernen
- VIP-Dashboard, Dual-Path VRRP, GW-Tracking (Migrations 0033/0034)
- Forward Proxy + DNS erweiterte Einstellungen (Migrations 0031/0032)
- unbound-control: edgeguard in unbound-Gruppe via postinst

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-31 18:18:31 +02:00
Debian
25c7cd0cb5 feat(cluster): PG Logical Replication + VIP/Keepalived + config_hash sync (v1.2.1–1.2.2)
- PG Logical Replication: edgeguard_shared PUBLICATION auf Primary,
  edgeguard_sub SUBSCRIPTION auf Secondary. Nur geteilte Config-Tabellen
  werden repliziert; node-eigene Daten (network_interfaces, ip_addresses,
  static_routes, cluster_settings, dns_settings, ntp_settings) bleiben
  lokal — OPNsense-Muster.
- cluster-init-replication: Erstellt PUBLICATION, Rolle + pg_hba-Einträge
  (logical + replication), WAL-Level auf logical.
- cluster-setup-standby: Erstellt SUBSCRIPTION (copy_data=true), pollt
  pg_subscription_rel bis alle Tabellen sync = 'r', rendert dann Configs.
- promote: manueller Failover via pg_promote() + touch recovery.signal.
- VIP/Keepalived: cluster_settings-Tabelle (vip_address, vip_interface,
  vrrp_router_id), /cluster/vip-settings API, Keepalived-Config-Generator
  mit VRRP + check_script + notify-Skripten in /usr/lib/edgeguard/scripts/.
- config_hash sync: Secondary pusht alle 5 Min seinen Hash via mTLS an
  Primary (PushSelfToPrimary). Heartbeat schreibt nur LOCAL, daher ohne
  aktiven Push wäre Primary-Sicht des Secondary-Hash stale gewesen.
- runSecondaryConfigRender: Goroutine auf Secondary rendert HAProxy+nftables
  neu wenn config_hash sich ändert (Logical-Replication-Nachzügler).
- confighash: node-spezifische Tabellen aus hashSpec entfernt.
- postinst: Keepalived-Skripte installieren, sudoers für keepalived.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-29 23:40:37 +02:00
Debian
e07b484a48 feat(cluster): Config-Hash-Compute für Drift-Detection
Setzt die Foundation aus 1.0.70 fort — bisher war ha_nodes.config_hash
noch NULL und das UI konnte keinen Drift erkennen.

internal/cluster/confighash.go:
  - ComputeConfigHash() berechnet SHA-256 (truncated auf 16 hex chars)
    über alle replizierbaren Tabellen. Pattern 1:1 aus mail-gateway/
    internal/handlers/cluster_status.go (driftHashSpec).
  - Pro Tabelle: md5((to_jsonb(t) - id - updated_at - created_at -
    excludes)::text) per row, dann string_agg ORDER BY rh.
  - Singleton-Tabellen (dns_settings, ntp_settings, mail_config-Stil)
    hashen direkt ohne agg.
  - 23 Tabellen: domains, backends, backend_servers, routing_rules,
    network_interfaces, ip_addresses, tls_certs (mit ExtraExclude
    last_renewed_at + last_error damit cert-renewal keinen drift
    erzeugt), firewall_zones+address_objects+address_groups+services+
    service_groups+rules+nat_rules, wireguard_interfaces+peers,
    forward_proxy_acls, dns_zones+records+settings, ntp_pools+settings,
    static_routes.
  - RefreshLocalHash() schreibt den Hash in die eigene ha_nodes-Row.

Scheduler:
  - 5-min-Tick ruft RefreshLocalHash. Pro-Mutation-Refresh wäre zu
    teuer (jede UI-Action triggert sonst 23 jsonb-Queries).
  - Initial-Refresh beim Scheduler-Boot damit /cluster/status nicht
    5 min auf den ersten Wert wartet.

handlers/cluster.go:
  - Status() ruft RefreshLocalHash mit 2s-Timeout on-demand. Damit
    sieht das UI auch zwischen den Scheduler-Ticks immer frische
    Werte; bei Timeout fallback auf den DB-Wert (eventuell stale).

Verifiziert auf 1.0.71: ha_nodes-Row hat config_hash=728834dce5ca4e48,
scheduler-log "config-hash refresh enabled tick=5m0s".

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-13 08:33:42 +02:00