mirror of
https://github.com/sol1/rustguac.git
synced 2026-09-10 09:35:45 +00:00
0a6b27cc4b
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.
386 lines
12 KiB
Markdown
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
|