Commit Graph

3 Commits (f961205512e1374dd5cac8fa6c8ce1fbe8bf9749)

Author SHA1 Message Date
nexxo b9fb401823 Release v1.3.85 — Handshake-Prüfung hing an einem Programm, das es nicht gibt
tests / pest (push) Failing after 8m54s Details
tests / assets (push) Successful in 22s Details
tests / release (push) Has been skipped Details
Die Übernahme brach in "WireGuard einrichten" ab: fünf Wiederholungen,
"WireGuard handshake not up yet". Geprüft wurde mit `ping -c1 -W2 <hub-ip>`.
Das fragte drei Dinge auf einmal und nannte nur eines: ob der Handshake steht,
ob ICMP durchkommt — und ob es `ping` auf der Maschine überhaupt GIBT.

Auf Hetzners `Debian-trixie-latest-amd64-base` gibt es das nicht. `iputils-ping`
ist im Image nicht dabei, und PrepareBaseSystem installiert
`curl gnupg ifupdown2 chrony`. Der Schritt scheiterte damit über einem Tunnel,
der stehen konnte. Auf dem alten Proxmox-Image war ping dabei, deshalb lief es
dort durch — dieselbe Pipeline, anderes Grundsystem.

Gefragt wird jetzt WireGuard selbst: `date +%s; wg show wg0 latest-handshakes`.
Die Uhr des HOSTS kommt in derselben Antwort mit, weil `latest-handshakes` eine
absolute Zeit ausgibt und ein Vergleich gegen UNSERE Uhr eine Zeitverschiebung
zwischen zwei Maschinen als Tunnelzustand läse. `date` ist in coreutils und
überall da.

Codex, zwei Runden:

- P1: `> 0` hiesse "hat jemals". WireGuard behält den Zeitstempel unbegrenzt,
  also meldete ein Wiederholungslauf über einem toten Tunnel "steht", und die
  Schritte danach wählten die Tunneladresse für SSH. Jetzt muss der Handshake
  frisch sein (180 s) und vom KONFIGURIERTEN Hub kommen — ein fremder Peer auf
  wg0 ist kein Beweis dafür, dass wir erreichbar sind.
- P1: Der neue Host-Versatz (.100) liess die Vergabe in einem Subnetz kleiner
  als /26 "erschöpft" melden, obwohl unten alles frei war. Der Versatz ist eine
  Bevorzugung, keine Bedingung: zweiter Durchgang von vorn.

Ausserdem, wie gewünscht: Hosts bekommen ihre Tunneladresse ab .100
(CLUPILOT_WG_HOST_OFFSET), Personen zählen weiter von unten. Fortlaufend
vergeben landete der erste Host zwischen zwei Notebooks, und wer eine Adresse
in einem Protokoll las, konnte nicht sagen, ob dahinter ein Mensch oder eine
Maschine steht.

2243 Tests grün.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-01 03:00:19 +02:00
nexxo 8ab50f5650 Release v1.3.81 — Host anlegen scheiterte am WireGuard-Peer
tests / pest (push) Failing after 9m3s Details
tests / assets (push) Successful in 22s Details
tests / release (push) Has been skipped Details
Das Anlegen eines Hosts endete in der Konsole mit einem 500, bevor der
Betreiber den Einmal-Code je zu sehen bekam. Ursache war nicht das Anlegen,
sondern der Tunnel-Peer: HostEnrolment::issueWithKeys() rief `wg set wg0`
selbst auf — im Web-Request, also im `app`-Container. Der hat weder NET_ADMIN
noch /dev/net/tun; wg0 lebt im Provisioning-Container. Die Antwort war
"Unable to modify interface: Operation not permitted".

Der Peer geht jetzt als ApplyHostVpnPeer auf die Provisioning-Queue — genau
dorthin, wo ApplyVpnPeer es für die VPN-Zugänge längst richtig macht, mit
derselben `wireguard:hub`-Sperre und demselben Grundsatz: der Sollzustand
kommt beim Ausführen aus der Zeile, nicht aus dem beim Einreihen
festgehaltenen Wert. Der abgelöste Schlüssel reist als Wert mit, weil in der
Zeile zu diesem Zeitpunkt schon der neue steht.

Aufgefallen ist es nie, weil die Testsuite den Hub gegen FakeWireguardHub
tauscht — der bestehende Test blieb grün, während der echte Weg seit jeher
fehlschlug. Die zwei neuen Tests prüfen deshalb den WEG statt des Ergebnisses:
in der Anfrage bleibt der Hub unberührt, und der Auftrag liegt auf der
Provisioning-Queue.

Codex: 0 Fehler, 0 Sicherheitsbefunde. Dazu sein P2 — /.claude/ stand weder
im Index noch in .gitignore, ein `git add -A` hätte 153 MB als verschachteltes
Repo eingebettet.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-01 00:43:10 +02:00
nexxo 903ebdd2b2 Give the operator one line to copy and three steps around it
The console could describe a takeover it had no way to start. This is the
vertical slice that closes that: a one-time code, the archive the rescue system
fetches, and the page that says what to do with both.

The command carries EVERYTHING the script needs before the tunnel exists,
because there is nothing to fetch — that is the whole point of spec §5. Which
means CluPilot generates the WireGuard keypair and admits the peer at the hub
before the machine has ever booted, and hands the private half over in the line.
It is worthless within minutes: task 9 of the script replaces it with one
generated on the machine.

Shown exactly once. The database holds only the code's hash and never the
private key, so leaving the page does not bring it back — it mints a new code,
which invalidates the old one. That is deliberate: a glance at somebody's screen
should be worth nothing an hour later.

Which is also why save() no longer redirects. Sending the operator to the host
detail page sends them away from the only value they need, and an existing test
asserted that redirect — it now asserts the opposite, with the reason written
next to it.

SHA-256 rather than bcrypt for the code, and the reason is not speed. Both
endpoints have to FIND the host by the code; with bcrypt that means trying every
row. The code is 32 characters of CSPRNG output, so it has the entropy that
stretching exists to manufacture.

resolve() and claim() are separate because progress reports arrive BEFORE
registration. If reporting consumed the code, a host could never register after
its first message.

The archive URL is always the public hostname. The console runs under admin.…,
but this line executes on a machine that must not reach the admin area — it is
locked down for exactly that reason — so route() from the console would emit a
hostname that 404s on a server only reachable through the provider's console.

The page warns about missing tunnel settings BEFORE the host is created, not
after. An empty hub key produces a line that looks clean, copies fine, runs, and
ends in a tunnel that never handshakes — discovered on the machine, after
somebody has already paid for it.

The three steps lead with the rescue system, because that is the one nobody
knows by heart, and it says enabling is not the same as booting into it — the
script refuses a running production machine, which is what a half-done switch
looks like from the inside.

1986 tests pass.

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