Self-hosted RustDesk Server Pro relay (hbbs/hbbr) on AWS EC2 via CDK
This repository has been archived on 2026-08-04. You can view files and clone it, but cannot push or open issues or pull requests.
Find a file
Adam Moussa d5dc998dc5
Document CDK app structure in README
The README described the deployed architecture and resources but never
documented that the repo itself is a CDK v2 app, leaving cdk.json and
the bin/lib layout unexplained for anyone opening the codebase.

Add a "CDK app" section mapping cdk.json, bin/app.ts, the stack file,
cdk.context.json, and the TypeScript config to their roles, so the
infrastructure-as-code component is discoverable from the README.
2026-07-10 15:56:34 -04:00
.github chore(ci): SHA-pin org reusable-workflow caller refs (INFRA-50) (#9) 2026-07-06 18:27:28 -04:00
bin Add RustDesk Server Pro self-hosted relay stack 2026-06-28 16:47:32 -04:00
docker Add RustDesk Server Pro self-hosted relay stack 2026-06-28 16:47:32 -04:00
lib Add internal DNS for the Pro admin console (#2) 2026-06-28 17:25:14 -04:00
userdata Add RustDesk Server Pro self-hosted relay stack 2026-06-28 16:47:32 -04:00
.gitignore Add RustDesk Server Pro self-hosted relay stack 2026-06-28 16:47:32 -04:00
cdk.context.json Add internal DNS for the Pro admin console (#2) 2026-06-28 17:25:14 -04:00
cdk.json build(deps): migrate CDK app ts-node->tsx, adopt typescript 7 (INFRA-183) (#10) 2026-07-08 17:33:56 -04:00
package-lock.json build(deps): migrate CDK app ts-node->tsx, adopt typescript 7 (INFRA-183) (#10) 2026-07-08 17:33:56 -04:00
package.json build(deps): migrate CDK app ts-node->tsx, adopt typescript 7 (INFRA-183) (#10) 2026-07-08 17:33:56 -04:00
README.md Document CDK app structure in README 2026-07-10 15:56:34 -04:00
RUNBOOK.md Add RustDesk Server Pro self-hosted relay stack 2026-06-28 16:47:32 -04:00
tsconfig.json Add RustDesk Server Pro self-hosted relay stack 2026-06-28 16:47:32 -04:00

rustdesk-server

CI Dependency Review TypeScript AWS CDK

Self-hosted RustDesk Server Pro (remote-desktop relay + rendezvous) for Sea Haven Industries, deployed to AWS via CDK.

Status: scaffold — not yet deployed. See First deploy.

Architecture

A single ARM64 EC2 instance runs RustDesk Server Pro (hbbs rendezvous/ID + hbbr relay) in Docker. Clients connect from anywhere over the public internet to a stable Elastic IP fronted by rustdesk.seahaven.com.

RustDesk clients (anywhere)
        │  TCP 21114-21119 / UDP 21116
        ▼
   Elastic IP ──► EC2 t4g.small (AL2023 arm64, SSM-managed)
                    │  Docker: hbbs + hbbr (network_mode: host)
                    ├─ /dev/xvda  20 GiB root (OS only, ephemeral)
                    └─ /var/lib/rustdesk ◄── standalone EBS 20 GiB (RETAIN)
                                              key pair + sled DB
   Nightly DLM snapshots (retain 30, tag rustdesk-backup=true)

All durable state (the id_ed25519 server key pair and the sled database) lives on a standalone, RETAINed EBS data volume, never an inline block device, so it survives instance replacement and stack deletion. See RUNBOOK.md.

CDK app

This repository is an AWS CDK v2 app written in TypeScript. It defines a single rustdesk-server CloudFormation stack — everything under Resources is declared as infrastructure-as-code here rather than provisioned by hand.

Path Role
cdk.json CDK app manifest. Its app command (npx tsx bin/app.ts) tells the CDK CLI how to synthesize the app — tsx executes the TypeScript entry point directly, with no separate compile step. Also holds the watch globs for cdk watch and the CDK feature-flag context.
bin/app.ts App entry point. Instantiates one RustdeskServerStack with an explicit stackName: "rustdesk-server" (kebab-case, matching the repo) pinned to account 328440206208 / us-east-1.
lib/rustdesk-server-stack.ts The stack definition — EC2 instance, standalone EBS data volume, Elastic IP, security group, IAM role, DLM policy, and Route 53 records. Deploy-time tunables (pinned image tag, VPC/subnet IDs, the RUSTDESK_PORTS map) are constants at the top of the file.
cdk.context.json Cached context lookups (VPC / subnet / AZ metadata) written by the CDK CLI; committed so synth is deterministic.
tsconfig.json, package.json TypeScript config and dependencies. aws-cdk-lib is pinned to an exact version and kept current by Dependabot; npm run synth / diff / deploy wrap the CDK CLI.

Synthesized CloudFormation templates land in cdk.out/ (git-ignored). See Deployment for the synth/deploy commands.

Documentation

The canonical map of Sea Haven's AWS infrastructure lives in Confluence. This project's rustdesk-server stack is represented there as a Mermaid subgraph.

Ports

Port Proto Purpose Exposure
21114 TCP Pro web console / API VPN/VPC only (10.10.0.0/16, 10.20.0.0/16)
21115 TCP hbbs NAT type test public
21116 TCP + UDP hbbs registration / hole punch / heartbeat public
21117 TCP hbbr relay public
21118 TCP hbbs web client (websocket) public
21119 TCP hbbr web client (websocket) public

Relay/rendezvous ports are public so clients connect from anywhere. The Pro admin console (21114) is restricted to the office VPN + VPC, so you administer the server and activate the Pro license over VPN. To take the relay VPN-only later, flip the public flags in RUSTDESK_PORTS in the stack.

Resources

  • EC2 rustdesk-server — AL2023 arm64, t4g.small, SSM-managed (no inbound SSH)
  • EBS data volume rustdesk-data — 20 GiB GP3, encrypted, RemovalPolicy.RETAIN, attached at /dev/xvdf
  • Elastic IP — stable public address, associated to the instance
  • Security group rustdesk-server — RustDesk ports above
  • IAM role rustdesk-server-instance — AmazonSSMManagedInstanceCore + secretsmanager:GetSecretValue on rustdesk/*
  • DLM rustdesk-server-dlm — nightly instance snapshots, retain 30
  • Route 53 A record rustdesk.seahaven.com → EIP

Configuration

Secrets (Secrets Manager) — created out of band

Secret Contents
rustdesk/server-key-pair id_ed25519 private + .pub public key generated by hbbs on first boot (mirror up post-deploy so a replacement host keeps the same key)
rustdesk/pro-license RustDesk Server Pro license key

SSM parameters (non-secret)

Parameter Purpose
/rustdesk-server/relay-host Public hostname clients use (rustdesk.seahaven.com)

The pinned Docker image tag lives in lib/rustdesk-server-stack.ts (RUSTDESK_IMAGE_TAG).

Deployment

CI/CD runs through the reusable org workflows (ci-typescript-cdk.yaml, cd-cdk.yaml). Pushes to main deploy automatically.

npm ci
npx cdk diff
npx cdk deploy

First deploy

  1. Confirm a public subnet ID in us-east-1a and set PUBLIC_SUBNET_ID in lib/rustdesk-server-stack.ts (replace subnet-REPLACE_ME).
  2. Verify/pin RUSTDESK_IMAGE_TAG.
  3. Create the OIDC deploy role githubdeploy-rustdesk-server and the repo secret AWS_DEPLOY_ROLE_ARN.
  4. cdk deploy (or push to main). The instance boots, pulls the images, and hbbs generates the key pair on the empty data volume.
  5. SSM in, read /var/lib/rustdesk/id_ed25519{,.pub}, store into rustdesk/server-key-pair.
  6. Over the office VPN, open http://rustdesk.seahaven.com:21114, activate the Pro license, create users (the console is not reachable off-VPN).
  7. Point a test client at rustdesk.seahaven.com + the public key; confirm a session relays.

Operations

See RUNBOOK.md for key rotation, restore-from-snapshot, and instance replacement.