Running a remote desktop service usually means maintaining a relay server with enough bandwidth to carry every screen frame. That is expensive and creates an obvious bottleneck. A different design is to separate the control plane from the media plane:
- Cloudflare Workers handles the API, authentication, and WebSocket signaling.
- D1, KV, R2, and Durable Objects provide persistence and coordination.
- WebRTC sends screen, keyboard, mouse, and clipboard traffic directly between peers.
- An optional VPS deployment replaces the Cloudflare backend with Node.js, SQLite, and Docker.
GsDesk is an open-source implementation of this architecture. Its server helps two endpoints find and authenticate each other, but it does not relay the desktop video stream.
Why this architecture matters
The expensive part of remote desktop software is continuous media traffic. If a Worker only processes API requests and signaling messages, the majority of bandwidth avoids the server entirely. That makes a free or low-cost serverless control plane practical for personal remote access, home labs, NAS administration, and lightweight IT support.
There is an important limitation: peer-to-peer connectivity depends on the network conditions of both endpoints. Strict NAT or firewall policies can prevent direct connections. A production deployment should therefore test the networks it needs to support and decide whether a TURN relay is required as a fallback.
Fast deployment path
Clone the project and install its dependencies:
git clone https://github.com/gsvps/gsdesk.git
cd gsdesk
npm install
Authenticate Wrangler and deploy the Cloudflare backend:
npx wrangler login
npm run deploy:cloudflare
After deployment, verify two separate routes:
-
https://your-domain.example/should returnsuccess; this is the health endpoint, not the control interface. -
https://your-domain.example/app/should open the browser control interface. The path is configurable throughWEB_APP_PATH.
The Windows client exposes its local UI at http://127.0.0.1:19527. Configure the deployed API URL and the controller JWT secret, enable incoming control on the target device, and connect with its eight-digit device ID plus either a one-time or permanent password.
Self-hosting on a VPS
If you prefer to keep the control plane off Cloudflare, the same protocol can run on a Linux VPS:
docker compose up -d --build
The self-hosted backend uses Node.js, SQLite, local file storage, and WebSockets. This option is useful when you need full control over persistence, logs, or network policy. It does not change the core design: desktop media still uses WebRTC peer-to-peer transport.
Security checklist
Before exposing an instance to the internet:
- Replace
CONTROLLER_JWT_SECRETwith a strong random value. - Treat the device ID as an identifier, not a password.
- Keep Ed25519 device private keys on the endpoint.
- Use OTPs for temporary access and avoid storing them.
- Disable automatic acceptance when users should approve each session.
- Keep API rate limiting and failed-login controls enabled.
- Use HTTPS/WSS and review any custom reverse-proxy configuration.
- Restrict access to the browser control route when your use case permits it.
WebRTC protects media with DTLS, but transport encryption does not compensate for weak controller secrets or overly permissive access settings. Authentication and endpoint security remain part of the threat model.
What to validate after deployment
A basic smoke test should cover more than the home page:
GET / -> success
GET /api/health -> API status and web_app_entry
GET /app/ -> browser controller
Then test device registration, a complete remote session, clipboard synchronization, file transfer, reconnect behavior, and connectivity from the actual networks you intend to use.
The full tutorial includes configuration variables, API routes, directory layout, Windows client build instructions, Cloudflare and VPS deployment details, and troubleshooting notes:
Original guide: https://www.gsvps.com/articles/tutorials-22
Disclosure: I am affiliated with GSVPS, which publishes the original tutorial and maintains the linked GsDesk project.
Top comments (0)