Skip to content

Cross-Device SSH (Tailscale + SSH config + Termux)

S2 · Pattern 🔬 Research 2026-04-17

Run ssh pc from any device you own — laptop, phone, remote machine — and land inside the PC’s WSL shell, reattach the running Zellij session, pick up exactly where you left off. No port forwarding, no key management, no IP memorization.

ComponentRole
TailscaleDevice-mesh authentication + stable IP per device
SSH daemon on the PCThe actual SSH target
~/.ssh/config with an aliasOne-word hostname
Termux (Android) or Termix (iOS)Mobile client
Zellij or tmux inside the SSH sessionSo the session survives disconnect

On the PC (server side):

Terminal window
# WSL2 on Windows:
curl -fsSL https://tailscale.com/install.sh | sh
sudo tailscale up

On the phone (Android): Install Tailscale from Play Store, sign in with the same account.

On any other device: same — install the client, sign in. All devices now appear in your tailnet.

Section titled “2. Enable Tailscale SSH (optional but recommended)”
Terminal window
sudo tailscale up --ssh

This lets Tailscale handle SSH authentication via the tailnet identity — no SSH keys needed. Per-device authorization happens in the Tailscale admin console.

If you prefer classic SSH key auth, skip --ssh and continue with normal ~/.ssh/authorized_keys.

Terminal window
# On the PC
tailscale status

You’ll see a MagicDNS name like pc-name.your-tailnet.ts.net and an IP like 100.x.y.z. MagicDNS is preferred — it’s stable across IP reassignments.

4. Configure SSH alias on each client device

Section titled “4. Configure SSH alias on each client device”

In ~/.ssh/config on laptop, phone, any other client:

Host pc
HostName pc-name.your-tailnet.ts.net
User your-username
ForwardAgent yes
ServerAliveInterval 60
ServerAliveCountMax 3

Replace pc-name.your-tailnet.ts.net with your actual MagicDNS name (or the 100.x.y.z IP if you skip MagicDNS).

Terminal window
ssh pc

You should land on the PC’s shell. If Tailscale SSH is enabled: no password prompt, no key prompt. Authentication happened via Tailscale.

Two options:

Option A: Auto-attach on SSH login — append to ~/.bashrc on the PC:

Terminal window
# If SSH'd in and not already in zellij, attach main session
if [[ -n "$SSH_CONNECTION" ]] && [[ -z "$ZELLIJ" ]]; then
zellij attach --create main
fi

Option B: Manual attach — just run zellij attach main after SSH’ing in, or use the z/zk/zl helpers from ../profiles/bashrc-snippets/zellij-helpers.sh.

Option C: Portagenty — from github.com/cybersader/portagenty — run pa to pick a workspace, which attaches the right session.

Terminal window
# On first install
pkg update && pkg upgrade
pkg install openssh
# Copy ~/.ssh/config from laptop to Termux's ~/.ssh/config
# Then
ssh pc

Tailscale’s Android app keeps the mesh up in the background. As long as Tailscale is active, ssh pc works.

Termux doesn’t exist for iOS due to Apple’s sandboxing. Options:

  • Termix — iOS SSH client with a terminal emulator. Works. Less rich than Termux.
  • GitHub Codespaces — access a cloud dev env from mobile. Different model (dev container vs your-machine).
  • a-Shell — Linux-ish shell for iOS. Limited SSH capability.

I haven’t committed to an iOS workflow. Termix is the lowest-effort path.

The session lives on the PC. Any client with Tailscale + SSH config reattaches it.

sequenceDiagram
participant L as Laptop
participant P as PC (Zellij)
participant Ph as Phone
L->>P: ssh pc
P-->>L: attach "main" session
Note over L,P: working...
L--xP: disconnect (close lid)
Note over P: session persists
Ph->>P: ssh pc (later)
P-->>Ph: same session resumes
Note over Ph,P: working...
L->>P: ssh pc (next day)
P-->>L: same session, all devices can attach
  • Disable public SSH port on the PC. Tailscale makes this fine — clients reach the PC via the tailnet only.
  • Tailscale ACLs — if your tailnet has multiple users, restrict who can SSH to your dev machine.
  • Rotate Tailscale auth keys periodically. Tailscale admin console supports this.
  • Don’t use ForwardAgent yes on untrusted systems. Only on your own devices.

Use MagicDNS hostnames in your SSH config, not IPs. Hostnames are stable; IPs can rotate.

Add ServerAliveInterval 60 to the SSH config (already in the example above). This keeps the session alive during brief network blips.

Check if the PC rebooted. Zellij sessions don’t survive reboots unless you use a supervisor. For reboot survival, consider zellij-layout with auto-launch via systemd user unit.

Confirm Tailscale is active on Android (notification shield icon). Confirm ssh your-full-tailnet-hostname works from another device before trying the alias.