Files
rustguac/docs/deployment-guide.md
Dave Kempe 0a6b27cc4b docs(installation): document non-Debian-13 install paths
Add 'Other Linux distributions' section explaining the FreeRDP ABI
mismatch that breaks drive/audio when running the Debian 13 .deb on
Ubuntu 24.04 (and likely other distros). Recommend the Docker image as
the supported path; provide an untested build-from-source recipe for
Ubuntu 24.04 against system FreeRDP 3.5. Mirror the pointer from
deployment-guide.md. Prompted by #153.
2026-06-04 13:26:14 +10:00

386 lines
12 KiB
Markdown

# Deployment Guide
A step-by-step guide for planning and deploying rustguac in production. Covers network architecture, server preparation, RDP target setup, security hardening, and ongoing operations.
## Architecture Overview
A typical deployment has three layers:
```
Internet
|
[HAProxy] ── TLS termination, rate limiting, Knocknoc ACL
|
[rustguac] ── session management, WebSocket proxy, connections
|
[guacd] ── protocol translation (SSH, RDP, VNC)
|
[targets] ── SSH servers, RDP desktops, VNC hosts
```
**All components can run on a single server** for small deployments (up to ~50 concurrent sessions). For larger deployments, guacd is the bottleneck (~158 MB per RDP session) and can be scaled separately.
### Port allocation
| Port | Service | Exposure |
|------|---------|----------|
| 443 | HAProxy (HTTPS) | Public / Knocknoc-gated |
| 8089 | rustguac (HTTPS) | Loopback only (behind HAProxy) |
| 4822 | guacd (TLS) | Loopback only |
| 6000-6099 | Xvnc displays | Loopback only (web sessions) |
## Step 1: Install rustguac
### Debian 13 (recommended)
```bash
# Download the latest .deb from GitHub releases
wget https://github.com/sol1/rustguac/releases/latest/download/rustguac_amd64.deb
sudo apt install ./rustguac_amd64.deb
```
This installs rustguac + guacd to `/opt/rustguac` with systemd services.
### Docker (recommended for non-Debian-13 hosts)
```bash
docker pull ghcr.io/sol1/rustguac:latest
docker run -d \
-p 443:8089 \
-v rustguac-data:/opt/rustguac/data \
-v rustguac-recordings:/opt/rustguac/recordings \
-v ./config.toml:/opt/rustguac/config.toml \
ghcr.io/sol1/rustguac:latest
```
The Docker image bundles guacd + FreeRDP + dependencies, so it runs cleanly on Ubuntu, RHEL, Rocky, Arch, and other distros where the bare-metal `.deb` would hit a FreeRDP ABI mismatch. See [installation.md](installation.md#other-linux-distributions) for the full story on non-Debian-13 targets.
See [installation.md](installation.md) for all install options.
## Step 2: Initial Configuration
### Create an admin API key
```bash
/opt/rustguac/bin/rustguac --config /opt/rustguac/config.toml add-admin --name admin
```
Save the printed key (`rgu_...`) — it is shown only once. Use it for initial setup, then **delete it once OIDC is configured** (see Step 5).
### Edit config.toml
```bash
sudo nano /opt/rustguac/config.toml
```
Key settings for a production deployment:
```toml
listen_addr = "127.0.0.1:8089" # Loopback only — HAProxy handles public TLS
guacd_addr = "localhost:4822"
[tls]
cert_path = "/opt/rustguac/tls/cert.pem"
key_path = "/opt/rustguac/tls/key.pem"
guacd_cert_path = "/opt/rustguac/tls/cert.pem"
# Trust HAProxy's X-Forwarded-For header
trusted_proxies = ["127.0.0.1/32"]
# Network allowlists — restrict what targets guacd can connect to.
# Prevents SSRF via crafted session requests.
[network]
allowed_ssh_cidrs = ["10.0.0.0/8", "172.16.0.0/12", "192.168.0.0/16"]
allowed_rdp_cidrs = ["10.0.0.0/8", "172.16.0.0/12", "192.168.0.0/16"]
allowed_vnc_cidrs = ["10.0.0.0/8", "172.16.0.0/12", "192.168.0.0/16"]
```
See [configuration.md](configuration.md) for the full reference.
### Start services
```bash
sudo systemctl enable --now rustguac
```
Verify: `curl -k https://localhost:8089/api/health`
## Step 3: Set Up HAProxy
HAProxy provides TLS termination, HTTP/2, WebSocket support, and Knocknoc integration.
**Using nginx, Caddy, Apache, or Traefik instead?** See [reverse-proxies.md](reverse-proxies.md) for per-proxy configs and an important `%2F` gotcha that affects nested folder paths on several of them.
### Install
```bash
sudo apt install haproxy
```
### Configure
Create `/etc/haproxy/haproxy.cfg`:
```
global
log /dev/log local0
maxconn 4096
stats socket /run/haproxy/admin.sock mode 0660 level admin
ssl-default-bind-options no-sslv3 no-tlsv10 no-tlsv11
defaults
log global
mode http
option httplog
timeout connect 5s
timeout client 30s
timeout server 30s
timeout tunnel 8h # Long-lived WebSocket sessions
timeout http-request 10s # Slowloris protection
frontend https
bind *:443 ssl crt /etc/ssl/private/rustguac.pem alpn h2,http/1.1
bind *:80
http-request redirect scheme https unless { ssl_fc }
http-request del-header X-Forwarded-For
option forwardfor
http-response set-header Strict-Transport-Security "max-age=31536000; includeSubDomains"
default_backend rustguac
backend rustguac
option httpchk GET /api/health
server rustguac 127.0.0.1:8089 ssl verify none check inter 30s
```
### TLS certificate
Use Let's Encrypt or your organisation's CA:
```bash
# Let's Encrypt example (certbot + HAProxy)
sudo certbot certonly --standalone -d console.example.com
sudo cat /etc/letsencrypt/live/console.example.com/{fullchain,privkey}.pem \
> /etc/ssl/private/rustguac.pem
sudo systemctl restart haproxy
```
## Step 4: Prepare RDP Targets
### Linux (xrdp with H.264)
For the best video experience with Linux desktops, use xrdp with x264 H.264 encoding. A single setup script handles everything — desktop environment, audio, xrdp rebuild with x264, and GFX configuration:
```bash
# On the RDP target machine (not the rustguac server):
wget -O setup-xrdp-gfx.sh https://raw.githubusercontent.com/sol1/rustguac/main/contrib/setup-xrdp-gfx.sh
sudo bash setup-xrdp-gfx.sh --desktop mate
```
The `--desktop` flag installs a desktop environment (default: `mate`). Options: `mate`, `xfce`, `kde`, `gnome`, `none`. MATE is recommended — it's lightweight, Windows-like, and works reliably over xrdp without GPU.
The script runs in three phases:
1. **Phase 1 (pure trixie):** Installs desktop, Firefox, Chromium, build tools, PulseAudio xrdp audio module, switches from PipeWire to real PulseAudio
2. **Phase 2 (temporary sid):** Adds Debian sid repo, installs matching xorgxrdp, rebuilds xrdp with `--enable-x264`, removes sid
3. **Phase 3 (configure):** Xorg backend, startwm.sh, gfx.toml with H.264 + x264 encoder
Run `bash setup-xrdp-gfx.sh --help` for all options, or `bash setup-xrdp-gfx.sh --diagnose` to troubleshoot after setup.
In the rustguac connections, enable these settings on the RDP entry:
- **Enable Graphics Pipeline (GFX)** -- checked
- **H.264 Passthrough** -- checked
- **Enable Desktop Composition** -- not needed for Linux (Windows-only DWM setting)
See [rdp-video-performance.md](rdp-video-performance.md) for manual setup and tuning.
### Windows
Windows RDP works out of the box. For video-heavy workloads:
```powershell
# On the Windows RDP server (as Administrator):
.\contrib\setup-rdp-performance.ps1
# With GPU hardware encoding:
.\contrib\setup-rdp-performance.ps1 -EnableGPU
```
This enables AVC 4:4:4, 60 FPS, desktop composition, and GPU encoding.
**Note:** Windows only sends H.264 when a GPU (physical or virtual) is available. Without GPU, it uses Planar/RemoteFX which guacd re-encodes as JPEG/WebP. This is still good quality — just not as low-latency as H.264 passthrough.
## Step 5: Configure Authentication
### OIDC Single Sign-On (recommended)
Add to `config.toml`:
```toml
[oidc]
issuer_url = "https://your-idp.example.com"
client_id = "rustguac"
redirect_uri = "https://console.example.com/auth/callback"
groups_claim = "groups"
session_ttl_secs = 28800 # 8 hours
[oidc.group_role_mappings]
"RemoteConsoleAdmins" = "admin"
"RemoteConsoleUsers" = "operator"
```
Set the client secret in `/opt/rustguac/env`:
```bash
echo 'OIDC_CLIENT_SECRET=your-secret-here' | sudo tee -a /opt/rustguac/env
sudo chmod 600 /opt/rustguac/env
sudo systemctl restart rustguac
```
See [integrations.md](integrations.md) for provider-specific guides (Authentik, JumpCloud, Entra ID, etc.).
### Delete the bootstrap API key
Once OIDC is working and you have an admin user, remove the initial API key:
```bash
# List admin keys
/opt/rustguac/bin/rustguac --config /opt/rustguac/config.toml list-admins
# Delete by name
/opt/rustguac/bin/rustguac --config /opt/rustguac/config.toml delete-admin --name admin
```
API keys are powerful (full admin, no MFA). For day-to-day use, OIDC with group-based roles is more secure. If you need programmatic API access, create scoped [user API tokens](roles-and-access-control.md) instead.
## Step 6: Set Up the Connections (Vault)
The connections stores connection entries in HashiCorp Vault or OpenBao. Credentials stay server-side — they never reach the browser.
```toml
[vault]
addr = "https://vault.example.com:8200"
mount = "secret"
base_path = "rustguac"
role_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
```
```bash
echo 'VAULT_SECRET_ID=your-secret-id' | sudo tee -a /opt/rustguac/env
sudo systemctl restart rustguac
```
See [integrations.md](integrations.md) for Vault setup, AppRole configuration, and mTLS.
## Step 7: Lock It Down with Knocknoc
[Knocknoc](https://knocknoc.io) removes the attack surface entirely. Instead of exposing rustguac's login page to the internet, Knocknoc gates access at the network layer:
1. **Before Knocknoc:** the login page is visible to scanners, bots, and attackers
2. **After Knocknoc:** the login page returns 403 unless the user has authenticated through Knocknoc first (SSO + MFA)
Only the front page (`/`) is gated. API endpoints, OIDC callbacks, and share links pass through to rustguac's own auth.
### HAProxy + Knocknoc configuration
Add to your HAProxy config:
```
# Dynamic ACL managed by knocknoc-agent
acl knoc_rustguac src -u 600
acl is_root path /
# Gate only the login page
use_backend rustguac if is_root knoc_rustguac
use_backend denied if is_root
use_backend rustguac
```
Install and configure [knocknoc-agent](https://docs.knocknoc.io) to manage ACL #600 via the HAProxy admin socket.
### Why this matters
rustguac gives users administrative access to servers. Even with OIDC and strong passwords, exposing the login page means:
- Brute-force and credential-stuffing attacks
- Zero-day exploits against the web layer
- Reconnaissance by scanners
Knocknoc ensures the login page is only reachable after identity-verified network authentication. The attack surface goes from "the entire internet" to "zero".
## Step 8: Enable Drive Mapping (optional)
Drive mapping lets users transfer files to/from remote sessions.
### Basic (unencrypted)
```toml
[drive]
enabled = true
drive_path = "/opt/rustguac/drives"
drive_name = "Shared Drive"
```
### Encrypted (LUKS + Vault)
For environments requiring at-rest encryption:
```bash
sudo /opt/rustguac/bin/drive-setup.sh
```
This creates a LUKS-encrypted volume with the encryption key stored in Vault. See [integrations.md](integrations.md) for details.
## Step 9: Session Recording (optional)
Session recordings are enabled by default and stored in `/opt/rustguac/recordings`.
```toml
recording_path = "/opt/rustguac/recordings"
[recording_rotation]
enabled = true
max_disk_percent = 80 # Auto-delete oldest when disk usage exceeds 80%
interval_secs = 300 # Check every 5 minutes
```
Recordings can be played back in the browser via the Sessions page, or exported for compliance.
## Ongoing Operations
### Monitoring
- **Health check:** `GET /api/health` returns 200 when rustguac and guacd are running
- **System status:** `GET /api/system/status` (admin only) shows version, uptime, active sessions
- **Reports:** Session history, top connections, top users available at `/reports.html` (poweruser+ role)
### Upgrading
```bash
# Debian package
sudo apt install ./rustguac_new-version.deb
sudo systemctl restart rustguac
```
Config files are preserved across upgrades (`--force-confold`). Database migrations run automatically on startup.
### Backup
Back up these paths:
- `/opt/rustguac/config.toml` — configuration
- `/opt/rustguac/data/rustguac.db` — users, tokens, session history
- `/opt/rustguac/env` — secrets (Vault secret ID, OIDC client secret)
- `/opt/rustguac/recordings/` — session recordings (if needed for compliance)
The connections is in Vault — back up Vault separately.
### Security checklist
- [ ] HAProxy terminates TLS with a valid certificate (not self-signed)
- [ ] rustguac listens on loopback only (`listen_addr = "127.0.0.1:8089"`)
- [ ] Network allowlists configured (prevent SSRF to unintended targets)
- [ ] OIDC configured with group-based role mappings
- [ ] Bootstrap API key deleted after OIDC setup
- [ ] Knocknoc gates the login page (optional but strongly recommended)
- [ ] Drive encryption enabled if file transfer is used in regulated environments
- [ ] Session recording enabled for audit compliance
- [ ] `/opt/rustguac/env` has `chmod 600` permissions
- [ ] Trusted proxies configured to match HAProxy IP