Format wie docs/session-2026-09-12-ipv6-plattform.md, an das diese Session anschliesst. Haelt fest, was verifiziert ist, was ausdruecklich nicht getestet wurde (Reboot-/Reconnect-Probe) und welche Entscheidungen offen beim Nutzer liegen (Zertifikatskette, Wildcard via BIND). Der Intent sagte noch "noch nicht ausgefuehrt"; Schritte 1 bis 5 sind erledigt, Schritt 6 nicht. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019jNMZkpvA9QuNEPg9BA6oY
163 lines
8.7 KiB
Markdown
163 lines
8.7 KiB
Markdown
# Session 12.09.2026 (Teil 2): Traefik auf pinix, öffentlicher IPv6-Eingang
|
|
|
|
## Übergabe für die nächste Session
|
|
|
|
Gearbeitet wurde auf **tnix** (nicht auf blunix), Branch `dev`, alles
|
|
gepusht. Vorgänger dieser Session:
|
|
[IPv6-Mobilfunkzugang und Plattformplanung](session-2026-09-12-ipv6-plattform.md).
|
|
Auftrag war der [Intent](intent/pinix-ipv6-traefik-webserver.md), dessen
|
|
Schritte 3 bis 5 jetzt umgesetzt sind.
|
|
|
|
**Stand:** <https://ipv6-test.0ff.space/> wird von **pinix** beantwortet,
|
|
über Traefik auf pinix, mit eigenem Let's-Encrypt-Zertifikat. Kein VPS,
|
|
kein Tailnet, kein Cloudflare-Proxy im Datenpfad — Cloudflare hält nur den
|
|
AAAA-Eintrag, der unverändert blieb. Der nginx-Test auf tnix ist entfernt.
|
|
|
|
**Nächster sinnvoller Schritt:** Schritt 6 des Intents — Reboot- und
|
|
Reconnect-Probe. Die ist ausdrücklich **nicht** gelaufen. Das öffentliche
|
|
Präfix rotiert nachweislich (auf Mangos `usb0` liegt neben der aktiven
|
|
Adresse noch `2a01:599:106:e90d:94dd:42ff:fe9a:627f` als `deprecated`).
|
|
Vor der Probe einen lokalen Rückweg sichern und den Zeitpunkt abstimmen.
|
|
|
|
## Arbeitsweise, auf die sich Nutzer und Agent geeinigt haben
|
|
|
|
Editiert wird auf tnix im Repo, gebaut und aktiviert wird **lokal auf
|
|
pinix**, committet wird erst, wenn es auf der Zielhardware läuft:
|
|
|
|
```bash
|
|
rsync -a --delete --exclude .git ./ pinix:/home/drone/nixos-config-build/
|
|
ssh pinix 'cd /home/drone/nixos-config-build && \
|
|
sudo nixos-rebuild switch --flake path:.#pinix --no-reexec'
|
|
```
|
|
|
|
Begründung: kein Commit pro Zwischenstand, kein Closure-Transfer, kein
|
|
Umweg über Forgejo; der `rsync` kostet etwa 1,5 s. Der nixbuild.net-Store
|
|
bleibt für große Kompilierläufe. `/home/drone/nixos-config` auf pinix ist
|
|
der Recovery-Checkout, kein Arbeitsplatz.
|
|
|
|
## Gesicherte Ergebnisse
|
|
|
|
- **pinix kann wieder von Forgejo fetchen.** `/etc/ssh/ssh_known_hosts`
|
|
war leer; der Pin für Port 2222 lag früher im auskommentierten
|
|
`localServices/forgejo.nix`. Seit `355b42e` steht er global in
|
|
`hosts/globalServices/forgejo-known-host.nix`. Henne-Ei: der Pin liegt
|
|
selbst im Repo, ein Pull konnte ihn also nicht holen — der rsync-Bauweg
|
|
war der Ausweg. Recovery-Checkout per `--ff-only` nachgezogen.
|
|
- **Traefik auf pinix**, `hosts/pinix/localServices/traefik.nix`.
|
|
Abgeleitet von blunix, aber bewusst ohne Cloudflare-DNS-Challenge (kein
|
|
API-Token, kein Secret, dafür keine Wildcard), ohne api/Dashboard, ohne
|
|
`ip_nonlocal_bind`, `log.level` INFO statt TRACE.
|
|
- **Statische Testseite**, `hosts/pinix/localServices/ipv6-test.nix`, nach
|
|
dem Muster von blunix' `launcher.nix`: `static-web-server` auf
|
|
`127.0.0.1:8001`, Route im Dienstmodul statt in einer zentralen Liste.
|
|
Die Seite nennt pinix beim Namen, damit ein alter tnix-Pfad auffällt.
|
|
- **Mango-DNAT umgelegt**, `scripts/configure-mango-ipv6-web.sh` ist jetzt
|
|
parametrisiert (`TARGET_IP`, `PUBLIC_IP`, `WAN_DEV`, `PORT_MAP`,
|
|
`RULE_PREFIX`, `STALE_PREFIXES`), räumt Regeln früherer Ziele vorher weg
|
|
und ermittelt die öffentliche Adresse zur Laufzeit statt sie
|
|
einzutragen. Aufruf vom LAN aus:
|
|
`ssh root@192.168.8.1 'sh -s' < scripts/configure-mango-ipv6-web.sh`.
|
|
Backup je Lauf unter `/root/ipv6-web-firewall-backup.*` auf dem Mango.
|
|
- **SNAT-Rückwegregeln entfallen ersatzlos.** Sie waren nötig, weil tnix
|
|
seine Default-Route auf dem iPhone-Hotspot behielt; pinix' Default-Route
|
|
zeigt ohnehin auf den Mango. Sechs Regeln wurden zu drei, und die echte
|
|
Client-Adresse steht wieder im Traefik-Log statt `fdee:3c40:44f0::1`.
|
|
- **Extern 8080 → intern 80**, weil auf pinix nur Traefik mit 80/443
|
|
lauscht. Der alte Link bleibt gültig und läuft über die
|
|
HTTPS-Weiterleitung des Proxys.
|
|
- **Zertifikat** per ACME HTTP-01, Resolver `le`, Speicher
|
|
`/var/lib/traefik/acme.json`. Traefik-Log: `Validations succeeded`,
|
|
also hat Let's Encrypt pinix von außen über IPv6 erreicht.
|
|
- **tnix-Testserver entfernt.** Damit fiel die statische ULA auf
|
|
`enp0s31f6` weg, die dort ein schwarzes Loch erzeugte: das Interface ist
|
|
DOWN, lieferte aber trotzdem die On-Link-Route für
|
|
`fdee:3c40:44f0::/64`, sodass tnix das gesamte LAN-Präfix in ein totes
|
|
Interface schickte. Über IPv4 lief derselbe Weg einwandfrei — eine
|
|
hübsche Falle, falls sie anderswo nochmal auftaucht.
|
|
|
|
### Gemessene Zustände (12.09.2026, vor weiterer Aktivierung neu prüfen)
|
|
|
|
| Prüfung | Ergebnis |
|
|
|---|---|
|
|
| `curl` von tnix, HTTPS mit `--resolve` auf pinix' ULA | 200, „Hallo von pinix." |
|
|
| Port 80 auf pinix | 301 auf HTTPS |
|
|
| unbekannter Hostname an Traefik | 404, kein Catch-all |
|
|
| `openssl s_client` gegen pinix:443 | vollständige Kette, `Verify return code: 0 (ok)` |
|
|
| pinix IPv6-Uplink | RA-Default-Route via `fe80::9683:c4ff:fe12:ab4d`, `github.com` 200 |
|
|
|
|
Adressen: pinix LAN-ULA `fdee:3c40:44f0:0:dea6:32ff:fe48:c6c8` (SLAAC aus
|
|
MAC `dc:a6:32:48:c6:c8`), Mango öffentlich
|
|
`2a01:598:ec1e:ce00:94dd:42ff:fe9a:627f`, Mango LAN `fdee:3c40:44f0::1`
|
|
bzw. `192.168.8.1`.
|
|
|
|
## Fallstrick, der Zeit gekostet hat
|
|
|
|
Der Intent verlangt eine „stabile LAN-Zieladresse". Der naheliegende Weg —
|
|
`networking.interfaces.end0.ipv6.addresses` wie in tnix'
|
|
`ipv6-web-test.nix` — **nimmt dem Host das Internet**: sobald ein Interface
|
|
eine statische IPv6-Adresse bekommt, schreibt das NixOS-dhcpcd-Modul für
|
|
dieses Interface `noipv6rs` in die generierte `dhcpcd.conf`. Keine
|
|
Router-Solicitation, keine RA-Default-Route — und pinix' Uplink ist
|
|
IPv6-only. Sichtbar wird das erst nach dem `switch`, weil dabei `dhcpcd`
|
|
neu startet und die vorhandenen Adressen mitnimmt.
|
|
|
|
Zurückgebaut. Ziel ist jetzt die SLAAC-Adresse, die aus MAC und
|
|
ULA-Präfix ohnehin deterministisch entsteht — dieselbe Adresse, nur ohne
|
|
den Nebeneffekt. Im Modul kommentiert. Wer eine wirklich unabhängige
|
|
statische Adresse will, muss die Default-Route mit lösen; ein erster
|
|
Versuch damit war laut `eb2022e` schon auf tnix gescheitert.
|
|
|
|
## Offene Punkte
|
|
|
|
- **Zertifikatskette.** Ein externer Abruf über einen Client mit älterem
|
|
CA-Bundle scheitert reproduzierbar an `unable to verify the first
|
|
certificate`; die Kette läuft über `ISRG Root YR`. pinix' eigenes Bundle
|
|
und `openssl` akzeptieren sie (`Verify return code: 0`). Verdacht: das
|
|
Root ist noch nicht überall im Trust Store, ältere Android-Geräte dürften
|
|
dasselbe Problem haben. Möglicher Fix: `preferredChain` im ACME-Resolver.
|
|
Das erzwingt eine Neuausstellung, also vorher den Eintrag aus
|
|
`acme.json` räumen. **Vom Nutzer noch nicht entschieden.**
|
|
- **Reboot-/Reconnect-Probe** (Intent Schritt 6) steht aus, siehe oben.
|
|
- **Wildcard über selbst gehostetes BIND** wurde besprochen und
|
|
**zurückgestellt**, nicht verworfen. Begründung: ein autoritativer NS
|
|
braucht einen zuverlässig erreichbaren Host, und genau diese Eigenschaft
|
|
ist für pinix noch nicht nachgewiesen. Die Fehlerfolgen sind
|
|
asymmetrisch — HTTP-01 kaputt heißt eine Seite ohne Zertifikat,
|
|
autoritativer DNS kaputt heißt `0ff.space` löst nirgends mehr auf, samt
|
|
Mail, XMPP-Föderation und ActivityPub. Ein nur über IPv6 erreichbarer NS
|
|
schließt zudem alle IPv4-only-Resolver aus. Vorgeschlagene Reihenfolge:
|
|
erst Eingang stabilisieren, dann als Zwischenstufe `_acme-challenge`
|
|
delegieren (nimmt Cloudflare den API-Token weg, ohne die Auflösung der
|
|
Domain an den Mobilfunkanschluss zu hängen), vollautoritatives BIND als
|
|
eigene Entscheidung mit Sekundären. Siehe `docs/roadmap.md`.
|
|
- **Subdomains wie auf blunix** sind erklärtes Ziel. Die Routing-Ebene
|
|
trägt das bereits: DNAT arbeitet auf Adresse und Port, jede weitere
|
|
Subdomain ist nur ein Traefik-Router. Nicht mitskalieren:
|
|
ein Zertifikat pro Hostname bei HTTP-01, ein AAAA je Subdomain auf eine
|
|
rotierende öffentliche Adresse, und IPv4-only-Besucher erreichen einen
|
|
IPv6-only-Eingang gar nicht — dafür bliebe blunix als zweiter Eingang.
|
|
|
|
## Dateien und Arbeitsstand
|
|
|
|
Commits auf `dev`, in dieser Reihenfolge:
|
|
|
|
| Commit | Inhalt |
|
|
|---|---|
|
|
| `54ea39e` | `docs/pinix-minimalbetrieb.md`: Forgejo-Fetch behoben, Henne-Ei festgehalten |
|
|
| `31a8e0f` | pinix: minimales Traefik plus Testseite, noch ohne TLS |
|
|
| `61b4d1f` | TLS über ACME HTTP-01, Mango-Skript parametrisiert, DNAT umgelegt |
|
|
| `4558f86` | tnix: IPv6-Testserver entfernt |
|
|
|
|
Aktive Generationen nach der Session:
|
|
pinix `w9dr3gl14dxwm5hb6l0rv7fxs0h83ahg-nixos-system-pinix`,
|
|
tnix `vjmsfk6kdgynnzdc0pz53cf5knbi02qr-nixos-system-tnix`.
|
|
|
|
Verworfen wurde eine uncommittete Änderung in
|
|
`hosts/tnix/configuration.nix`, die das WLAN zurück auf den
|
|
iPhone-Hotspot gestellt hätte — ein `switch` damit hätte tnix aus dem
|
|
Netz geworfen, in dem es gerade hängt.
|
|
|
|
Rückbau auf den vorherigen Stand: `dest_ip` in den Mango-Regeln zurück auf
|
|
tnix' ULA `fdee:3c40:44f0:0:ca5b:76ff:fe96:e24` (oder das Skript mit
|
|
`TARGET_IP=...` erneut laufen lassen) und auf tnix die Generation vor
|
|
`4558f86` booten, die den nginx-Test noch enthält.
|