Gateway-Pool für Failover einrichten
Setup
1. Voraussetzungen
- Mindestens 2 Gateway-Peers angelegt (
/peers, peer_type=gateway) - Beide Gateways müssen die Backend-Hosts in ihrem LAN erreichen können
- Lizenz:
gateway_pools=true(Failover ist meist im Basis-Plan, Load-Balancing oft Pro)
2. Pool anlegen
/gateway-pools → "Pool erstellen":
- Name: Aussagekräftiger Bezeichner (z. B.
Heimnetz) - Modus:
Failover (priorisiert)— primärer Gateway bedient, Backup nimmt nur bei AusfallLoad-Balancing— alle alive Members bedienen parallel (lizenzabhängig)
- LB-Policy (nur Load-Balancing):
round_robin— gleichverteilt nach Reihenfolgeleast_conn— Member mit wenigsten aktiven Verbindungenip_hash— Sticky pro Client-IP (gleicher Client → gleicher Member)
- Failback-Cooldown: Wie lange nach Recovery gewartet wird, bevor Routen zurück wandern. Presets:
60 s— Linux-Container (LXC), schneller Reboot180 s— Linux-VM600 s(10 min) — Proxmox-Host900 s(15 min) — Synology / QNAP NAS1800 s(30 min) — Windows-Server3600 s(60 min) — Konservativ
- Outage-Nachricht (optional): Custom 503-Body, wenn ALLE Member down
3. Member hinzufügen
Im Modal rechts:
- Gateway aus Dropdown wählen → "Hinzufügen"
- Position #1 ist primär (höchste Priorität). Per Drag & Drop sortieren.
- Bereits hinzugefügte Gateways verschwinden aus dem Dropdown (= keine Doppelung möglich)
- "Speichern" persistiert atomar (
PUT /api/v1/gateway-pools/:id/members)
4. Routen verbinden
Bei Failover: Nichts zu tun. Sobald die Route's target_peer_id einem Pool-Member gehört, greift die Failover-Logik beim nächsten state-change automatisch.
Bei Load-Balancing:
/gateway-pools → "Routen migrieren":
- Ziel-Pool auswählen
- Liste zeigt alle Gateway-pinned Routen, gruppiert nach Quell-Peer
- Loopback-Routen (
127.0.0.1) sind gelb markiert + standardmäßig ungecheckt — Begründung:ssh.example.com → 127.0.0.1:22bedeutet "auf der Gateway-Maschine selbst". Wenn das auf einen anderen Member migriert wird, ändert sich die Zielmaschine. - Auswahl prüfen, "OK" → atomarer DB-Update + Caddy-Resync
Alternativ: Routen einzeln über /routes editieren und target_kind: pool, Ziel-Pool wählen.
Failover-Mode im Detail
Mechanismus
Normaler Betrieb:
routes.target_peer_id = 79 (Home)
routes.original_peer_id = NULL
↓
Frontend-Caddy → 10.8.0.8:18080 (Home companion-caddy)
→ 192.168.1.5:5001 (NAS auf Home-LAN)
Home fällt aus:
watchdogTick (alle 30 s) → evaluatePeer → alive=0 → transition='alive_to_down'
↓
_onTransition('alive_to_down', peerId=79):
UPDATE routes
SET target_peer_id = 84, -- DS918, höchste Priorität alive
original_peer_id = 79, -- Quelle merken
updated_at = NOW
WHERE target_peer_id = 79 AND original_peer_id IS NULL AND target_kind = 'gateway'
↓
syncToCaddy() -- Caddy reload mit neuen Upstream
notifyConfigChanged(79) -- Home weiß nichts mehr von den Routen
notifyConfigChanged(84) -- DS918 zieht die Routen jetzt
↓
Frontend-Caddy → 10.8.0.2:18080 (DS918 companion-caddy)
→ 192.168.1.5:5001 (NAS, jetzt von DS918 aus erreicht)
Home recovered:
watchdogTick → cooldown_to_alive → transition fired NACH failback_cooldown_s
↓
_onTransition('cooldown_to_alive', peerId=79):
UPDATE routes
SET target_peer_id = original_peer_id,
original_peer_id = NULL,
updated_at = NOW
WHERE original_peer_id = 79
↓
syncToCaddy() + notifyConfigChanged für 79 + 84
↓
Routen wieder auf Home, normal weiter.
Boot-Reconcile
Transitionen feuern nur bei State-Changes. Wenn ein Peer beim Container-Start bereits offline ist, gibt's kein alive_to_down → kein Pivot. gatewayHealth.reconcileFailoverState() läuft 1× beim Server-Boot und holt das nach:
- Für jeden offline Pool-Member: alive Sibling finden, Routen pivoten
- Für jede Route mit
original_peer_id != NULLderen Original-Peer wieder alive ist: Route zurück migrieren
Damit ist die DB nach Container-Restart konsistent mit dem realen Health-State.
Beobachtbarkeit
Activity-Log-Events:
gateway_down/gateway_alive— State-Change pro Peerpool_failover_activated— Routes wurden auf Sibling pivotet (mitfromPeerId/toPeerId)pool_failover_restored— Routes zurück auf originalen Peerpool_outage_started/pool_outage_resolved— Alle/erster Pool-Member offline
Webhook (falls konfiguriert): gateway_state_change mit Payload {peer_id, alive: bool}.
SQL für aktuellen Stand:
SELECT id, domain, target_peer_id, original_peer_id
FROM routes WHERE target_kind='gateway' AND enabled=1;
Eine Zeile zeigt sofort wer wohin routet — original_peer_id != NULL heißt "aktuell im Failover".
Beispiel-Setup: Heimnetz-Failover
Typische Heim-Konfiguration mit zwei Gateways: ein Synology NAS (DS918, 192.168.2.151) und ein Linux-Mini-PC ("Home", 192.168.2.5). Beide auf demselben LAN, beide erreichen alle Backend-Hosts.
1. /peers → "Home Gateway" und "DS918 Gateway" anlegen, beide enabled
2. /gateway-pools → Pool "Heimnetz" anlegen:
- Modus: Failover
- Failback-Cooldown: 900s (NAS-Preset, weil DS918 längere Updates hat)
- Members: Home (Position #1), DS918 (Position #2)
3. Bestehende Routen brauchen NICHTS — Failover greift automatisch
4. Test:
- DS918 reboot → Home als Primär bleibt online → keine Auswirkung
- Home reboot → Routen wandern zu DS918 → Services bleiben erreichbar
- Home recovered → nach 15 min Cooldown zurück zu Home
Bei reinem Failover bleibst Du bei target_peer_id-Pinning. Erst wenn Du Load-Balancing willst (z. B. Streaming + Backup parallel über beide Gateways), ist die "Routen migrieren"-Funktion nötig.