Self-Hosted Remote Desktop: The Full 2026 Guide (RustDesk + GoDesk Relay)

Want remote desktop where your traffic never touches a vendor's server? This guide walks through self-hosting the relay end-to-end on a $5/month VPS, what to install, how to harden it, and how to handle the failure modes that the docs skip over.
For most users, the vendor-hosted relay (TeamViewer's, AnyDesk's, GoDesk's) is fine. End-to-end encryption means the relay sees ciphertext only, it can't read your screen frames, keystrokes, or files. But "fine" isn't "ideal" if you have one of these constraints:
- Compliance: regulated industry where data must not transit any third-party infrastructure (legal, defense, certain healthcare).
- Sovereignty: you don't want your remote-access metadata (who connected to what, when, for how long) collected by anyone.
- Cost at scale: if you're running 100+ devices through a relay, vendor fees add up, self-hosted relay on a $5 VPS handles thousands of sessions.
- Air-gapped or restricted networks: the vendor relay isn't reachable from your environment.
If any of those describe you, this guide walks through self-hosting end-to-end on a basic VPS. The reference stack is RustDesk's hbbs + hbbr, which both GoDesk and RustDesk clients can connect to. Total setup time: about 30 minutes including TLS.
What you're building
Two services:
- hbbs (rendezvous server): handles the initial handshake. Both clients connect to it briefly to discover each other, exchange public keys, and figure out whether direct P2P is possible. Listens on TCP/UDP 21115-21117.
- hbbr (relay server): if direct P2P fails (NAT, firewall), traffic flows through the relay. Listens on TCP 21117 (and UDP for some scenarios).
The relay only kicks in when P2P doesn't work, which is most consumer scenarios because of NAT, but rare on a same-LAN setup. So even with self-hosted relay, you're only paying VPS bandwidth for the sessions that need it.
Step 1: Pick a VPS
Bandwidth is the main resource. CPU and RAM are minimal (the relay is just forwarding bytes). Reasonable picks in 2026:
- Hetzner CX22 (€4/mo, 2 vCPU, 4 GB RAM, 20 TB bandwidth, EU data centers), best price-to-bandwidth ratio.
- DigitalOcean Basic Droplet ($6/mo, 1 vCPU, 1 GB, 1 TB bandwidth), good UX, US/EU regions.
- OVH VPS Starter (€3.50/mo, 2 vCPU, 2 GB, unmetered bandwidth), best for high-bandwidth scenarios.
- Hetzner Storage Box, NOT a VPS, listed because some readers ask. Won't work for this; you need an actual server.
Pick a region close to where the connecting clients will be, this matters for latency since relay traffic is round-trip-bound.
Step 2: Set up the server
Spin up a fresh Ubuntu 22.04 or Debian 12 VPS. SSH in as root.
# Update + harden basics
apt update && apt upgrade -y
apt install -y ufw fail2ban docker.io docker-compose-plugin
ufw allow 22/tcp # SSH
ufw allow 21115:21119/tcp
ufw allow 21115:21119/udp
ufw enable
systemctl enable --now docker
Don't skip the firewall. RustDesk's default config exposes only the ports it needs, but the rest should be locked down.
Step 3: Run hbbs + hbbr via Docker
Create /opt/godesk-relay/docker-compose.yml:
services:
hbbs:
image: rustdesk/rustdesk-server:latest
container_name: hbbs
restart: unless-stopped
ports:
- "21115:21115/tcp"
- "21116:21116/tcp"
- "21116:21116/udp"
- "21118:21118/tcp"
command: hbbs -r your-server.example.com:21117
volumes:
- ./data:/root
hbbr:
image: rustdesk/rustdesk-server:latest
container_name: hbbr
restart: unless-stopped
ports:
- "21117:21117/tcp"
- "21119:21119/tcp"
command: hbbr
volumes:
- ./data:/root
Replace your-server.example.com with the actual hostname. Start it:
cd /opt/godesk-relay
mkdir -p data
docker compose up -d
docker compose logs --tail 20
You should see hbbs print a public key on first start, save it from the logs (id_ed25519.pub in the data volume) because clients use it to verify they're connecting to YOUR relay and not a man-in-the-middle.
Step 4: Configure DNS
Point an A record for relay.yourdomain.com at the VPS's IP. RustDesk also accepts a bare IP, but a hostname is more flexible if you ever migrate.
Step 5: Point clients at the self-hosted relay
This is the part most guides skim over. Each client needs three configuration values:
- ID server =
relay.yourdomain.com:21116 - Relay server =
relay.yourdomain.com:21117 - Public key = the contents of
data/id_ed25519.pubfrom your VPS
On Windows / macOS / Linux:
- Open the GoDesk or RustDesk client.
- Settings → Network → ID/Relay server.
- Enter the three values above. Save.
- Restart the client.
The status indicator should turn green within a few seconds, showing it's registered with your relay. If it stays red, check the firewall rules and that the public key matches exactly.
Step 6: Add TLS (optional but recommended)
The default RustDesk protocol is already encrypted at the application layer (the public key you copied is part of that). Adding TLS on top adds a second layer and protects against some passive-network attacks. Setup involves a reverse proxy (nginx or Caddy) in front of the relay ports.
Caddy version (simpler):
relay.yourdomain.com {
reverse_proxy /ws/* localhost:21118
reverse_proxy * localhost:21115
}
Caddy auto-issues the Let's Encrypt cert. Update clients to use port 443 with TLS enabled.
Step 7: Backup the keys
The data/ directory contains the rendezvous server's key pair. If you lose it, every client has to be reconfigured with the new public key. Back it up:
# Local backup
rsync -avz vps:/opt/godesk-relay/data/ ~/godesk-relay-backup-$(date +%Y%m%d)/
# OR copy the two key files
scp vps:/opt/godesk-relay/data/id_ed25519* ~/godesk-keys/
Store the backup somewhere offline. If the VPS is compromised, you want to be able to spin up a new one with the same keys so existing clients keep working without reconfiguration.
Failure modes the docs don't mention
Failure 1: Clients can't reach the relay. 90% of the time this is the firewall. Check ufw status, check that the cloud provider's security group also allows the same ports, and run nc -vz relay.yourdomain.com 21116 from a client to verify reachability.
Failure 2: P2P always falls back to relay. Symmetric NAT or strict corporate firewalls force everything through the relay. This is normal, performance is good but bandwidth metering applies. Use relay.yourdomain.com with a high-bandwidth VPS plan.
Failure 3: The relay process dies and doesn't restart. Docker's restart: unless-stopped handles most cases. Add docker compose ps to a cron job that alerts you on missing containers.
Failure 4: SSL cert expires. If you're using Caddy, this is automatic, it renews 30 days before expiry. If you're using nginx + certbot, set up a cron job to renew. certbot.eff.org has the official guide.
Bandwidth math
Quality matters here. Rough back-of-envelope:
- Low quality (text-heavy work): ~50 KB/s = 180 MB/hour
- Medium (general office work): ~200 KB/s = 720 MB/hour
- High (video, design): ~1 MB/s = 3.6 GB/hour
A Hetzner CX22 with 20 TB/month bandwidth handles roughly 5,500 hours of high-quality sessions per month, way more than any individual or small team will use. The 20 TB cap is more relevant for organizations with hundreds of devices.
Pre-built option: GoDesk's self-hostable relay
Everything above is the manual route using RustDesk's open-source stack. GoDesk publishes a self-host bundle of the same hbbs/hbbr stack with sensible defaults pre-configured. If you don't want to manage Docker compose files, see our self-hosting guide, same architecture, with a one-command install script that wraps the steps above.
When NOT to self-host
Self-hosting adds operational overhead: monitoring, key backups, OS updates, certificate renewal. If your use case is "I want to remote into my home PC", the vendor-hosted relay (free GoDesk tier handles 5 GB/month) is far less work than running your own VPS forever.
Self-host if you have a real reason, compliance, sovereignty, scale. Skip it if "it'd be cool" is the only motivation; the operational tax catches up with you eventually.
Recap
- $5/month VPS in your preferred region.
- Docker + UFW + RustDesk's hbbs/hbbr containers.
- DNS A record pointing at the VPS.
- Three config values on each client (ID server, relay server, public key).
- Backup the keys.
- Optional: TLS via Caddy/nginx.
End-to-end setup time: 30 minutes. Ongoing maintenance: minimal. The result: remote desktop where your traffic never transits anyone else's infrastructure.
For more on the GoDesk side of this, self-hosting documentation, the open-source landscape, or the client itself.