Skip to content
TENVO AI · LIVE · v0.16.4 · TLS · Per-device certs · AGPL-3.0 · FREE TIER · 30 DEVICES · SELF-HOSTABLE INFRA · BYO API KEY · MCP FOR CLAUDE & CURSOR
Back to BlogGuide

Self-hosted remote desktop: the honest 2026 guide

Tenvo Editorial Team12 min read
Self-hosted remote desktop: the honest 2026 guide

You can self-host the relay — the stack is open source and this guide walks the entire install. What the tutorials leave out is what it costs to keep running, and who should actually take that on.

Search for self-hosted remote desktop and you get a dozen tutorials that end at docker compose up -d. The install is the easy part, and it is genuinely 30 minutes. This guide covers it in full — and then covers the part that decides whether you should have done it at all: what the thing costs to keep alive once the tutorial ends.

The short answer

Self-host when a requirement forces you to. Use a managed relay when nothing does. That sounds glib, so here is the actual test:

  • Self-host if: a written compliance obligation says session traffic must not transit third-party infrastructure; you operate air-gapped or otherwise restricted networks where an external relay is unreachable; or data-residency rules name a jurisdiction you must stay inside.
  • Use a managed relay if: your reason is any version of "I'd rather run it myself." That is a real preference, and it is also a standing operations job — see the bill below before you sign up for it.

Worth being clear about what you are choosing between, because it is not two different products. Tenvo is AGPL-3.0 and the managed relay runs the same hbbs/hbbr architecture this guide installs. The choice is who operates the box, not what the software does.

First: what a relay can actually see

This matters before anything else, because it is usually the reason people reach for self-hosting in the first place — and it is usually described wrong.

On a direct peer-to-peer connection, the session runs end-to-end between the two devices. When a direct connection cannot be established — symmetric NAT, strict corporate firewalls — the session is relayed instead, and TLS terminates at the relay. Whoever operates that relay is therefore in a position to see relayed traffic. We are not going to tell you otherwise about ours.

That is a property of the protocol, not of who pays for the server. Running the relay yourself does not encrypt anything that a vendor relay would not; it changes who occupies that position. If your answer to "who is permitted to occupy it" is written into a compliance obligation, self-hosting is the correct answer and the rest of this guide is for you. If it is not written down anywhere, you are taking on an operations job to solve a problem you do not have.

What you are building

Two services:

  • hbbs (rendezvous server): handles the initial handshake. Both clients connect to it briefly to discover each other, exchange public keys, and work out whether direct P2P is possible. Listens on TCP/UDP 21115-21117.
  • hbbr (relay server): carries the session when direct P2P fails. Listens on TCP 21117 (and UDP for some scenarios).

The relay only engages when P2P does not work — common on consumer NAT, rare on a same-LAN setup. So even self-hosted, you only pay VPS bandwidth for the sessions that actually need relaying.

Step 1: Pick a VPS

Bandwidth is the resource that matters. CPU and RAM are minimal, since the relay is forwarding bytes rather than processing them.

  • Hetzner CX22 (€4/mo, 2 vCPU, 4 GB RAM, 20 TB bandwidth, EU data centres) — 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.

Pick a region close to the clients that will connect. Relay traffic is round-trip-bound, so this is the single biggest lever you have on perceived latency — and, as covered below, the one a single VPS is worst at.

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

Do not skip the firewall. The default config exposes only the ports it needs; everything else should be locked down.

Step 3: Run hbbs + hbbr via Docker

Create /opt/tenvo-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, then start it:

cd /opt/tenvo-relay
mkdir -p data
docker compose up -d
docker compose logs --tail 20

hbbs prints a public key on first start. Save it from the logs (id_ed25519.pub in the data volume) — clients use it to verify they are connecting to your relay and not an impostor.

Step 4: Configure DNS

Point an A record for relay.yourdomain.com at the VPS IP. A bare IP works too, but a hostname is far easier to live with if you ever migrate.

Step 5: Point clients at your relay

The part most guides skim. Each client needs three values:

  • ID server = relay.yourdomain.com:21116
  • Relay server = relay.yourdomain.com:21117
  • Public key = the contents of data/id_ed25519.pub from your VPS

On Windows, macOS and Linux:

  1. Open the Tenvo or RustDesk client.
  2. Settings → Network → ID/Relay server.
  3. Enter the three values above and save.
  4. Restart the client.

The status indicator should go green within a few seconds. If it stays red, check the firewall rules and that the public key matches exactly — a trailing newline is the usual culprit.

Step 6: Add TLS

Put a reverse proxy in front of the relay ports. Caddy is the shortest path:

relay.yourdomain.com {
    reverse_proxy /ws/* localhost:21118
    reverse_proxy * localhost:21115
}

Caddy issues and renews the Let's Encrypt certificate for you. Update the clients to use port 443 with TLS enabled — which also gets you through restrictive outbound firewalls that only permit 443.

Step 7: Back up the keys

The data/ directory holds the rendezvous server's key pair. Lose it and every client must be reconfigured with a new public key — by hand, on every machine.

# Local backup
rsync -avz vps:/opt/tenvo-relay/data/ ~/tenvo-relay-backup-$(date +%Y%m%d)/
# OR copy the two key files
scp vps:/opt/tenvo-relay/data/id_ed25519* ~/tenvo-keys/

Store it offline. If the VPS is ever compromised you want to rebuild on a fresh box with the same keys, so existing clients keep working untouched.

The failure modes the tutorials skip

Clients cannot reach the relay. Nearly always the firewall. Check ufw status, check that the cloud provider's security group allows the same ports, and run nc -vz relay.yourdomain.com 21116 from a client to confirm reachability.

Everything falls back to relay. Symmetric NAT and strict corporate firewalls force every session through the relay. Performance holds up, but your bandwidth bill is now the whole story rather than the exception.

The relay dies and does not come back. Docker's restart: unless-stopped covers the common cases. It does not cover a full disk, an OOM kill, or a kernel panic — for those you need monitoring that pages someone, and that someone is you.

The certificate expires. Automatic under Caddy. Under nginx + certbot it is a cron job you have to remember you own; certbot.eff.org has the official guide.

The bill the tutorials do not show you

The €4 VPS is the cheapest line on the invoice, and quoting it as the cost of self-hosting is the same trick as quoting a car's purchase price as the cost of driving. The rest of it:

  • You are on call for your own relay. When it dies at 2am, remote access is what you no longer have to fix it with.
  • OS patching, forever. A public-facing box on the internet is a box you are responsible for keeping patched.
  • Key custody. Lose data/ and you reconfigure every client by hand. That backup is now something you have to actually verify, not just schedule.
  • Certificate renewal. Automatic until the day it is not.
  • One region, one box. A single VPS is one location and no failover. Clients on the far side of the world pay for that in round-trip latency; if the box is down, everyone is down.

Bandwidth is the one cost that is genuinely easy to estimate. Rough figures per relayed session:

  • Low quality, text-heavy work: ~50 KB/s = 180 MB/hour
  • Medium, general office work: ~200 KB/s = 720 MB/hour
  • High, video and design work: ~1 MB/s = 3.6 GB/hour

A Hetzner CX22's 20 TB/month covers roughly 5,500 hours of high-quality relayed sessions. For an individual or a small team that ceiling is never the binding constraint — which is precisely the point. If bandwidth was the reason you were going to self-host, it is not a good one. The binding constraints are the four bullets above it.

What the managed relay does instead

Same architecture, different operator. The relay fleet is multi-region rather than one VPS, so clients connect to something near them instead of near you. It is monitored by people whose job that is. Key material, patching and certificate renewal stop being your problem. When something breaks at 2am, the person paged is not you.

That is what the subscription buys: Free at $0, Lite at $2.99/mo, Pro at $7.99/mo — see pricing for what sits in each tier, or the business plans if you are deploying across a team. Set against a €4 VPS plus your own on-call rota, the arithmetic is not close for most people.

When self-hosting is genuinely the right call

It is the right call when an obligation names it: regulated work where traffic must not cross third-party infrastructure, air-gapped or restricted networks where an external relay is unreachable, or residency rules that pin you to a jurisdiction. In those cases the operational cost is not overhead, it is the requirement, and this guide is exactly what you need.

It also matters that the option exists at all. Tenvo is AGPL-3.0 and the server stack is open source, so the managed relay is a convenience you are buying rather than a lock you are accepting. If we ever stop being worth it, the exit is the guide above — that is the point of publishing it. See how the managed build compares to plain RustDesk, or how the security model works.

Recap

  1. A VPS in the region closest to your clients.
  2. Docker, UFW, and the hbbs/hbbr containers.
  3. A DNS A record pointing at the VPS.
  4. Three config values on every client: ID server, relay server, public key.
  5. An offline backup of data/ that you have actually restored from once.
  6. TLS via Caddy, and monitoring that pages you.

Thirty minutes to stand up; indefinitely to own. If a requirement puts you in that seat, the steps above are the whole job. If nothing does, start on the managed relay — download the client, and come back to this page the day a compliance form makes it relevant.

Get Tenvo

Ready to try it yourself?

Free for 30 devices, no credit card. Up and connected in two minutes.