Build Your Own Linux Rescue ISO With SSH and a Coding Agent
Build a custom rescue ISO with your SSH keys, ZeroTier network, and pi coding agent baked in. Clone, configure .env, run ./build.sh. Boot it on a remote machine, SSH in from anywhere, run pi to troubleshoot.
Repo: FabianUntermoser/rescue-iso (MIT).
Why not just Use SystemRescue
SystemRescue is great but doesn’t ship a coding agent. Customizing means editing the ISO by hand. I wanted one command to rebuild with my own config baked in. SystemRescue won on maturity and toolset over ZQuickInit, SystemRescueBuilder, and archangel.
How it Works
git clone https://github.com/FabianUntermoser/rescue-iso
cd rescue-iso
cp .env.example .env # fill in your keys and network
./build.sh # produces systemrescue-custom-amd64.isoCopy to Ventoy USB and boot. autorun0 sets root password, generates SSH keys, starts SSH. setup.sh in background installs Node.js, pi, joins ZeroTier. SSH in seconds, agent in a minute.
Remote Access
- Direct SSH: same network,
ssh root@<ip>. - ZeroTier: configure network ID in
.env, approve in ZeroTier Central. - reverse_ssh: built into SystemRescue. Remote machine tunnels to a bounce host (a VPS with a public IP), you connect through it.
The Coding Agent
Pi installed, configure OpenRouter API key in .env. SSH in, run pi. Full SystemRescue toolset: fsck, parted, dd, btrfs, zfs, mdadm, lvm. Untested end to end. Build works, autorun runs, but no real repair yet.
The Build System
build.sh replaces __PLACEHOLDER__ patterns from .env automatically. Add a new placeholder to any script, add the same key to .env, and the build picks it up. Secrets stay out of the repo.
ROOT_PASSWORD=
ZEROTIER_NETWORK=
ZEROTIER_API_KEY=
OPENROUTER_API_KEY=
nofirewall cow_spacesize=2G baked into GRUB via autorun. No boot params to remember.
A couple things I haven’t sorted yet. ZeroTier auto-authorize needs the API key in .env otherwise you approve the device in the web UI. Fine for my use, annoying if you’re mailing the USB to someone. And reverse_ssh needs a bounce host I haven’t set up, so that path is untested.