diff --git a/docs/tp31-schritt5-runbook.md b/docs/tp31-schritt5-runbook.md new file mode 100644 index 0000000..440830e --- /dev/null +++ b/docs/tp31-schritt5-runbook.md @@ -0,0 +1,176 @@ +# TP31 Schritt 5 — Runbook: cloudflared auf ap1/ap2 + CNAME-Flip +# Stand 2026-08-27 — vorbereitet, nicht ausgeführt. +# +# ⚠️ device-mode-Wechsel ist NICHT remote möglich — erfordert physischen +# Mode-Button-Druck an jedem AP, danach Reboot. Dieser Runbook-Teil muss +# vor Ort ausgeführt werden. + +## 0. IST-STAND (live gelesen 2026-08-27) +- Tunnel **bf-public** `48d3b0b6` ✅: Ingress mit 4 öffentlichen Hostnames → `10.40.20.40:80` +- Token: `~/.secrets/credentials.env` → `BF_PUBLIC_TUNNEL_TOKEN` +- Config-Dateien: `routeros/cloudflared/credentials.json`, `cloudflared-bf-public-config.yml`, `ap-bootstrap.rsc` +- Firewall: Regel 27 `MGMT→INFRA TCP` deckt `vlan99→vlan20:80` bereits ab ✅ +- Alte Tunnel: bf-mm (n8n, n8n-mcp, gitea-mcp, pbs), bf-nas (gitea, grafana, pve-mcp, vw, ds-bf), bf-pve (pve, ccu, iobroker, z2m25, portainer, hass, ha-mcp) + +## 1. DEVICE-MODE-WECHSEL (physisch, vor Ort) + +### 1a. Container-Paket checken +``` +/system package print where name="container" +``` +Falls nicht installiert: Winbox → System → Packages → Check For Updates → container aktivieren. + +### 1b. device-mode ändern +``` +/system device-mode update container=yes +``` +Das Gerät fordert auf, den Mode-Button zu drücken. Am hAP ax² ist das der +Knopf an der Front. Nach Drücken: „configuration changed, reboot required". + +### 1c. Reboot +``` +/system reboot +``` + +### 1d. Prüfen +``` +/system device-mode print +# output muss zeigen: container: yes +``` + +## 2. CONTAINER BOOTSTRAP (auf JEDEM AP einzeln) + +### 2a. Backup +``` +/system backup save name=vor-tp31-apX +``` + +### 2b. Dateien hochladen (via SFTP, Port 22) +```bash +# ap1 (10.40.99.11) +sftp admin@10.40.99.11 <<'EOF' +put routeros/cloudflared/credentials.json flash/ +put routeros/cloudflared-bf-public-config.yml flash/ +EOF + +# ap2 (10.40.99.12) +sftp admin@10.40.99.12 <<'EOF' +put routeros/cloudflared/credentials.json flash/ +put routeros/cloudflared-bf-public-config.yml flash/ +EOF +``` + +### 2c. Bootstrap-Script importieren + ausführen +``` +/import routeros/cloudflared/ap-bootstrap.rsc +``` + +Falls `/import` Probleme macht: Zeilen einzeln per SSH absetzen. + +### 2d. Abnahme +``` +/container print +# Status muss "started" sein +/log print where message~"cloudflared" +# Muss "Registered tunnel connection" zeigen +``` + +CF-Dashboard: Tunnel bf-public → Connections muss > 0 zeigen (1 Connector pro AP). + +## 3. CNAME-FLIP (nach erfolgreichem Bootstrap, sequentiell) + +Reihenfolge: **n8n → gitea → hass → vw**. Jeweils mit Abnahme zwischen den Flips. + +### 3a. Vor jedem Flip: Test-CNAME temporär + +Vor dem Umhängen eines Produktiv-Namens testen wir mit einem **Extra-CNAME** +`test-tp31.emsenhuber.net → bf-public.cfargotunnel.com`, der durch die +Wildcard-Access-App `*.emsenhuber.net` bereits geschützt ist. + +```bash +# curl im BF-LAN (testet Tunnel→Caddy→Backend) +curl -s -o /dev/null -w '%{http_code}' --resolve test-tp31.emsenhuber.net:443:10.40.99.11 http://test-tp31.emsenhuber.net +# Erwartet: 302 (Access-Login-Redirect) +# Bei 5xx: Container-Log lesen, Caddy erreichbar? /log print auf dem AP +``` + +### 3b. Flip n8n.emsenhuber.net + +```bash +# Zone-ID ist 1b5bc02fdf61b6b989afde543f3f4134 +# Alten CNAME lesen: +CNAME_ID=$(curl -s -H "Authorization: Bearer $CF_API_TOKEN" \ + "https://api.cloudflare.com/client/v4/zones/1b5bc02fdf61b6b989afde543f3f4134/dns_records?name=n8n.emsenhuber.net" \ + | jq -r '.result[0].id') + +# Auf bf-public.cfargotunnel.com umhängen: +curl -s -X PATCH -H "Authorization: Bearer $CF_API_TOKEN" \ + -H "Content-Type: application/json" \ + "https://api.cloudflare.com/client/v4/zones/1b5bc02fdf61b6b989afde543f3f4134/dns_records/$CNAME_ID" \ + -d '{"content":"48d3b0b6-7233-4781-a76a-1de4a5e957ce.cfargotunnel.com","proxied":true}' +``` + +**Abnahme:** Browser → n8n.emsenhuber.net → Access-Login → 200 von n8n. + +### 3c. Flip gitea.emsenhuber.net +Analog, aber VORHER prüfen ob Git-Push über Token von außen noch geht. + +### 3d. Flip hass.emsenhuber.net +**VORSICHT:** HA Companion App kann Access-Login nicht. Vor dem Test: +- Browser öffnen, Access-Login durchführen, Session-Cookie setzen +- App öffnen und prüfen ob sie die Session übernimmt + +### 3e. Flip vw.emsenhuber.net +**VORSICHT:** Bitwarden auf bypass, NICHT hinter Access. Prüfen dass +die Access-Policy `vw.emsenhuber.net` weiterhin `bypass` ist. + +## 4. AUFRÄUMEN (nach erfolgreichem Flip ALLER 4 Namen) + +### 4a. Alte CNAMEs löschen +Löschen aller CNAMEs, die noch auf bf-mm/bf-nas/bf-pve zeigen. +**Ausnahme:** `3k23uow7`, `82unkpb5`, `j44d6tua` (SSH-Tunnel-Namen, +keine öffentlichen Hostnames — erst mit Schritt 6 anfassen). + +```bash +for name in n8n-mcp gitea-mcp grafana pve-mcp ds-bf ccu iobroker z2m25 pve portainer pbs ha-mcp nautobot gateway-dw; do + ID=$(curl -s -H "Authorization: Bearer $CF_API_TOKEN" \ + "https://api.cloudflare.com/client/v4/zones/1b5bc02fdf61b6b989afde543f3f4134/dns_records?name=${name}.emsenhuber.net" \ + | jq -r '.result[0].id // empty') + if [ -n "$ID" ]; then + curl -s -X DELETE -H "Authorization: Bearer $CF_API_TOKEN" \ + "https://api.cloudflare.com/client/v4/zones/1b5bc02fdf61b6b989afde543f3f4134/dns_records/$ID" + echo "Deleted ${name}.emsenhuber.net" + fi +done +``` + +### 4b. Alte Tunnel deaktiviert lassen (nicht löschen!) +bf-mm, bf-nas, bf-pve erst löschen nach 1 Woche Betrieb ohne Vorfälle. + +## 5. ABNAHME-KRITERIEN (pro Flip) +- [ ] Tunnel bf-public zeigt 2+ Connections (ap1 + ap2) +- [ ] Browser: Name → Access-Login → 200/302 vom Caddy +- [ ] Caddy-Log zeigt eingehenden Request (`pct exec 130 -- journalctl -u caddy -n 5`) +- [ ] Kein 530/1033 über 24h (alte Tunnel noch aktiv → Round-Robin wäre sichtbar) + +## 6. ROLLBACK (je Flip) +CNAME zurück auf den alten Tunnel setzen: +```bash +curl -s -X PATCH -H "Authorization: Bearer $CF_API_TOKEN" \ + -H "Content-Type: application/json" \ + "https://api.cloudflare.com/client/v4/zones/1b5bc02fdf61b6b989afde543f3f4134/dns_records/$CNAME_ID" \ + -d '{"content":".cfargotunnel.com","proxied":true}' +``` + +## 7. FALLEN +- **Kein Container ohne device-mode-Wechsel** — `container`-Paket ist mit + `device-mode=home` gesperrt. Physischer Zugang zwingend. +- **hAP Flash-Constraint:** ~95 MB frei. cloudflared-Image ~30 MB → passt. + Aber keine weiteren Container auf demselben AP. +- **NAND-Verschleiß:** cloudflared schreibt kaum (Config in Cloudflare, kein + Query-Log wie AGH). Trotzdem kein zweiter Container. +- **MGMT→INFRA forward nur TCP:** Cloudflared baut QUIC (UDP 7844) zu CF. + Das ist Egress (LAN→WAN), nicht INFRA — die Regel 27 greift nicht für + Cloudflareds eigenen Tunnel-Traffic. Der geht über die `defconf`-Regel 2 + (est/rel) oder über `LAN→WAN` (Regel 14). **Kein zusätzlicher Firewall-Change + nötig.**