SSH into one stable Tailscale node and reach your whole tailnet from it via short per-host functions + sshfs mounts. A riced Arch dev container with sshd, a stateful home, and declarative .env auth. See README.md and ROAMING.md.
4.0 KiB
Roaming ~ — arch-dev v3
Turn neovim-ide into your roaming home directory. SSH in from any device, and every server on your tailnet feels like home: one keyring, one shell history, one set of dotfiles, reachable from anywhere.
This is what makes neovim-ide more than another riced nvim install — it's a control plane for your whole fleet.
The Model
You (phone / tablet / chromebook)
↓ ssh
nvimide.tailnet.ts ← your roaming home (this container)
↓ ssh / sshfs over tailnet
┌──────────┬──────────┬──────────┐
mail proxy dev (any host)
You live in nvimide. Files live on remote hosts (mounted via sshfs when you want them). Commands run on remote hosts via short per-host functions.
Keys never leave nvimide — agent auth handles remote login, remote sudo
still prompts (the security boundary stays intact).
Files
| File | Purpose |
|---|---|
~/.config/roaming/hosts |
Registry — one line per host (source of truth) |
~/.config/roaming/roaming.zsh |
Engine — generates host functions, mount helpers |
add_new_machine.sh |
Onboard a new host (key + register + verify) |
Usage
Run commands on a host
Each registry entry becomes a command. Dumb by design — pipes and redirects run locally, exactly like plain ssh (predictable, no surprises).
mail # interactive shell on mail
mail tail -f /var/log/mail.log # TTY allocated — -f works
mail sudo systemctl restart postfix # remote sudo prompts for password
proxy sudo systemctl reload caddy
dev docker compose logs -f
Mount a host's filesystem
mount_host mail # sshfs the registered path → /workspace/mail
ls /workspace/mail/etc/postfix/
unmount_host mail # clean unmount (handles stale mounts)
Mounts use reconnect,ServerAliveInterval=15,ServerAliveCountMax=3 so a
network blip errors out in ~45s instead of freezing your shell forever.
Status & reload
roaming-status # list hosts + which are mounted
roaming-reload # re-read registry after editing hosts by hand
Add a new machine
add_new_machine.sh mail mail.tailnet.ts root /
# 1. ssh-copy-id (one password prompt)
# 2. appends to ~/.config/roaming/hosts
# 3. verifies key-based login
After that, mail works in the next shell (or after roaming-reload).
Registry Format
# name fqdn user mount
mail mail.tailnet.ts root /
proxy proxy.tailnet.ts admin /etc/caddy
dev dev-server.tailnet.ts youruser
useroptional — defaults to$ROAMING_DEFAULT_USERor current usermountoptional — omit if you only run commands, never mount
Onboarding a Fresh Client
The whole point: a new device needs almost nothing.
- Install your SSH key to reach nvimide.tailnet.ts
- SSH in — you're home. Dotfiles, history (atuin), keys, the works.
No per-device key sprawl. nvimide holds the fleet keyring; clients only need to reach nvimide.
Gotchas (learned, baked in)
- Pipes are local.
mail tail -f log | grep errgreps locally. Want it remote? Quote the whole pipeline:mail 'tail -f log | grep err'. - Stale mount frozen?
fusermount3 -uz /workspace/<name>force-clears it. tail -f/htop/ sudo need a TTY — handled (ssh -talways).- Agent forwarding (
-A) is intentionally OFF — a compromised remote could abuse a forwarded agent. Add per-host later only if you need to hop.
Roadmap (future hardening)
- SSH CA + OIDC (Authelia) — replace
authorized_keyswith short-lived certs issued after Authelia auth. Collapses key management fleet-wide. Deferred: keys stay as the stable fallback until the cert flow is proven. - autofs — system-level lazy mount/unmount (60s idle auto-unmount) as an
alternative to manual
mount_host. - atuin — single shell-history brain in nvimide, DB in the postgres cluster; retire atuin-server.