Commit Graph

4 Commits (c99911ca55db24c68aae7750f47e40724722ead3)

Author SHA1 Message Date
nexxo 5f3d983658 Der Tunnel bekommt eine feste Adresse — damit ist die conntrack-Falle weg statt behandelt
Die Wurzel des ganzen Uebels, endlich an der Wurzel: Docker traegt den
veroeffentlichten UDP-Port als Weiterleitung auf die Container-Adresse ein, und
der Kernel merkt sich jeden laufenden Strom samt dieser Adresse. Bekam der
Container beim Neubau eine andere — und er bekam die naechste freie —, zeigten
alle gemerkten Stroeme ins Leere. Und sie verfallen nicht, weil WireGuards
Lebenszeichen sie alle 25 Sekunden auffrischt.

Deshalb kam ein Telefon nach Aus/Ein sofort zurueck und ein Host mit festem
Quellport ueberhaupt nicht.

Jetzt hat vpn-hub eine feste Adresse (172.18.0.240, ueber CLUPILOT_VPN_HUB_IP
aenderbar) in einem Netz mit erklaertem Subnetz. Nach einem Neubau entsteht exakt
dieselbe Weiterleitung, die gemerkten Stroeme bleiben gueltig, und es gibt nichts
mehr aufzuraeumen. Nachgemessen: 172.18.0.240 vor und nach
`up -d --force-recreate vpn-hub`.

UND DIE UMSTELLUNG SELBST, die mich beim Bauen fast den Stapel gekostet haette:
Docker kann ein bestehendes Netz nicht umdefinieren. Es muss neu angelegt werden,
und das scheitert, solange auch nur EIN Container daranhaengt — `up -d` bricht
dann mit "network … has active endpoints" ab und laesst den Stapel halb unten
stehen. Genau so hier passiert, mit einem Container, der gar nicht zum Stapel
gehoerte. Das Deployment vergleicht deshalb vorher das erklaerte Subnetz mit dem
tatsaechlichen und faehrt bei Abweichung EINMAL geordnet herunter, statt darueber
zu stolpern. Danach stimmen die Werte ueberein und der Block tut nie wieder etwas.

Das conntrack-Aufraeumen bleibt trotzdem drin: als Rueckfahrkarte fuer Server auf
aelterem Stand und fuer den Fall, dass jemand das Subnetz aendert.

2510 Tests gruen.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-03 09:10:54 +02:00
nexxo e3c781f067 Der Tunnel bekommt einen eigenen Container
Bisher wohnte wg0 im Container des Provisionierungs-Arbeiters, also im Abbild
`clupilot-app`. Das wird bei fast jeder Freigabe neu gebaut — und ein neu
gebauter Container bekommt eine neue Adresse im Compose-Netz, womit die
Weiterleitung fuer UDP 51820 neu geschrieben wird und JEDE bestehende
WireGuard-Sitzung abreisst. Der Tunnel hing damit am Veroeffentlichungstakt der
Anwendung, und zusaetzlich daran, dass ein PHP-Prozess nicht abstuerzt.

Jetzt gehoert der Netz-Namensraum einem eigenen Container `vpn-hub` mit eigenem,
winzigem Abbild (Alpine plus wireguard-tools), das sich fast nie aendert.
Provisionierungs-Arbeiter, Terminal-Bruecke, interner DNS und internes Gateway
steigen dort ein, statt einer von ihnen den Namensraum zu besitzen.

NACHGEMESSEN, nicht angenommen: App-Abbild neu gebaut, Arbeiter, Bruecke und
Gateway per --force-recreate neu erzeugt — der Hub blieb Container 92e928cf53b0,
wg0 und beide Zugaenge unangetastet, und nginx erreichte die Bruecke weiter
(HTTP 426). Genau der Vorgang, der bisher jedes Mal alles abgerissen hat.

Nachgezogen:
- nginx spricht die Bruecke unter `vpn-hub:8082` an — dem Namen des
  Namensraum-Eigentuemers; ein Mitbewohner hat keinen eigenen DNS-Eintrag.
- update.sh baut vpn-hub mit und haengt Nachbar-Neustarts und den
  conntrack-Griff an die Frage, ob der Hub WIRKLICH neu gebaut wurde.
- update-agent.sh startet den Arbeiter nicht mehr neu, sondern signalisiert ihm.
  Diese Stelle laeuft unbeaufsichtigt hinter dem Knopf „Dienste neu starten" —
  wer den drueckt, rechnet nicht damit, sich selbst auszusperren.
- Vier Meldungen in der Konsole rieten dem Betreiber, genau den Befehl von Hand
  auszufuehren, der ihm den Tunnel abreisst. Auch die sind korrigiert.
- rescue-tunnel.sh und das Runbook zeigen auf den neuen Besitzer.

Eine Kleinigkeit unterwegs, die ich falsch angekuendigt hatte: `[[ … ]] && x=true`
bricht unter `set -e` NICHT ab — bash nimmt die linke Seite einer &&-Liste
ausdruecklich aus. Nachgeprueft; die if-Form bleibt trotzdem, aus Lesbarkeit, und
der Kommentar sagt jetzt den wahren Grund.

2509 Tests gruen.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-03 07:49:29 +02:00
nexxo 7b336d49f9 Runbook: Wenn der Tunnel weg ist
tests / pest (push) Failing after 8m44s Details
tests / assets (push) Successful in 25s Details
tests / release (push) Has been skipped Details
Der Rettungsweg war bisher muendliche Ueberlieferung, verteilt ueber einen
Chatverlauf. Jetzt aufgeschrieben, mit der einen Regel darueber: kein Weg zurueck
darf durch den Tunnel fuehren, der gerade kaputt ist.

Vier Wege hinein (SSH auf den Server, Anbieterkonsole, das Notfallskript auf dem
Host, eine offline abgelegte WireGuard-Konfiguration), ein Entscheidungsbaum zum
Eingrenzen, und je Fall die Befehle. Dazu vier Dinge, die man EINMAL einrichtet,
solange nichts brennt — darunter der sudoers-Eintrag, ohne den der conntrack-
Griff aus v1.4.6 nur als Warnung im Protokoll landet statt zu laufen.

Und ein Abschnitt darueber, was seit v1.4.4/v1.4.6 nicht mehr passieren sollte:
wer es trotzdem sieht, hat einen Server auf altem Stand.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-03 07:15:10 +02:00
nexxo 668ed67de4 Write down what to do when the bootstrap stops
One entry per section: how you notice, where to look, what it usually is. Above
all of them the rule the plan already states — a half installed machine is
reinstalled, not repaired — with the reason, which is not convenience. The
script is built so a second run on a freshly imaged machine always comes out the
same; a run on a machine somebody straightened out by hand is no longer that.
Repairing trades a repeatable result for a one-off, and the difference only
shows up on the next host.

rescue_checked is the stated exception, because nothing has been written yet. It
is the only section where fixing in place is right, and the runbook says so
rather than leaving the reader to infer it.

Two things that are easy to get wrong are answered up front. Whether the reboot
has happened is one `findmnt -no FSTYPE /` — tmpfs or overlay means still in the
rescue system, zfs means the first-boot hook already resumed. And when a host is
unreachable, the first question is whether the firewall had even run: it is
applied last, so if `registered` is not done, the cause is the network and not
the rules.

The installer can be watched while it runs. If QEMU is still up, forwarding 5900
over SSH shows what the ISO is doing, and an input mask there means the answer
file was not accepted and the installer has dropped into interactive mode where
it will sit until the hour expires. That failure otherwise arrives as a timeout
saying nothing.

The last heading is the honest one: everything here is written from the script
and the findings behind it, not from incidents. What actually stops on the first
real run belongs in this file afterwards, quoted as it appeared in the console.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-07-30 20:22:32 +02:00