Files
rustguac/docs/installation.md
T
Dave Kempe 0d69e8fed4 Rename Address Book → Connections; allowed_groups picker; session privacy (#102)
Three pieces of v1.6.0 work that happened together and are easier to
review as one save point.

Rename: Address Book → Connections
- static/addressbook.html renamed to static/connections.html
- Nav links, page titles, empty states, onboarding, and prose updated
  across all 8 static pages (connections, admin, docs, index,
  recordings, reports, sessions, tokens).
- README, CLAUDE.md, and every file under docs/ updated.
- src/main.rs: connections.html added to the branded-page map and
  route list; /addressbook.html returns a 308 permanent redirect so
  existing bookmarks keep working.
- Backend API paths, Rust types, and Vault storage paths are
  deliberately unchanged — internal only.

Folder allowed_groups picker
- New SQLite table `seen_groups` tracks OIDC groups observed in any
  user login; OIDC callback upserts after extracting groups.
- `GET /api/auth/known-groups` (admin-only) returns the union of
  group_role_mappings and seen_groups.
- `GET /api/addressbook/folders/{scope}/{folder}/config` adds the
  missing endpoint the frontend was already calling — existing
  allowed_groups now prefill the edit-folder modal.
- Folder modal swaps the free-text comma-separated input for a chip
  picker with a themed combobox dropdown: autocomplete over known
  groups, keyboard nav, "+ add custom" row for unlisted groups.

Active session visibility (GitHub #102)
- `GET /api/sessions` scopes to the caller's own sessions by default;
  `?all=true` lets admins opt in (used by the Sessions page).
- `GET /api/sessions/{id}` and the thumbnail GET/PUT endpoints are
  now owner-or-admin, returning 404 for other callers so session
  existence isn't leaked.
- Connections' Active Sessions strip is now always owner-scoped —
  admins still manage everyone via the Sessions page.
2026-04-18 21:56:20 +10:00

8.6 KiB

Installation

Pre-built .deb packages are available from the releases page for Debian 13 (Trixie) and compatible distributions.

sudo apt install ./rustguac_*.deb

Using apt install (not dpkg -i) ensures all runtime dependencies are resolved automatically.

The package installs to /opt/rustguac and creates systemd services for both guacd and rustguac.

Post-install

  1. Create an admin API key:
/opt/rustguac/bin/rustguac --config /opt/rustguac/config.toml add-admin --name admin

Save the printed API key — it is only shown once.

  1. Configure — edit /opt/rustguac/config.toml as needed (see Configuration).

  2. Start the services:

sudo systemctl enable --now rustguac

This starts both rustguac-guacd (the protocol daemon) and rustguac (the web proxy).

  1. (Recommended) Set up the connections with Vault / OpenBao:

The connections is rustguac's primary way to manage connections. It stores SSH, RDP, VNC, and web session entries in HashiCorp Vault or OpenBao KV v2. Credentials are stored server-side and never sent to the browser.

Without Vault, rustguac can still create ad-hoc sessions via the API, but the connections UI (the main user-facing feature) will not be available.

See Vault / OpenBao Connections for full setup instructions, including Vault policy, AppRole configuration, and the [vault] config section.

  1. (Optional) Set up encrypted drive storage:
sudo /opt/rustguac/bin/drive-setup.sh

See Drive / File Transfer for details.

  1. (Optional) Enable VDI desktop containers:

If you want to use VDI sessions (ephemeral Docker desktop containers), install Docker and grant rustguac access:

# Install Docker (if not already installed)
curl -fsSL https://get.docker.com | sh

# Allow rustguac to manage containers
sudo usermod -aG docker rustguac
sudo systemctl restart rustguac

Then add a [vdi] section to your config — see VDI Desktop Containers for full setup.

Option B: Bare-metal install script

For fresh Debian 13 systems, the install script builds everything from source:

sudo ./install.sh

This performs the following steps:

  1. Installs system packages (build tools, Xvnc, Chromium, cryptsetup, etc.)
  2. Installs the Rust toolchain (if not present)
  3. Clones and builds guacd from guacamole-server source, applying patches automatically
  4. Builds rustguac with cargo build --release
  5. Creates the rustguac system user (home: /home/rustguac)
  6. Generates a self-signed TLS certificate
  7. Installs binaries, static files, and config to /opt/rustguac
  8. Sets up systemd services

Install flags

Flag Description
--no-tls Skip TLS certificate generation, listen on HTTP port 8089
--hostname=FQDN Hostname for the TLS certificate (default: system hostname)
--deps-only Only install system packages, then exit
--no-deps Skip apt package installation

Installed layout

/opt/rustguac/
  bin/rustguac           # Main binary
  bin/drive-setup.sh     # LUKS drive setup script
  sbin/guacd             # Guacamole protocol daemon
  lib/                   # guacd shared libraries
  static/                # Web UI files
  tls/                   # TLS certificates
  data/                  # SQLite database
  recordings/            # Session recordings
  config.toml            # Configuration file
  env                    # Environment variables (VAULT_SECRET_ID, etc.)

Systemd services

Service Description
rustguac-guacd guacd protocol daemon (TLS, loopback only)
rustguac rustguac web proxy (depends on guacd)

Both services run as the rustguac user and restart on failure.

The rustguac service loads environment variables from /opt/rustguac/env via systemd's EnvironmentFile directive. Use this for secrets like VAULT_SECRET_ID and OIDC_CLIENT_SECRET.

Option C: Docker

Pre-built images are available on Docker Hub:

docker pull sol1/rustguac:latest
docker run -d -p 8089:8089 sol1/rustguac:latest

To build from source instead:

docker build -t rustguac .
docker run -d -p 8089:8089 rustguac

The Docker image:

  • Uses a multi-stage build (Debian 13 trixie-slim runtime)
  • Builds guacd from source with patches applied
  • Generates a self-signed TLS certificate at build time
  • Enables TLS between rustguac and guacd by default
  • Exposes HTTP on port 8089 (put a reverse proxy in front for HTTPS)

API key setup

On first run (when no database exists), the container automatically generates an admin API key and prints it to the logs:

docker logs rustguac

Save the printed key — it is only shown once. To generate additional keys later:

docker exec rustguac /opt/rustguac/bin/rustguac \
    --config /opt/rustguac/config.toml add-admin --name my-admin

Customizing the configuration

To persist config changes across container restarts, bind-mount a local config.toml into the container:

  1. Copy the default config from the image:
docker run --rm --entrypoint cat sol1/rustguac:latest /opt/rustguac/config.toml.default > config.toml
  1. Edit config.toml as needed (see Configuration):
# Example: allow SSH to private networks
ssh_allowed_networks = ["127.0.0.0/8", "::1/128", "10.0.0.0/8", "172.16.0.0/12", "192.168.0.0/16"]
  1. Mount it in your Docker Compose file or docker run command (see below).

If no config file is mounted, the container uses a built-in default on first start.

Docker Compose example

services:
  rustguac:
    image: sol1/rustguac:latest
    ports:
      - "8089:8089"
    volumes:
      - ./config.toml:/opt/rustguac/config.toml
      - rustguac-data:/opt/rustguac/data
      - rustguac-recordings:/opt/rustguac/recordings
    environment:
      - RUST_LOG=info

volumes:
  rustguac-data:
  rustguac-recordings:

Option D: RPM package (build from source)

Pre-built RPM packages are not currently provided. An RPM spec file (rustguac.spec) and build script (build-rpm.sh) are included for Red Hat / Fedora / Rocky Linux based systems. You will need FreeRDP 3.x development headers installed.

# Install build dependencies (example for Rocky/RHEL 9)
sudo dnf install -y epel-release
sudo dnf config-manager --set-enabled crb
sudo dnf install -y gcc gcc-c++ make git autoconf automake libtool \
    freerdp-devel cairo-devel libjpeg-turbo-devel libpng-devel libwebp-devel \
    libssh2-devel openssl-devel libvncserver-devel pango-devel \
    pulseaudio-libs-devel rpm-build

# Build the RPM
bash build-rpm.sh
sudo rpm -i rustguac-*.rpm

RPM builds are untested — contributions and feedback are welcome.

Option E: Development

# Clone guacamole-server alongside rustguac
git clone https://github.com/apache/guacamole-server.git ../guacamole-server

# Install build deps, build guacd, build + run rustguac
./dev.sh deps
./dev.sh build-guacd
./dev.sh start

For development with TLS:

./dev.sh generate-cert

cat > config.local.toml <<EOF
[tls]
cert_path = "cert.pem"
key_path = "key.pem"
guacd_cert_path = "cert.pem"
EOF

./dev.sh start

System dependencies

For bare-metal installs, rustguac requires:

  • Rust toolchain (1.75+)
  • guacd (built from guacamole-server source)
  • Xvnc (tigervnc-standalone-server) — for web browser sessions
  • Chromium — for web browser sessions
  • cryptsetup — for LUKS encrypted drive storage
  • Build libraries for guacd: libcairo2, libjpeg, libpng, libwebp, libssh2, libssl, libvncserver, libpango, libpulse, ffmpeg, freerdp3

See install.sh for the full package list.

guacamole-server patches

guacd requires patches to build and run correctly with FreeRDP 3.15+ as shipped in Debian 13. These patches are in the patches/ directory and are applied automatically by all build scripts.

The patches fix:

  1. Autoconf -Werror vs deprecated FreeRDP headers — FreeRDP 3.15 deprecates codecs_free(), breaking compile tests
  2. Deprecated function pointer API — replaces ->input->MouseEvent() etc. with safe FreeRDP 3.x functions
  3. NULL pointer dereference — FreeRDP 3.x fires PubSub events before guac_rdp_disp is allocated
  4. Struct layout mismatch — channel source files missing config.h see wrong field offsets when SSH support is enabled