Contributed by @vk2amv (Lindsay). Adds two example VDI container images under contrib/: one with PulseAudio audio, one with PulseAudio + x264/GFX. Contrib-only, no impact on shipping code.
Thanks Lindsay.
Contributed by @vk2amv (Lindsay). Adds Linux Mint Debian Edition 7 detection to the GFX/H.264 setup script, picks the right Debian source codename when LMDE reports its own, replaces the broken upstream PulseAudio sources helper with an inline equivalent that handles both distros, adds Cinnamon as a desktop option, and adds Microsoft Edge installer plus audio diagnostics and a per-session audio loader script.
contrib-only change; no impact on running rustguac deployments.
Thanks Lindsay.
Single shell script in contrib/ that takes a fresh box from "no Vault" to
"rustguac-ready Vault" without copy-pasting the integrations.md walkthrough.
Three modes:
bootstrap (default) Provision an existing Vault using $VAULT_ADDR and
$VAULT_TOKEN. Just creates the policy, AppRole, and
prints the rustguac config snippet.
--dev Spawn `<cli> server -dev` first (in-memory, root
token = "root"), then bootstrap it. For demos and
throwaway local development.
--local Install Vault or OpenBao as a systemd service on
this host with file-backed storage and on-disk
auto-unseal via an ExecStartPost helper. The unseal
key sits at <config_dir>/unseal-key (0400 root:root)
and a SECURITY.txt is written next to it spelling
out the convenience-over-security trade. Single-host
boxes only; for anything else use cloud-KMS unseal.
Auto-detects vault vs bao and picks the right filesystem layout, system
user, and service name for each (vault: /etc/vault.d, vault.service,
vault:vault; openbao: /etc/openbao, openbao.service, openbao:openbao).
Both flavors use the same HCL config grammar so the rest of the script is
shared.
Idempotent: re-running detects existing user, mount, policy, AppRole,
init bundle, and systemd unit. Drop-in is used if a unit already exists
(apt-installed vault) instead of clobbering it.
The script does NOT install the binary itself - it errors cleanly if
vault/bao isn't in PATH and tells the operator to install one.
### OIDC discovery error wrap
src/oidc.rs now reshapes the openidconnect crate's "unexpected issuer
URI `X` (expected `Y`)" validation error into something an operator
can act on without having to reason about which side is the config
and which is the provider. For the overwhelmingly common
trailing-slash case the message collapses to a single actionable
line; for the rarer case where the two URIs differ materially (wrong
tenant, copy-pasted authorise URL, Keycloak path change), it falls
back to a config/provider/fix three-liner. Raw Debug output is
preserved for any non-mismatch discovery failure. Works for any
OIDC provider, not just JumpCloud.
### xrdp TLS key permissions (contrib/setup-xrdp-gfx.sh)
After rebuilding xrdp from sid, the `adduser xrdp ssl-cert` step
from the Debian postinst doesn't always re-apply cleanly, leaving
the xrdp user unable to read /etc/xrdp/key.pem. xrdp then falls
back to "classic RDP security" and FreeRDP drops the connection
with a MAC checksum error. New Step 9 in Phase 3 explicitly adds
xrdp to ssl-cert and normalises the key's ownership/mode. Step
list in the help text renumbered to match.
### Aurora default when [theme] is absent
src/main.rs resolved the theme via ThemeConfig::resolve() only when
config.theme was Some(..), and otherwise fell through to a hardcoded
("dark", builtin_presets()[0].1.clone()) pair. That meant aurora
only kicked in when a [theme] section was present in config.toml,
even an empty one. ThemeConfig now derives Default (all fields
Option<String>, so zero-cost), and main.rs resolves via
config.theme.clone().unwrap_or_default().resolve() so absent and
empty [theme] behave identically. Regression test added.
### docs/reverse-proxies.md
New doc covering nginx, Caddy, Apache, and Traefik with per-proxy
configs and the %2F-decoding gotcha that causes 404s on nested
subfolder paths when a proxy normalises the URI before forwarding.
The issue was surfaced by @mauroparente in #105 — thanks for the
repro and the nginx config that made the root cause obvious.
deployment-guide.md Step 3 and integrations.md HAProxy section
both link to the new doc.
Audio module must be built while system is pure trixie — sid's newer
libglvnd/libsystemd/libxcb break PulseAudio build dependencies.
Single script now does: desktop + build tools + audio → sid xrdp rebuild → remove sid → configure.
Audio:
- RDP audio output now works through guacamole. Advertise audio/L16
and audio/L8 mimetypes in the guacd handshake, and explicitly set
disable-audio=false. Fixed mimetype mismatch that silently prevented
guacd from creating audio streams.
- Browser AudioContext auto-resumed on user interaction (click/keydown)
to comply with autoplay policy.
Video performance:
- Per-entry GFX pipeline toggle (enable_gfx) — enables RemoteFX codec
- Per-entry desktop composition toggle (enable_desktop_composition)
- Per-entry force lossless toggle (force_lossless) — PNG-only mode
- WebSocket proxy buffer increased from 8KB to 64KB
- Video Performance section in address book UI for RDP entries
Documentation:
- RDP Video Performance guide with Windows server tuning (AVC444,
60fps, GPU encoding) and Linux xrdp setup (Debian 13)
- contrib/setup-xrdp-gfx.sh — automated GFX/H.264 setup for xrdp
- contrib/setup-xrdp-audio.sh — automated PulseAudio module build