01 / Title
Deck 09 ยท the remote-control rig

Your desk, in your pocket.

Your phone becomes a real screen + keyboard + mouse for your Mac and Ubuntu box โ€” on the home WiFi, or from a coffee shop three cities away. Built from what the OS already ships, one free app, and (only off the home network) one mesh VPN. $0, no cloud in the control path, no ports opened to the internet.

macOS Screen Sharing x11vnc RealVNC Viewer Tailscale / WireGuard verified live
the gap between a thought and acting on it shouldn't cost a walk to the desk โ€” or a flight home read the full post โ†—
02 ยท the itch

Why would you want this? Four moments.

Not a workstation replacement โ€” occasional, light touches on real work, from wherever you already are.

๐Ÿ›‹๏ธ Mid-rest, an agent needs a nudge

Tap the phone, type "looks good, continue" โ€” it lands as a real keypress in the real terminal.

๐Ÿ”จ A build is running upstairs

Glance at the mirrored terminal. No SSH session to remember, no monitoring app.

๐Ÿ’ฌ A reply is worth sending now

Your normal phone keyboard โ€” glide typing, autocorrect, clipboard โ€” typing into Slack, email, a commit message.

โœˆ๏ธ Another city entirely

The same saved entry still reaches home, through an encrypted tunnel. Zero router ports opened.

2
servers, mostly pre-installed
1
phone app, both machines
1
mesh VPN โ€” only off the LAN
$0
no subscription, ever
03 ยท the route

Three parts. Each removes exactly one constraint.

Set up in order โ€” everything after Part 1 builds on Part 1 and never rebuilds it.

๐Ÿ“ถ
PART 1 ยท SAME NETWORK

Phone drives the desktop over home WiFi. Running today.

โ”€โ”€โ–บ
๐ŸŒ
PART 2 ยท THE INTERNET

Same rig from anywhere โ€” a re-addressing, not a rebuild.

โ”€โ”€โ–บ
โš™๏ธ
PART 3 ยท DEEP DIVE

What's on the wire โ€” for when you want the why.

The one habit worth forming: one phone app โ€” RealVNC Viewer โ€” drives both machines. One saved entry per box (<ip>:5900), each with its own password. Two entries, one muscle memory.
Setup cost: a weekend, once. The payoff doesn't expire.
04 ยท part 1 โ€” why VNC

"Why not just SSH?" SSH can't do this job.

SSH โ€” a parallel door into the basement

Drops you into a new text shell. Can't see the desktop you left running, can't click, can't type into open apps, can't fire shortcuts.

VNC โ€” a mirror plus a hand

Phone sees your apps, exactly as left. Every tap and keystroke is injected as a real input event โ€” indistinguishable from sitting at the keyboard.

the property everything rests onReal input events โ†’ every app and every hotkey listener responds. That's why a phone can fire Super+A or dictate a commit message โ€” and why this rig is VNC-based, not SSH-based. (The gears, slide 18.)
Both OSes serve VNC with built-in or one-command tooling, so any standards-compliant client connects.
05 ยท part 1 โ€” the Mac

The Mac half: the server is already installed.

  1. System Settings โ†’ General โ†’ Sharing โ†’ Screen Sharing โ€” on. Keep it plain Screen Sharing, not Remote Management (RM serves the login window and typing into it drops focus).
  2. โ“˜ โ†’ "VNC viewers may control screen with password" โ€” set that password. Without it, most phone clients fail to connect at all.
  3. Connect from the phone to <mac-ip>:5900 โ€” the VNC password, username blank. (Tested live.)
Android phone running RealVNC Viewer connects over home WiFi to a Mac: VNC over port 5900 into macOS Screen Sharing, which injects real mouse and keyboard events into the desktop input stack
The macOS control path โ€” one toggle + a VNC password and every app responds as if you typed it. Click to zoom.
Bonus over Ubuntu: Screen Sharing serves the login window too โ€” VNC in and log in remotely after a reboot. Full auth quirks: slide 13.
06 ยท part 1 โ€” Ubuntu

The Ubuntu half: one package, one command.

$ sudo apt install -y x11vnc # find the real display number first: who โ†’ "<user> :N <date>" $ x11vnc -display :<N> -auth guess -usepw -shared -repeat -forever
Android phone running RealVNC Viewer connects over home WiFi to an Ubuntu desktop: VNC over port 5900 into x11vnc, which injects real mouse and keyboard events into the existing X11 session
The Ubuntu control path โ€” x11vnc turns the session you're already logged into into the server. Click to zoom.
the two flags that bite-shared (default off): without it, one stale half-open connection blocks every reconnect. -repeat (default off): without it, held keys repeat never โ€” one character per touch. Both earned by real failure.
Persist it: a .desktop file in ~/.config/autostart/ โ€” starts at graphical login. Firewall: ufw allow from <your-subnet> to any port 5900, never wider. Full flag table: the post.
07 ยท part 1 โ€” the phone

The phone half: one app, no account.

RealVNC Viewer, free. Standardized on for one reason that beats any feature list: it speaks the classic VNC auth both servers serve โ€” same app, same gestures, same saved list for the Mac and the Ubuntu box.

Android phone in landscape running RealVNC Viewer, driving a dual-monitor desktop: browser on the left monitor, terminal on the right โ€” both in one VNC session
Verified live: a dual-monitor desktop, both screens in one session โ€” swipe to pan between them, pinch to zoom. Same story on the Mac and Ubuntu. Click to zoom.
read this before signing inRealVNC the company sells a cloud ecosystem โ€” accounts, device lists, "connect from anywhere". None of it is needed. The Viewer connects direct, machine-to-machine. Don't sign in; add an address, connect: <ip>:5900 + its VNC password.
First win to chase: connect, tap anywhere โ†’ the real cursor moves. If it does, the rig works; everything left is technique.
08 ยท part 1 โ€” first drive

First drive: it feels like sitting down.

The moment it clicks โ€” you're on the couch, the desktop is upstairs, and neither of you notices the distance:

โŒจ๏ธ The nudge

Terminal mirrored on the phone. You type "looks good, continue" โ€” it lands as a real keypress in the real terminal, same as if you'd walked over.

๐Ÿ‘€ The glance

A build's mid-run upstairs? Pull up the phone, read the tail of the output, put it away. Nothing to reconnect, nothing to remember.

verified liveWindow switching, multi-key shortcuts, the full keyboard โ€” all from the phone, exactly as from the desk. The next four slides are the technique that makes it fewer taps, every time.
Your normal keyboard comes along: glide typing, autofill, even voice typing โ€” with two cautions coming on slide 12.
09 ยท part 1 โ€” gestures

Your fingers are the mouse: taps are clicks.

All client-side behavior โ€” identical against the Mac and the Ubuntu box.
10 ยท part 1 โ€” everyday moves

The moves you'll use every single day.

Switch terminals by keystroke โ€” use the desktop's window overview (hot corner or Alt+Tab) instead of hunting window thumbnails.
Tip for anything you fire from the phone: pick single-key global hotkeys (End, Insert) โ€” every combo costs an extra arming tap.
11 ยท part 1 โ€” personas

Same three mechanics, whoever you are.

Gestures, modifier toggles, the hot corner โ€” everything above reduces to those three. What changes is what you do with them:

๐Ÿ‘ฉโ€๐Ÿ’ป if you live in terminals

The dev

Ctrl+Shift+C/V to copy-paste in terminals (the Shift is the tell), Ctrl+R history search, โ†‘+Enter to rerun.

๐Ÿงญ if you're browsing, not building

The explorer

Pinch = client-side zoom on dense pages, three-finger tap = middle-click paste, Esc kills dialogs.

๐ŸŽฌ if it's media and messages

Everyone else

Keyboard autofill fills desktop passwords, the emoji panel sends real keystrokes, Space plays and pauses.

Voice typing comes along for free too โ€” the phone's mic key, straight into whatever's focused. Its cautions are next.
12 ยท part 1 โ€” cautions

Two cautions, both learned the annoying way.

caution 1 โ€” autocorrectAutocorrect + terminals don't mix. It will "fix" flags, paths, and git subcommands โ€” and keystrokes arrive already corrected, with no desktop-side guard to catch it. Disable it for the VNC app, or proofread before Enter.
caution 2 โ€” the cursorVoice typing lands wherever the cursor is. Check the focused window before you speak โ€” dictation commits instantly into whatever app owns the cursor.
One honesty note on voice: phone keyboards dictate through their maker's cloud speech service โ€” free and zero-setup, but not offline. Know which way that cuts before dictating anything sensitive.
13 ยท part 1 โ€” when it breaks

When it breaks: three symptoms cover most of it.

The full symptom โ†’ fix table โ€” including the timeout-vs-refused tell and the Mac's three auth behaviors โ€” lives in the post's Reference section. Read it here โ†—
the security line, in one breathKeep 5900 LAN-scoped, treat the VNC password as 8 characters effective, and never port-forward 5900 โ€” needing in from outside is Part 2's job.
14 ยท part 2 โ€” off the LAN

"Wait โ€” this only works on my WiFi." Fixable. Not by port-forwarding.

The 2010 advice fails silently on a large share of modern connections. Five minutes tells you which side you're on:

# 1 โ€” router admin panel: note its WAN IP # 2 โ€” ask the internet what IP your desktop is seen as $ curl ifconfig.me # 3 โ€” compare: same โ†’ real public IP, forwarding possible # different, or WAN IP inside 100.64.0.0/10 # โ†’ CGNAT: your ISP's shared NAT drops inbound, forever
CGNAT is standard now on many fiber and 5G connections โ€” your router's "public" side is itself private, inside the ISP's NAT layer. Everything on your side can be perfect and the packets still never arrive.
And even with a clean check โ€” don't, not raw VNC: classic VNC auth is a single shared 8-character password, and a correct guess drives your desktop. The real goal: put phone and desktop on one private network, wherever both physically are.
15 ยท part 2 โ€” the mesh VPN

Tailscale: your private network that follows the devices.

A mesh VPN built on WireGuard encryption. Install it, log in once โ€” every device gets a permanent private 100.x.y.z address (the "tailnet") that never changes when the device moves. The phone just dials that instead of the LAN IP.

Phone on cafรฉ WiFi and desktop at home, each with a permanent 100.x.y.z tailnet address; RealVNC Viewer targets the tailnet IP on 5900; direct WireGuard tunnel end-to-end encrypted, DERP relay fallback carrying ciphertext only; no router ports opened
Part 2 in one picture โ€” a networking-layer swap; the rig's software never learns a VPN exists. Click to zoom.
What actually changes: the address the phone dials (LAN IP โ†’ tailnet IP), one ufw rule (100.64.0.0/10 instead of your subnet), and two small installs. x11vnc, Screen Sharing, the port, the password, the app โ€” all unchanged. A re-addressing, not a rebuild.
16 ยท part 2 โ€” trust

"Can I trust some company's VPN?" Here's the case.

the crypto

WireGuard's, not home-rolled

Formally verified primitives, end-to-end between your two devices only. The coordination server exchanges public keys โ€” relays carry ciphertext by construction.

the code

Data-touching parts are open

Every client and even the relay code are on GitHub. The closed piece โ€” coordination โ€” sees metadata, never payloads.

the exit

Audited, and exit-able

Recurring third-party audits, millions of daily users. If the trade-off ever stops being acceptable: Headscale, a self-hosted control plane, same clients.

E2E
encryption device-to-device
0
router ports opened
1
account, free tier
17 ยท part 2 โ€” the receipts

Not a diagram โ€” a live session.

mobile data
WiFi off, live session
direct
WireGuard path โ€” no relay
~66 ms
phone โ†” desktop
verified from cellularScreen updated, taps and keystrokes landed, every Part 1 skill carried over โ€” on a carrier network. Verify the interaction, not the connection: connect, hit the hot corner, open a terminal, type a line, fire a Ctrl+key combo. Anything stuttery โ†’ tailscale status will say relay โ€” that's transport, not the rig.
The Mac's route ran live too โ€” through the DERP relay, the encrypted fallback (~125 ms, fully usable VNC): the one carrier round where no direct path was punchable. Honest edge: the escape hatches (SSH reverse tunnel, Headscale, Cloudflare Tunnel) remain untested on this rig.
18 ยท part 3 โ€” hotkeys

The deep dive's best trick: why shortcuts fire.

VNC key events reach x11vnc, which calls the XTEST extension to inject input at the X server level โ€” same keycodes, same grabs as the physical keyboard driver, so terminals, the window manager, and global hotkey hooks all respond. SSH delivers bytes to one process's stdin โ€” no keyboard event as far as the OS is concerned
XTEST โ€” the X11 extension built for test automation, injecting at the server level, upstream of every app. Click to zoom.
macOS runs the same play, different plumbing โ€” verified live: shortcuts fired from the phone exactly as from the keyboard.
19 ยท part 3 โ€” finding each other

Your phone and your desktop sit behind two different firewalls. How do they meet?

Rendezvous sequence: both peers contact the server outbound; each learns the other's observed address; both send at each other simultaneously so each side's outbound packet opens a pinhole in its own NAT for the other's packets to slip through
The rendezvous trick: both sides send at each other simultaneously โ€” each outbound packet opens a pinhole in its own firewall. Click to zoom.
the envelope

WireGuard

Each device pair shares keys; traffic is a sealed UDP envelope no relay can open.

the usual outcome

Direct path

Coordination tells each side the other's address; the simultaneous handshake connects them directly.

the fallback

DERP relay

When no direct path is punchable: encrypted packets relayed through Tailscale's servers. Slower by a hop, still ciphertext โ€” a post office, not a listener.

See which path you're on: tailscale status prints "direct" or "relay" per peer โ€” it explains the latency you feel.
20 ยท part 3 โ€” the protocol

RFB โ€” the conversation every VNC session opens with.

Sequence diagram of the RFB handshake: version exchange, security negotiation where macOS serves two auth types at once, DES challenge-response where the password is the DES key, then framebuffer updates and pointer/key events
RFC 6143 โ€” step 3 is where the 8-character cap lives. Click to zoom.
why 8 characters, mechanicallyClassic VNC auth is a DES challenge-response: the server sends a challenge; the client encrypts it with DES using the password itself as the key โ€” and DES keys are 8 bytes. Whatever you type past character 8 never enters the computation. Every classic-auth implementation inherits it โ€” macOS and x11vnc alike. Not a bug: the protocol wearing its age on its sleeve.
This is also why the Mac can serve two auth doors at once โ€” a client negotiating the wrong one dies with a rejected-correct-password loop. Symptom โ†’ layer โ†’ check map: the post's Reference.
21 ยท after setup โ€” the daily loop

After the weekend: nothing to type.

The VPN runs as a service, the servers autostart, the firewall rule persists across reboots. What's left in a normal week:

start ยท only if you unloaded it

Mac server on

sudo launchctl load -w โ€ฆ/screensharing.plist โ†’ confirm with the port check. Phone: VPN toggle โ†’ saved entry.

check ยท ten seconds

Me or the rig?

tailscale status โ€” online? direct or relay? Then nc -vz <ip> 5900: refused = server off ยท timeout = path ยท succeeded = go.

stop ยท done for the day

Close things down

Phone: disconnect, VPN off (battery). Mac: the matching unload โ€” one line each direction, both survive reboots.

Ubuntu has no daily anything โ€” server, VPN, and firewall all persist on their own. The Mac's launchctl pair is the only on/off in the whole internet rig.
22 ยท the bill

What it actually costs: see for yourself.

$0
software, forever
1
Saturday of setup
2
OSes, served by built-ins
3
routes verified live
23 ยท where this landed

Where this landed: a full second seat at the desk.

Every "verified" above means run live on the actual rig โ€” the build story is in the post, failures included.
24 ยท build it

The couch is a valid place to get something done. So is another city.

Part 1 alone takes an evening and works on your home network today. The internet comes along later as one small install.

Tools: macOS Screen Sharing (built-in) ยท x11vnc (GPL-2.0) ยท RealVNC Viewer (free, direct mode) ยท Tailscale (free personal, WireGuard E2E)

Deck Controls

SpaceNext slide
Previous slide
Home / EndFirst / last slide
19Jump to slide N
OOverview grid
GGo to slide
FToggle fullscreen
BBlackout screen
?Toggle this help
Click diagramZoom (lightbox)
Click left / right halfPrev / next slide
Swipe (touch)Prev / next slide
Press ? or Esc to close

All slides โ€” click to jump