Intro
I built a terminal server that runs on my home machine and lets me open a full shell from my iPhone. No cloud, no relay, no App Store. Here's how it works and why I made some of the choices I did.
Section: The Problem with Existing Tools
Brief walkthrough of why ttyd, tmate, and raw SSH from mobile all have meaningful tradeoffs for the "check your home machine from anywhere" use case.
Section: Why Tailscale Serve (Not Funnel, Not a Reverse Proxy)
Explains the decision to use tailscale serve specifically — how it provides HTTPS, a stable URL, and tailnet-only access without any router config or cert management. Why this was the right tradeoff versus self-hosting a reverse proxy or using tailscale funnel.
Section: The Terminal Stack: xterm.js + Socket.IO
Short technical explanation of how the browser terminal works — xterm.js renders the frontend, Socket.IO streams the PTY output, Node.js spawns the shell process. What the latency characteristics look like in practice over Tailscale.
Section: PWA on iPhone — What Works and What Doesn't
Honest assessment of the PWA terminal experience on iOS. What works well (add to home screen, full-screen mode), what's still rough (keyboard behavior, copy/paste quirks), and what I'd change.
Section: ntfy Integration for Session Notifications
How the ntfy push notification setup works — fires when a session exits. Why this is useful for long builds or monitoring agent processes. How to configure it with a self-hosted ntfy instance.
Section: Setup and Getting Started
One-command setup walkthrough. Prerequisites (Node.js, Tailscale), what npm run setup:tailscale actually does, and how to verify it's working.
Section: What's Missing / Roadmap
Honest list of rough edges: session persistence across reloads, multi-machine dashboard maturity, mobile keyboard quirks. What I'm actively working on.
Closing
Link to GitHub, invitation for feedback, note on AGPL-3.0 licensing.
Top comments (0)