mirror of
https://github.com/UNITRONIX/BetterDesk.git
synced 2026-10-26 22:37:07 +00:00
75a77a368e
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)
190 lines
6.4 KiB
YAML
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 |