Implements hq ADR 0105 on the host side. Pairs with mesh-controller feat/adopt-the-tunnel (#49). Revised after review (H1, H2, H6, C3's host half, C4, rekey path).
Genesis (adopted): finds the one WireGuard interface up besides mesh0 (--tunnel names one when several are), settles --hub-port and --overlay-range on it (a disagreeing value is refused naming the tunnel's), exempts the hub port held by the tunnel from the ports-free check, and skips ADR 0100's non-overlap check only for a range that is now the tunnel's.
Enrolment: the found interface's private key becomes the node's overlay key (identity.OverlayKeyFrom), stored exactly as a generated one — never printed, never sent. The tunnel travels in the enrol request as tunnel.
mesh-host overlay take --tunnel <iface> — for a node that enrolled before this feature. Rewrites overlay.key and identity.Overlay with the found key; identity, sealing and serving keys are the same bytes in and out (rekey_test.go), so nothing the mesh sealed to the node is remade. Sends a Report{rekey} signed by the identity key over RekeyProof(node, previous, key, tunnel); told first, written second, and the key before the take is kept as overlay_before so a re-run names the same previous. The running host's mesh0 picks the key up when the next push restarts it.
Apply: a service may carry takes-over (adopted declarations only). Nothing is stopped until the mesh's interface is known to replace the found one: the declared config (the file the service restarts on) must have ListenPort = found port, Address = found address, and the key file its PostUp … private-key <path> names must hold the found key — else refused before any stop, naming the remedy (overlay take / re-place). Then the found config is kept like any held file, the found unit stopped and disabled, never flushed. If wg-quick@mesh0 then fails to start, wg-quick@wg0 is started again and the account says so. An interface still up with its unit inactive (raised by hand) is re-checked 3× over ~6 s, then refused naming wg-quick down <iface>. The account has three states — not-taken, taken, down (found down, mesh's not up) — read from the machine, and is given on every takeover declaration, failure included.
H6 note: the first build re-stopped a found unit somebody started again on every apply. Dropped: on the hub it is moot (wg0 cannot bind the port mesh0 holds), on a spoke it is hazardous (two interfaces, one key, flapping). The found unit running again beside the mesh's is reported as not-taken with a note naming systemctl stop wg-quick@<iface>, and not touched.
New package internal/tunnel (wg-quick config parser + finder).
Do not merge without the controller PR.
Implements hq ADR 0105 on the host side. Pairs with mesh-controller `feat/adopt-the-tunnel` (#49). Revised after review (H1, H2, H6, C3's host half, C4, rekey path).
**Genesis (adopted)**: finds the one WireGuard interface up besides `mesh0` (`--tunnel` names one when several are), settles `--hub-port` and `--overlay-range` on it (a disagreeing value is refused naming the tunnel's), exempts the hub port held by the tunnel from the ports-free check, and skips ADR 0100's non-overlap check only for a range that is now the tunnel's.
**Enrolment**: the found interface's private key becomes the node's overlay key (`identity.OverlayKeyFrom`), stored exactly as a generated one — never printed, never sent. The tunnel travels in the enrol request as `tunnel`.
**`mesh-host overlay take --tunnel <iface>`** — for a node that enrolled before this feature. Rewrites `overlay.key` and `identity.Overlay` with the found key; identity, sealing and serving keys are the same bytes in and out (`rekey_test.go`), so nothing the mesh sealed to the node is remade. Sends a `Report{rekey}` signed by the identity key over `RekeyProof(node, previous, key, tunnel)`; told first, written second, and the key before the take is kept as `overlay_before` so a re-run names the same `previous`. The running host's `mesh0` picks the key up when the next push restarts it.
**Apply**: a `service` may carry `takes-over` (adopted declarations only). **Nothing is stopped until the mesh's interface is known to replace the found one**: the declared config (the file the service restarts on) must have `ListenPort` = found port, `Address` = found address, and the key file its `PostUp … private-key <path>` names must hold the found key — else refused before any stop, naming the remedy (`overlay take` / re-place). Then the found config is kept like any held file, the found unit stopped and disabled, never flushed. **If wg-quick@mesh0 then fails to start, wg-quick@wg0 is started again** and the account says so. An interface still up with its unit inactive (raised by hand) is re-checked 3× over ~6 s, then refused naming `wg-quick down <iface>`. The account has three states — `not-taken`, `taken`, `down` (found down, mesh's not up) — read from the machine, and is given on every takeover declaration, failure included.
**H6 note**: the first build re-stopped a found unit somebody started again on every apply. Dropped: on the hub it is moot (wg0 cannot bind the port mesh0 holds), on a spoke it is hazardous (two interfaces, one key, flapping). The found unit running again beside the mesh's is reported as `not-taken` with a note naming `systemctl stop wg-quick@<iface>`, and not touched.
New package `internal/tunnel` (wg-quick config parser + finder).
Do not merge without the controller PR.
On an adopted machine the private network takes the predecessor's tunnel
over in place (hq ADR 0105). Genesis finds the one interface up besides the
mesh's own, settles the hub's port and the mesh's range on it, and skips
ADR 0100's non-overlap check for a range that is now the tunnel's; a
--hub-port or --overlay-range that disagrees is refused naming the tunnel's.
At enrolment the found interface's private key becomes this node's overlay
key — the one credential the mesh takes rather than mints — stored where a
generated one is stored, never printed and never sent; the tunnel (port,
address, range, peers) travels with the keys so the mesh composes from it
before the first declaration.
The interface's service may say what it takes over. Before the mesh's unit
starts, the found configuration is kept like any held file and the found
unit is stopped and disabled; nothing is flushed, and an interface still up
after its unit stopped refuses the takeover rather than half-working. The
report says what was carried: interface, port, range, peer count, taken or
not, and where the original was kept.
Review of the ADR 0105 build (hq ADR 0105). The takeover stopped the found
unit and then found out whether the mesh's interface would do; a start that
failed left the machine with no tunnel at all.
Now nothing is stopped until the declared interface listens on the found port
at the found address and the key file it names holds the found key — the
refusal names the remedy — and a mesh interface that fails to start after the
takeover has the found unit started again, with the account saying so. The
account has three states (not taken, taken, down) and is given on every
takeover, failure included. An interface raised by hand is looked at again
for a moment and then refused naming `wg-quick down`. A found unit started
again by hand beside the mesh's is said, not stopped: on the hub it cannot
hold the port, and on a spoke two interfaces with one key would fight.
`mesh-host overlay take --tunnel <iface>` is the path for a node that
enrolled before the mesh knew to take a tunnel over: the found key becomes its
overlay key — identity, sealing and serving keys untouched, so nothing sealed
to the node is remade — and the mesh is told with a rekey signed by the
identity key, over the key left, the key taken and the tunnel. Told first,
written second, so a run again puts right whichever half did not happen.
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Implements hq ADR 0105 on the host side. Pairs with mesh-controller
feat/adopt-the-tunnel(#49). Revised after review (H1, H2, H6, C3's host half, C4, rekey path).Genesis (adopted): finds the one WireGuard interface up besides
mesh0(--tunnelnames one when several are), settles--hub-portand--overlay-rangeon it (a disagreeing value is refused naming the tunnel's), exempts the hub port held by the tunnel from the ports-free check, and skips ADR 0100's non-overlap check only for a range that is now the tunnel's.Enrolment: the found interface's private key becomes the node's overlay key (
identity.OverlayKeyFrom), stored exactly as a generated one — never printed, never sent. The tunnel travels in the enrol request astunnel.mesh-host overlay take --tunnel <iface>— for a node that enrolled before this feature. Rewritesoverlay.keyandidentity.Overlaywith the found key; identity, sealing and serving keys are the same bytes in and out (rekey_test.go), so nothing the mesh sealed to the node is remade. Sends aReport{rekey}signed by the identity key overRekeyProof(node, previous, key, tunnel); told first, written second, and the key before the take is kept asoverlay_beforeso a re-run names the sameprevious. The running host'smesh0picks the key up when the next push restarts it.Apply: a
servicemay carrytakes-over(adopted declarations only). Nothing is stopped until the mesh's interface is known to replace the found one: the declared config (the file the service restarts on) must haveListenPort= found port,Address= found address, and the key file itsPostUp … private-key <path>names must hold the found key — else refused before any stop, naming the remedy (overlay take/ re-place). Then the found config is kept like any held file, the found unit stopped and disabled, never flushed. If wg-quick@mesh0 then fails to start, wg-quick@wg0 is started again and the account says so. An interface still up with its unit inactive (raised by hand) is re-checked 3× over ~6 s, then refused namingwg-quick down <iface>. The account has three states —not-taken,taken,down(found down, mesh's not up) — read from the machine, and is given on every takeover declaration, failure included.H6 note: the first build re-stopped a found unit somebody started again on every apply. Dropped: on the hub it is moot (wg0 cannot bind the port mesh0 holds), on a spoke it is hazardous (two interfaces, one key, flapping). The found unit running again beside the mesh's is reported as
not-takenwith a note namingsystemctl stop wg-quick@<iface>, and not touched.New package
internal/tunnel(wg-quick config parser + finder).Do not merge without the controller PR.