Runbook docs/tp16.3-bf-public-ap-connector-runbook.md fuer die Vor-Ort-Session geschrieben; docs/tp31-schritt5-runbook.md abgeloest (read-only-Header). Live-Befunde 2026-08-30, die den Plan aendern: - ap3 ist neu und NICHT baugleich: cAP ax (cAPGi-5HaxD2HaxD, 10.40.99.13), arm64/96 MB frei, aber ROS 7.24.1 gegen 7.24 auf ap1/ap2 => zwei verschiedene container.npk. device-mode=basic statt home (fetch bereits an). - Blocker A: bf-public-Ingress zeigt auf :80, Caddy antwortet dort mit 308 auf https => Redirect-Schleife ueber CF fuer alle vier Namen. Faellt heute nicht auf, weil die Alttunnel an Caddy vorbei direkt aufs Backend gehen. Fix: https://10.40.20.40:443 + originServerName je Regel (ueber 443 4x 200). - Blocker B: es gibt KEINE Freigabe vlan99 -> vlan20:443. Die forward-Kette wurde vollstaendig gelesen (36 Regeln); die einzige MGMT->INFRA-Regel ist ein src-port=8728-Rueckweg. Der Vorgaenger-Runbook behauptet das Gegenteil ("Regel 27 deckt vlan99->vlan20:80 ab") - Regel 27 ist IOT->INFRA. - Blocker C: ROUTER_AP3_PASS fehlt in ~/.secrets/credentials.env (nur in ~/.claude.json). Nebenbefund: credentials.env laesst sich in zsh nicht sourcen (rohe WireGuard-Zeilen ab ~Z.69) - Variablen bleiben still leer. - Kein PoE an beiden CRS326 => kein Remote-Power-Cycle, Bestaetigung physisch. - Die sechs abzubauenden Container auf allen drei Hosts verifiziert; terpene-cloudflared und fm.emsenhuber.net bleiben. CF-Rollback-Snapshots unter docs/cf-backup/*-20260830-vor-tp16.3-schnitt.json neu angelegt (vier Ingress-Configs + CNAMEs inkl. Record-IDs) - es gab sie vorher nicht. Quick-Index, TP16.3-Abschnitt und Ist-Stand-Block mitgezogen. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
193 lines
7.8 KiB
Markdown
193 lines
7.8 KiB
Markdown
# 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.
|
|
|
|
> 🔴 **ABGELÖST 2026-08-30 — NICHT MEHR AUSFÜHREN.**
|
|
> Nachfolger: [`tp16.3-bf-public-ap-connector-runbook.md`](tp16.3-bf-public-ap-connector-runbook.md).
|
|
> Dieses Dokument bleibt als Historie stehen. Drei Gründe, warum es nicht mehr trägt:
|
|
> 1. **Es kennt `ap3` nicht** (cAP ax, `10.40.99.13`, seit 2026-08-30 in Betrieb) — und ap3 läuft
|
|
> **ROS 7.24.1** gegen 7.24 auf ap1/ap2, braucht also ein **anderes `container.npk`**.
|
|
> 2. **§2b unterstellt einen Registry-Pull.** Auf ap1/ap2 ist `fetch: no` (`device-mode=home`) —
|
|
> das Image muss als `.tar` hoch und per `/container add file=` importiert werden.
|
|
> 3. 🔴 **§0 behauptet, „Regel 27 `MGMT→INFRA TCP` deckt `vlan99→vlan20:80` bereits ab ✅".**
|
|
> **Das ist falsch.** Die `forward`-Kette des Core wurde am 2026-08-30 vollständig gelesen:
|
|
> Regel 27 ist `IOT->INFRA http-rueckweg` (`in-interface=vlan30`), und die einzige MGMT→INFRA-Regel
|
|
> (Nr. 26) ist ein `src-port=8728`-Rückweg der API. **Eine Freigabe für den Connector existiert
|
|
> nicht** — ohne sie landet er in `TP5-WOULD-DROP` + Drop.
|
|
>
|
|
> Ebenfalls im Nachfolger, hier noch nicht enthalten: der **Redirect-Loop** über `:80`
|
|
> (Caddy antwortet dort mit 308) und der Abbau der sechs Container.
|
|
|
|
## 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":"<alter-tunnel-id>.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.**
|