From e44f1cfe4db08cb55508aed8201bcae44ce95285 Mon Sep 17 00:00:00 2001 From: oz6un Date: Tue, 14 Jul 2026 07:12:17 +0300 Subject: [PATCH] =?UTF-8?q?chore:=20remove=20mosh=20=E2=80=94=20it=20can't?= =?UTF-8?q?=20work=20with=20Tailscale=20SSH?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit mosh can't bootstrap through Tailscale SSH: tailscaled swallows TCP :22 after WireGuard decryption and never feeds it to a real OpenSSH server, which mosh-server needs. Verified end-to-end (auth + mosh-server + bidirectional UDP all work, yet the handshake fails on both a Mac and a phone; Tailscale #4919). The repo installed mosh AND the README told users to 'mosh devbox' — a package that does nothing and a doc that can't deliver. Removed both; tmux already provides the session survival mosh was there for (and survives reboots too). FOOTGUNS records why + the OpenSSH-on-a-separate-port workaround for anyone who wants it. Live box brought to parity. Co-Authored-By: Claude Fable 5 --- README.md | 3 ++- cloud-init.yaml | 1 + docs/FOOTGUNS.md | 10 ++++++++++ 3 files changed, 13 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index b1c6a5b..11d9113 100644 --- a/README.md +++ b/README.md @@ -87,7 +87,8 @@ Optional: enable **Tailscale Serve** on your tailnet for HTTPS preview URLs — - **`ssh devbox`** lands you in fish inside a persistent tmux session. Detach with `Ctrl-b d`, split with `Ctrl-b |` / `Ctrl-b -`, new window with `Ctrl-b c`. Mouse works and selections copy to your local clipboard. Sessions survive network drops and the nightly reboot — layouts - restore, and `claude --continue` resumes a conversation. Use `mosh devbox` on flaky networks. + restore, and `claude --continue` resumes a conversation. tmux is what makes reconnecting + seamless; if your client drops, reconnect and you're back exactly where you were. - **`http://devbox:`** opens any dev server from any tailnet device — no flags, no tunnels — including localhost-only binds and Docker publishes. For HTTPS (secure cookies, service workers), run `tailscale serve --bg ` for `https://..ts.net`, and `tailscale serve off` when done. diff --git a/cloud-init.yaml b/cloud-init.yaml index 082fcf7..75a2ba4 100644 --- a/cloud-init.yaml +++ b/cloud-init.yaml @@ -41,6 +41,7 @@ packages: - python3 - docker.io - docker-compose-v2 + # (mosh intentionally absent — it can't bootstrap through Tailscale SSH; see FOOTGUNS) users: - name: ${DEV_USER} diff --git a/docs/FOOTGUNS.md b/docs/FOOTGUNS.md index 4e3ed67..372e949 100644 --- a/docs/FOOTGUNS.md +++ b/docs/FOOTGUNS.md @@ -131,6 +131,16 @@ broke something in practice; don't re-learn them. - **ntfy mirror in claude-notify**: nothing subscribed to the topic after Pushover won; it was a second HTTP call per event to nobody. Single-channel now; ntfy is ~15 lines to re-add if a free/desktop channel is ever wanted. +- **mosh**: can't bootstrap through **Tailscale SSH** — `tailscaled` swallows all + TCP :22 packets after WireGuard decryption and never hands them to the kernel's + sshd, and mosh needs a *real* OpenSSH server to launch `mosh-server`. Verified + end-to-end (SSH auth + `mosh-server` + bidirectional UDP all work, yet the mosh + handshake fails on both a Mac and a phone) — see Tailscale issue #4919. Not a + firewall or locale problem; the design is fundamentally incompatible. tmux + already covers session survival (and survives reboots, which mosh can't). To + actually get mosh, run classic OpenSSH on a non-22 port (tailscaled owns 22) + + a device key, and point the client's mosh at that port — an opt-in worth adding + only if someone genuinely wants the instant-echo feel. ## Hetzner