neovim-ide/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  wayne
  • user optional — defaults to $ROAMING_DEFAULT_USER or current user
  • mount optional — omit if you only run commands, never mount

Onboarding a Fresh Client

The whole point: a new device needs almost nothing.

  1. Install your SSH key to reach nvimide.tailnet.ts
  2. 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 err greps 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 -t always).
  • 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_keys with 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.