Skip to content

Instantly share code, notes, and snippets.

@alpsware
Last active December 30, 2025 06:29
Show Gist options
  • Select an option

  • Save alpsware/dba8debc1ac1099e0054ea03c70418bb to your computer and use it in GitHub Desktop.

Select an option

Save alpsware/dba8debc1ac1099e0054ea03c70418bb to your computer and use it in GitHub Desktop.
Rustdesk Websockets Docker Compose Configuration with Traefik
# SUMMARY:
# This Docker Compose file sets up a Rustdesk self-hosted server with two components:
# 1. Signaling server (hbbs)
# 2. Relay server (hbbr)
#
# Key Features:
# - Integrated with Traefik for HTTPS routing and automatic SSL via Let's Encrypt.
# - Uses external 'traefik' network for reverse proxy.
# - WebSocket connections work out of the box (no manual server file edits needed).
# - TLS ports for direct TCP connections are commented out, uncomment if needed.
# - Both servers share a 'data' volume for keys and db, if relay runs on a different host, copy keys manually.
#
version: '3'
# Variables:
# DOMAIN - used domain
# Traefik will use this to match Host() rules like ${DOMAIN} and relay1.${DOMAIN}.
networks:
traefik:
external: true
# We attach services to the external 'traefik' network so Traefik
# (running as a separate container) can discover and route to them.
services:
# signaling server (hbbs)
rustdesk-server-hbbs:
container_name: rustdesk-server-hbbs
hostname: rustdesk-server-hbbs
command: hbbs
image: rustdesk/rustdesk-server-pro:latest
expose:
- 21114 #hbbs REST/API (admin & public UI behind Traefik)
#ports:
# - 21115:21115 #TCP rendezvous
# - 21116:21116 # TCP NAT forwarding
# - 21116:21116/udp #UDP NAT forwarding
labels:
- traefik.enable=true
- traefik.docker.network=traefik
# setup web
# append '&& PathPrefix(`/api`)' if you only want non admin ui publicly
- traefik.http.routers.rustdesk.rule=Host(`${DOMAIN:-yourdomain.com}`)
- traefik.http.routers.rustdesk.entrypoints=web-secure
- traefik.http.routers.rustdesk.tls=true
- traefik.http.routers.rustdesk.tls.certresolver=certresolver
- traefik.http.services.rustdesk.loadbalancer.server.port=21114
- traefik.http.routers.rustdesk.service=rustdesk
# setup websockets
- traefik.http.routers.rustdeskws.rule=Host(`${DOMAIN:-yourdomain.com}`) && PathPrefix(`/ws/id`)
- traefik.http.routers.rustdeskws.entrypoints=web-secure
- traefik.http.routers.rustdeskws.tls=true
- traefik.http.routers.rustdeskws.tls.certresolver=certresolver
- traefik.http.services.rustdeskws.loadbalancer.server.port=21118
- traefik.http.routers.rustdeskws.service=rustdeskws
environment:
- ALWAYS_USE_RELAY=Y
- ENCRYPTED_ONLY=1
depends_on:
- rustdesk-server-hbbr
volumes:
- data:/root # Shared data: keys/certs/configs. If hbbr runs elsewhere, copy keys.
restart: unless-stopped
networks:
- traefik
# relay server (hbbr)
rustdesk-server-hbbr:
container_name: rustdesk-server-hbbr
command: hbbr
image: rustdesk/rustdesk-server-pro:latest
#ports:
# - 21117:21117 # TCP relay port for direct client connections
labels:
- traefik.enable=true
- traefik.docker.network=traefik
# setup websockets
- traefik.http.routers.rustdeskrelay1.rule=Host(`relay1.${DOMAIN:-yourdomain.com}`) && PathPrefix(`/ws/relay`)
- traefik.http.routers.rustdeskrelay1.entrypoints=websecure
- traefik.http.routers.rustdeskrelay1.tls=true
- traefik.http.routers.rustdeskrelay1.tls.certresolver=certresolver
- traefik.http.services.rustdeskrelay1.loadbalancer.server.port=21119
- traefik.http.routers.rustdeskrelay1.service=rustdeskrelay1
environment:
- ENCRYPTED_ONLY=1
volumes:
- data:/root # Shared keys with hbbs. On separate host, copy keys securely.
restart: unless-stopped
networks:
- traefik
volumes:
data:
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment