From 190bc07d563cd3bc55e752727ea1fd2f252e52ba Mon Sep 17 00:00:00 2001 From: Ananth Bhaskararaman Date: Wed, 15 Jul 2026 23:53:09 +0530 Subject: [PATCH 1/2] docs(flatcar): cover remote reprovision (tailscale/headless/watchdog) The stock recipe uses --force and assumes console access. On a host reached only over SSH, the pivot drops the old OS's networking and the launching session with it, leaving you blind while flatcar-install rewrites the disk. Document --tailscale.authkey (tsnet, survives losing host networking), --headless (survive SSH disconnect), and --watchdog-timeout (reboot instead of brick on a hung installer). --- docs/reprovision/flatcar.md | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/docs/reprovision/flatcar.md b/docs/reprovision/flatcar.md index 003802c..42b15f0 100644 --- a/docs/reprovision/flatcar.md +++ b/docs/reprovision/flatcar.md @@ -113,6 +113,40 @@ To pin the Flatcar version explicitly: # then run xmorph as above. ``` +## Reprovisioning a remote host + +The `--force` invocation above assumes you can watch the console. On a +headless box reached only over SSH, the pivot tears down the old OS's +networking the moment services stop — the session that launched xmorph +goes with it, and you're blind while `flatcar-install` rewrites the disk. +Bring your own reachability into the in-RAM installer rootfs: + +```sh +sudo xmorph pivot \ + --image docker.io/alpine:latest \ + --rootfs ./overlay/ \ + --entrypoint /install.sh \ + --tailscale.authkey tskey-auth-xxxxx \ + --headless \ + --watchdog-timeout 20m \ + --force +``` + +- **`--tailscale.authkey`** joins the pivoted rootfs to your tailnet via + tsnet (userspace, so it survives losing the host's own networking). + Default `tailscale up` args are `--ssh --hostname=-xmorph`, so the + host reappears as `-xmorph` with Tailscale SSH while the installer + runs. Use `--tailscale.server` for a Headscale coordination server. + (Plain `--ssh.enable --ssh.authorized-keys` also starts an sshd in the + installer, but only helps if the rootfs still holds a routable address + after pivot — Tailscale doesn't depend on that.) +- **`--headless`** detaches xmorph from the launching terminal (implies + `--force`), so an SSH disconnect doesn't kill the install mid-write. +- **`--watchdog-timeout`** resets the box if the entrypoint hangs, turning + a wedged install into a reboot instead of a silent brick. Still keep an + out-of-band recovery path — `flatcar-install` failing before it writes a + working bootloader leaves the disk unbootable. + ## What happens 1. xmorph pulls `alpine:latest`, merges `./overlay/` on top, and pivots From 1ca5587fcdea76caed36a8ee912429a5ea8b9033 Mon Sep 17 00:00:00 2001 From: Ananth Bhaskararaman Date: Thu, 16 Jul 2026 02:14:32 +0530 Subject: [PATCH 2/2] docs(flatcar): remote reprovision uses auto-detach / --systemd-mode --headless was removed from xmorph; on systemd the pivot now self-relocates into a transient scope so an SSH/run0 disconnect can't kill it, and unit-driven runs use --systemd-mode. Drop --headless from the remote example accordingly. --- docs/reprovision/flatcar.md | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/docs/reprovision/flatcar.md b/docs/reprovision/flatcar.md index 42b15f0..61b5940 100644 --- a/docs/reprovision/flatcar.md +++ b/docs/reprovision/flatcar.md @@ -115,11 +115,11 @@ To pin the Flatcar version explicitly: ## Reprovisioning a remote host -The `--force` invocation above assumes you can watch the console. On a -headless box reached only over SSH, the pivot tears down the old OS's -networking the moment services stop — the session that launched xmorph -goes with it, and you're blind while `flatcar-install` rewrites the disk. -Bring your own reachability into the in-RAM installer rootfs: +The `--force` invocation above assumes you can watch the console. On a box +reached only over SSH, the pivot tears down the old OS's networking the +moment services stop — the session that launched xmorph goes with it, and +you're blind while `flatcar-install` rewrites the disk. Two things to +arrange: staying reachable, and not getting killed with the session. ```sh sudo xmorph pivot \ @@ -127,7 +127,6 @@ sudo xmorph pivot \ --rootfs ./overlay/ \ --entrypoint /install.sh \ --tailscale.authkey tskey-auth-xxxxx \ - --headless \ --watchdog-timeout 20m \ --force ``` @@ -140,8 +139,16 @@ sudo xmorph pivot \ (Plain `--ssh.enable --ssh.authorized-keys` also starts an sshd in the installer, but only helps if the rootfs still holds a routable address after pivot — Tailscale doesn't depend on that.) -- **`--headless`** detaches xmorph from the launching terminal (implies - `--force`), so an SSH disconnect doesn't kill the install mid-write. +- **Surviving the disconnect is automatic on systemd.** Before it builds + the rootfs, xmorph relocates itself into a transient systemd scope (via + `StartTransientUnit`, like `systemd-run --scope`), so the launching SSH + session — or a `run0`/`systemd-run` wrapper — ending won't take the + install down with it. If xmorph *can't* detach (non-systemd host, or the + relocation fails) it warns and pauses a grace window first. +- **Driving it from a unit?** If you launch via a systemd unit yourself + (`systemd-run --unit xmorph-pivot -- xmorph pivot …`, or a + `rescue.target` unit), pass **`--systemd-mode`** instead: it skips the + self-relocation and init coordination and implies `--force`. - **`--watchdog-timeout`** resets the box if the entrypoint hangs, turning a wedged install into a reboot instead of a silent brick. Still keep an out-of-band recovery path — `flatcar-install` failing before it writes a