Files
rustdesk-server/docs/DOCKER.md
T
mike 8ad3f43d21
build / build-linux-amd64 (push) Successful in 1m48s
ci(linux): add build workflow + Docker build instructions
2026-05-07 09:53:29 +02:00

191 lines
9.6 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# RustDesk Server — Docker Compose Deployment
The repo ships a `docker-compose.yml` that **builds the server from source**
(this fork's `pro-features` branch) and runs `hbbs` + `hbbr` as two
containers. No prebuilt image is pulled — every `docker compose build`
clones the configured Git URL and runs `cargo build --release` inside the
build stage.
For the runtime flag reference (CLI options accepted by `hbbs` itself), see
[CONFIGURATION.md](CONFIGURATION.md). This document only covers the Compose
glue.
---
## Quick start
```bash
cp .env.example .env
# edit .env — at minimum set RUSTDESK_DOMAIN, and change
# RUSTDESK_BOOTSTRAP_ADMIN_PASSWORD before the first boot
docker compose up -d --build
```
The bootstrap admin (default `admin` / `changeme`) is seeded into the
`users` table on the **first** boot only — once the row exists, those
flags are ignored. If you boot with the default password and forget to
change it, rotate it via the admin UI; if you forget the password
entirely, delete `./data/db_v2.sqlite3` (loses all server-side state) or
edit the `users` row with `sqlite3` directly.
First build pulls the Rust toolchain image and compiles the workspace; expect
several minutes. Subsequent builds reuse the cargo cache layer unless the
Git ref or build args change.
After it boots:
| Endpoint | Port | Purpose |
|------------------------------------------|---------|------------------------------------------|
| `tcp://<domain>:21115` | 21115 | NAT test |
| `tcp+udp://<domain>:21116` | 21116 | ID / rendezvous (desktop clients) |
| `tcp://<domain>:21117` | 21117 | Relay (hbbr) |
| `ws://<domain>:21118` | 21118 | Browser-facing rendezvous WebSocket |
| `ws://<domain>:21119` | 21119 | Browser-facing relay WebSocket |
| `http://<domain>:21114/admin/` | 21114 | Admin dashboard (pro-features) |
| `http://<domain>:21114/api/*` | 21114 | Management API (pro-features) |
Persistent state — including the auto-generated `id_ed25519` keypair and the
SQLite database — lives in `./data/` (bind-mounted to `/root` in both
containers).
---
## Files
| File | Role |
|-----------------------------|---------------------------------------------------------------------------------------|
| `docker-compose.yml` | Two services (`hbbs`, `hbbr`) sharing one image built from `docker/Dockerfile.source`.|
| `docker/Dockerfile.source` | Multi-stage build: clones the repo, runs `cargo build --release`, copies binaries into a `debian:bookworm-slim` runtime. |
| `.env.example` | Documented template; copy to `.env`. |
| `data/` | Created on first run. Contains keypair + SQLite DB. **Back this up.** |
The legacy single-stage `docker/Dockerfile` (busybox + s6-overlay, expects
prebuilt binaries) and `docker-classic/Dockerfile` are unrelated to this
flow and unused by `docker-compose.yml`.
---
## Environment variables
These are read by `docker-compose.yml` from `.env`. Compose ships them
through to the container as command-line flags or `environment:` entries,
not as raw process env (with the exception of `RUST_LOG` and
`ALWAYS_USE_RELAY`, which `hbbs` reads from env directly).
### Runtime
| Variable | Default | Effect |
|--------------------------------|-----------------|-------------------------------------------------------------------------------------------------------|
| `RUSTDESK_DOMAIN` | **required** | Public hostname clients connect to. Passed as `hbbs -r ${RUSTDESK_DOMAIN}:21117`. |
| `RUSTDESK_BOOTSTRAP_ADMIN_USERNAME` | `admin` | Seeded as the initial admin on **first boot only** (when the `users` table is empty). Ignored on subsequent restarts. Empty disables the bootstrap. |
| `RUSTDESK_BOOTSTRAP_ADMIN_PASSWORD` | `changeme` | Same — bcrypt-hashed at insert. Change this in `.env` before the first `up`, or rotate via the admin UI immediately after. |
| `RUSTDESK_KEY` | `-` | Pre-shared key. `-` = auto-generate on first boot (written to `./data/id_ed25519{,.pub}`); `_` = encrypted-only with auto-key; or paste a base64 public key to pin it. Applied to **both** `hbbs` and `hbbr` via `-k`. |
| `RUSTDESK_HTTP_PORT` | `21114` | Pro-features admin API + dashboard port. Set to `0` to disable HTTP entirely. The host port published is the same value. |
| `RUSTDESK_ALWAYS_USE_RELAY` | `N` | Force every session through the relay even on LAN. Read from env by hbbs (any non-empty/non-`N` value enables). |
| `RUST_LOG` | `info` | Log filter. e.g. `debug`, `hbbs=debug,sqlx=warn`. |
### Build source
| Variable | Default | Effect |
|------------------------|---------------------------------------------------------------|-----------------------------------------------------------------------------------------|
| `RUSTDESK_GIT_URL` | `https://gitea.cstudio.ch/mike/rustdesk-server.git` | Repo cloned inside the builder stage. |
| `RUSTDESK_GIT_BRANCH` | `pro-features` | Branch / tag / commit to check out (`--branch` so it must be a ref name, not a SHA). |
| `DATABASE_URL` | unset (uses the cloned repo's `.env`) | Overrides the `DATABASE_URL` sqlx reads at compile time. Rarely needed — see below. |
Build-arg changes only take effect when the image is rebuilt:
`docker compose build --no-cache hbbs` (or `up -d --build`).
---
## Why `DATABASE_URL` is a build-time concern
`hbbs` uses `sqlx::query!` macros, which verify SQL **at compile time** by
running the queries against a real SQLite database. The repo includes a
checked-in `db_v2.sqlite3` with the schema pre-applied, and a tracked `.env`
file pointing at it (`DATABASE_URL=sqlite://./db_v2.sqlite3`).
Cargo automatically reads `.env` from the project root, so `cargo build`
inside the builder stage Just Works without any explicit configuration.
You only need to set `DATABASE_URL` in the Compose `.env` if you fork the
schema or want to point the compile-time check at a different SQLite file.
At **runtime** the binary opens its own DB under `/root/` (your `./data/`
bind mount) — that path is not configurable via this variable.
---
## Adding extra `hbbs` flags
`docker-compose.yml` only wires the most common flags. To pass others
(SMTP, OIDC, recording dir, audit retention, …), edit the `command:`
block of the `hbbs` service. Example — enable SMTP and set the public
base URL needed for OIDC callbacks:
```yaml
command: >
hbbs
-r ${RUSTDESK_DOMAIN:?...}:21117
-k ${RUSTDESK_KEY:--}
--http-port ${RUSTDESK_HTTP_PORT:-21114}
--admin-ui-dir /opt/rustdesk/admin_ui
--bootstrap-admin-username=${RUSTDESK_BOOTSTRAP_ADMIN_USERNAME:-}
--bootstrap-admin-password=${RUSTDESK_BOOTSTRAP_ADMIN_PASSWORD:-}
--public-base-url https://${RUSTDESK_DOMAIN}:${RUSTDESK_HTTP_PORT:-21114}
--smtp-host ${SMTP_HOST}
--smtp-user ${SMTP_USER}
--smtp-pass ${SMTP_PASS}
--smtp-from ${SMTP_FROM}
```
Then add the matching variables to `.env`. The full flag list lives in
[CONFIGURATION.md](CONFIGURATION.md).
If you mount an `oidc.toml`, drop it into `./data/` and pass
`--oidc-config /root/oidc.toml`.
---
## Operational notes
**Upgrading.** Pull the latest commit on `pro-features` and rebuild:
```bash
docker compose build --pull --no-cache
docker compose up -d
```
The `--pull` refreshes the Rust toolchain base image; `--no-cache` forces a
fresh `git clone` (otherwise Docker will reuse the cached clone layer).
Alternatively, bump `RUSTDESK_GIT_BRANCH` to a tag and rebuild — the changed
build arg invalidates the clone layer automatically.
**Logs.** `docker compose logs -f hbbs` (or `hbbr`). Both containers run
the binary in the foreground.
**Persistence.** Everything that matters is in `./data/`:
`id_ed25519{,.pub}` (the server keypair — losing this invalidates every
existing client) and `db_v2.sqlite3` (users, address books, audit, etc.).
Back up the whole directory.
**TLS.** The server itself speaks plain HTTP on 21114 and plain WebSocket
on 21118 / 21119. Front it with nginx or Caddy for TLS — see the "TLS
deployment" section in `CONFIGURATION.md`. When you do, set
`--http-listen=127.0.0.1` and `--ws-listen=127.0.0.1` in the `command:`
block so the reverse proxy can claim the public ports.
**Building behind a proxy.** Pass `HTTP_PROXY` / `HTTPS_PROXY` build args
through Compose:
```yaml
build:
<<: *rustdesk-build
args:
HTTP_PROXY: http://proxy.internal:3128
HTTPS_PROXY: http://proxy.internal:3128
```
**Resource hint.** Cold compile takes ~35 GB of RAM for the linker step
(LTO + `codegen-units = 1`). On a small VPS, build the image on a beefier
machine, push to a registry, and pull from the VPS instead — set the
`image:` field to a registry tag and drop the `build:` block.