Himansh Raj

Building a Remote Desktop Over the Network

· 3 min read

Building a Remote Desktop Over the Network

I wanted to reach my desktop from anywhere without opening a single inbound port on my router. So I built PC Dashboard — a self-hosted remote PC management app that runs on my Windows 11 machine and exposes it securely to the internet at pc.himansh.in.

The goal wasn't to reinvent RDP. It was to have one browser tab where I can watch the machine, open a shell, move files around, and, when I need it, get the actual Windows desktop — all without a VPN or a firewall hole.

How it reaches the machine

The core trick is that nothing listens for inbound connections. Everything flows through a Cloudflare Tunnel that the PC opens outbound:

  • Browser to Cloudflare Edge to Cloudflare Tunnel to the PC
  • The tunnel fans out to a few local services — the dashboard, a terminal server, Guacamole for the desktop, and any dynamic port forwards

Because the connection is outbound, no inbound firewall rules are needed. Access is also gated twice: Cloudflare Zero Trust (OTP email + a 24-hour session) sits in front, and the dashboard itself has its own auth layer with password, passkey (WebAuthn), and TOTP options.

The remote desktop piece

The part I care about most here is the in-browser desktop. Rather than write a screen-capture and input-injection pipeline from scratch, I leaned on Apache Guacamole running in Docker, which speaks RDP and renders it as HTML5:

  • One-click start/stop of the Guacamole container from the dashboard
  • A full Windows desktop in the browser — no client install
  • It rides the same tunnel as everything else

Using Guacamole meant the hard problems of clientless RDP — codec, input, clipboard — were already solved, and I could focus on wiring it into the dashboard cleanly.

Everything else in the tab

A remote desktop is more useful when you don't actually need the desktop for most tasks. So the dashboard also gives me:

  • System monitoring — real-time CPU, RAM, GPU (NVIDIA + iGPU), and disk, with live charts updating every 2 seconds and a searchable process table
  • In-browser terminal — a real emulator via xterm.js + node-pty over WebSocket, with tabs for PowerShell, CMD, and WSL
  • File manager — browse every drive, upload/download, inline text editing, plus video/audio streaming and PDF/image preview
  • App launcher — one-click Jupyter Lab, VS Code Web, or Open WebUI, each auto-routed through a fresh subdomain
  • Port forwarding — expose a local port as a *.himansh.in subdomain on the fly via the Cloudflare API, no tunnel restart

What I learned

A few things stuck with me building this:

  1. Outbound tunnels beat inbound holes. Cloudflare Tunnel plus Zero Trust gave me remote access with a better security posture than port-forwarding ever would.
  2. Reuse the solved parts. Guacamole handled clientless RDP so I didn't have to; my job was integration, not codecs.
  3. The desktop is the fallback, not the default. Most days the terminal, files, and monitors are enough — the full desktop is there for the times nothing else will do.

The stack is Next.js 14 + Bun, Tailwind and shadcn/ui, systeminformation for metrics, and Cloudflare Tunnel tying it together.

If you want to look at the code, here it is: remote-desktop on GitHub.