Files
BetterDesk/docker-compose.yml
T
UNITRONIX 75a77a368e fix(docker): align auth stores and remove withdrawn agent builds
Make split Compose services use one explicit primary SQLite database and forward admin credentials to both Go and Node.js. Remove Docker and installer CI dependencies on withdrawn agent source trees, and add regression coverage for Docker build contexts and bootstrap mappings.

Refs #385

Thanks: INSOLVE (Honorary); Marco Jakobs (@jacotec); MyNameisStitch (@MyNameisStitch); Redspin (@playerumpknow)
2026-09-16 13:09:51 +02:00

190 lines
6.4 KiB
YAML

# BetterDesk Console - Docker Compose Setup
# Architecture: Go server (single binary) + Node.js web console
#
# ============================================================================
# QUICK START (no build required):
# curl -fsSL https://raw.githubusercontent.com/UNITRONIX/Rustdesk-FreeConsole/main/docker-compose.quick.yml -o docker-compose.yml
# docker compose up -d
#
# BUILD FROM SOURCE (this file):
# docker compose build && docker compose up -d
# ============================================================================
#
# The Go server replaces separate hbbs/hbbr — it handles signal, relay,
# and HTTP API in a single process.
services:
# BetterDesk Server (Go) — replaces hbbs + hbbr
# Single binary: signal (21116), relay (21117), API (21114), NAT test (21115)
server:
build:
context: .
dockerfile: Dockerfile.server
image: betterdesk-server:local
pull_policy: never
container_name: betterdesk-server
hostname: betterdesk-server
command: ["/usr/local/bin/betterdesk-server", "-mode", "all", "-api-port", "21114", "-key-file", "/opt/rustdesk/id_ed25519"]
ports:
- "21114:21114" # Go HTTP API (default — direct client + REST)
- "21115:21115" # NAT type test
- "21116:21116/tcp" # Signal TCP
- "21116:21116/udp" # Signal UDP
- "21117:21117" # Relay TCP
- "21118:21118" # WebSocket Signal
- "21119:21119" # WebSocket Relay
volumes:
- rustdesk-data:/opt/rustdesk
- console-data:/app/data:ro
environment:
- ENCRYPTED_ONLY=1
- DB_URL=${DB_URL:-/opt/rustdesk/db_v2.sqlite3}
- AUTH_DB_PATH=/app/data/auth.db
# Admin credentials (first run only; existing users are not overwritten).
# Keep these mappings in both services so Go and Node.js seed the same account.
- ADMIN_PASSWORD=${ADMIN_PASSWORD:-}
- INIT_ADMIN_USER=${ADMIN_USERNAME:-admin}
- INIT_ADMIN_PASS=${ADMIN_PASSWORD:-}
- SQLITE_AUTH_DB_MODE=${SQLITE_AUTH_DB_MODE:-}
- SIGNAL_RATE_LIMIT_PER_IP=${SIGNAL_RATE_LIMIT_PER_IP:-20}
- P2P_FIRST=${P2P_FIRST:-Y}
- ALWAYS_USE_RELAY=${ALWAYS_USE_RELAY:-N}
- P2P_FALLBACK_MS=${P2P_FALLBACK_MS:-2000}
- SAME_NAT_RELAY=${SAME_NAT_RELAY:-Y}
# Enrollment policy. Fresh volumes default to "managed" (operator approves
# new devices); pre-existing volumes keep their current mode. Set to
# "open", "managed", or "locked" to override.
- ENROLLMENT_MODE=${ENROLLMENT_MODE:-}
- NTP_SERVERS=${NTP_SERVERS:-pool.ntp.org,time.google.com,time.cloudflare.com}
- BILLING_MAX_CLOCK_SKEW_MS=${BILLING_MAX_CLOCK_SKEW_MS:-2000}
- BILLING_REQUIRE_SYNCED_CLOCK=${BILLING_REQUIRE_SYNCED_CLOCK:-1}
- BILLING_TRUST_OS_NTP=${BILLING_TRUST_OS_NTP:-Y}
# Optional: map betterdesk to host bind-mount owner (Synology etc.). Default 10001.
- PUID=${PUID:-10001}
- PGID=${PGID:-10001}
networks:
- betterdesk-net
restart: unless-stopped
# SECURITY (audit fix L-02, 2026-04-10): drop all capabilities except
# those needed by the entrypoint to chown volumes + su-exec to non-root.
security_opt:
- no-new-privileges:true
cap_drop:
- ALL
cap_add:
- SETUID
- SETGID
- CHOWN
- FOWNER
healthcheck:
test: ["CMD", "curl", "-sf", "http://localhost:21114/api/health"]
interval: 30s
timeout: 10s
retries: 3
start_period: 60s
# BetterDesk Console — Node.js Web Interface
console:
build:
context: .
dockerfile: Dockerfile.console
image: betterdesk-console:local
pull_policy: never
container_name: betterdesk-console
hostname: betterdesk-console
ports:
- "5000:5000" # Web console (admin panel)
- "21121:21121" # Backward compat proxy → Go :21114
volumes:
- rustdesk-data:/opt/rustdesk # Shared server data (keys, db) — needs write for WAL mode
- console-data:/app/data # Console sessions and optional legacy auth.db
environment:
- NODE_ENV=production
- PORT=5000
- HOST=0.0.0.0
- API_HOST=0.0.0.0
- API_ENABLED=true
- API_PORT=21121
- RUSTDESK_API_PROXY=true
- GO_API_PORT=21114
- SERVER_BACKEND=betterdesk
- HBBS_API_URL=http://betterdesk-server:21114/api
- BETTERDESK_API_URL=http://betterdesk-server:21114/api
- RUSTDESK_PATH=/opt/rustdesk
- DATA_DIR=/app/data
- DB_PATH=/opt/rustdesk/db_v2.sqlite3
- SQLITE_AUTH_DB_MODE=${SQLITE_AUTH_DB_MODE:-}
- PUB_KEY_PATH=/opt/rustdesk/id_ed25519.pub
- API_KEY_PATH=/opt/rustdesk/.api_key
- SESSION_SECRET=${SESSION_SECRET:-}
# Admin credentials (first run only; existing users are not overwritten).
- ADMIN_PASSWORD=${ADMIN_PASSWORD:-}
- DEFAULT_ADMIN_USERNAME=${ADMIN_USERNAME:-admin}
- DEFAULT_ADMIN_PASSWORD=${ADMIN_PASSWORD:-}
- WS_HBBS_HOST=betterdesk-server
- WS_HBBS_PORT=21116
- WS_HBBR_HOST=betterdesk-server
- WS_HBBR_PORT=21117
- DOCKER=true
# Optional: map betterdesk to host bind-mount owner (Synology etc.). Default 10001.
- PUID=${PUID:-10001}
- PGID=${PGID:-10001}
networks:
- betterdesk-net
restart: unless-stopped
# SECURITY (audit fix L-02, 2026-04-10): drop all caps except those
# needed by su-exec (SETUID/SETGID) and volume permission fixes (CHOWN/FOWNER).
security_opt:
- no-new-privileges:true
cap_drop:
- ALL
cap_add:
- SETUID
- SETGID
- CHOWN
- FOWNER
depends_on:
server:
condition: service_started
healthcheck:
test: ["CMD", "curl", "-sf", "http://localhost:5000/health"]
interval: 30s
timeout: 10s
retries: 3
start_period: 30s
# Nginx Reverse Proxy (Optional — only with --profile nginx)
nginx:
image: nginx:alpine
container_name: betterdesk-nginx
ports:
- "80:80"
- "443:443"
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf:ro
- ./ssl:/etc/nginx/ssl:ro
networks:
- betterdesk-net
restart: unless-stopped
depends_on:
- console
profiles:
- nginx
volumes:
rustdesk-data:
driver: local
driver_opts:
type: none
o: bind
device: ${RUSTDESK_DATA_PATH:-./data}
console-data:
driver: local
networks:
betterdesk-net:
driver: bridge
ipam:
config:
- subnet: 172.28.0.0/16