Add Apache Guacamole — a clientless remote-desktop gateway that brokers RDP / VNC / SSH / telnet / Kubernetes to remote targets, rendered in the browser. This is the recommended bastion / jump-box app, and unlike the full Kasm Workspaces platform (see #32) it slots into Hola's model cleanly with no server changes.
Components (3 plain containers — no privilege, no Docker socket, no host ports)
guacamole/guacamole — the Tomcat web app (ingress, HTTP on 8080)
guacamole/guacd — the proxy daemon that speaks the target protocols (internal, 4822)
- a database:
postgres (recommended) or mariadb — stores users, connections, permissions, history
Hola packaging notes
- Pinned images for all three;
expose only (guacd/db internal). Data under ${HOLA_APP_DATA} (the DB volume).
- Ingress: the web app on
8080. The router emits http://… and Traefik terminates real TLS, so the browser gets HTTPS at https://<app>.<base> — good fit today.
- Set
WEBAPP_CONTEXT=ROOT so it serves at the subdomain root (default context is /guacamole).
- Wire the web app to the others via env:
GUACD_HOSTNAME/GUACD_PORT and POSTGRES_HOSTNAME/POSTGRES_DATABASE/POSTGRES_USER/POSTGRES_PASSWORD.
- Websockets carry the session tunnel — confirm Traefik passes them (it does).
- DB schema must be seeded once. Guacamole ships the schema via
/opt/guacamole/bin/initdb.sh --postgresql. In a single-stack app, either bake the generated SQL into the bundle and mount it into the DB's /docker-entrypoint-initdb.d, or run a one-shot init container before the web app starts. (Packaging decision below.)
Auth
Two good options against Authentik — both keep connection definitions in the DB:
native-oidc via the OpenID extension (OPENID_AUTHORIZATION_ENDPOINT, OPENID_JWKS_ENDPOINT, OPENID_ISSUER, OPENID_CLIENT_ID, OPENID_REDIRECT_URI, OPENID_USERNAME_CLAIM_TYPE, OPENID_GROUPS_CLAIM_TYPE). OIDC handles identity; the DB stores connections/permissions (the two layer).
forward-auth via the header extension (guacamole-auth-header, trusting e.g. X-authentik-username). Simplest to wire with the Authentik outpost.
- Recommend native-oidc; map
hola-admins to Guacamole admins and keep the local guacadmin as break-glass.
Security
It's a bastion into internal RDP/SSH/VNC — treat it as sensitive. Gate behind SSO, restrict to admins where possible, and call this out in the README. (MFA can be left to Authentik at the gate rather than Guacamole's TOTP extension.)
Open questions
postgres vs mariadb (leaning postgres).
- Schema seeding: baked SQL in the DB init dir vs a one-shot init container — pick the cleaner one for the bundle.
native-oidc (OpenID ext) vs forward-auth (header ext) as the shipped default.
How to add it (see repo README)
./bin/create-package.sh guacamole → edit src/guacamole/src/{compose.yaml,manifest.json} (ingress guacamole:8080, WEBAPP_CONTEXT=ROOT, auth mode).
- Add
icons/guacamole.svg.
./bin/push-oci-package.sh guacamole then ./bin/build-catalog.sh.
Acceptance
- Installs, healthy at
https://guacamole.<base> (served at root), SSO login via Authentik works, a test RDP/VNC/SSH connection to an internal host renders in the browser over websockets, and connections/history persist across a restart.
Related: the Kasm/KasmVNC streamed-desktop issue (#32) — Guacamole is the gateway to existing hosts, KasmVNC is a streamed workstation; they're complementary.
🤖 Generated with Claude Code
Add Apache Guacamole — a clientless remote-desktop gateway that brokers RDP / VNC / SSH / telnet / Kubernetes to remote targets, rendered in the browser. This is the recommended bastion / jump-box app, and unlike the full Kasm Workspaces platform (see #32) it slots into Hola's model cleanly with no server changes.
Components (3 plain containers — no privilege, no Docker socket, no host ports)
guacamole/guacamole— the Tomcat web app (ingress, HTTP on8080)guacamole/guacd— the proxy daemon that speaks the target protocols (internal,4822)postgres(recommended) ormariadb— stores users, connections, permissions, historyHola packaging notes
exposeonly (guacd/db internal). Data under${HOLA_APP_DATA}(the DB volume).8080. The router emitshttp://…and Traefik terminates real TLS, so the browser gets HTTPS athttps://<app>.<base>— good fit today.WEBAPP_CONTEXT=ROOTso it serves at the subdomain root (default context is/guacamole).GUACD_HOSTNAME/GUACD_PORTandPOSTGRES_HOSTNAME/POSTGRES_DATABASE/POSTGRES_USER/POSTGRES_PASSWORD./opt/guacamole/bin/initdb.sh --postgresql. In a single-stack app, either bake the generated SQL into the bundle and mount it into the DB's/docker-entrypoint-initdb.d, or run a one-shot init container before the web app starts. (Packaging decision below.)Auth
Two good options against Authentik — both keep connection definitions in the DB:
native-oidcvia the OpenID extension (OPENID_AUTHORIZATION_ENDPOINT,OPENID_JWKS_ENDPOINT,OPENID_ISSUER,OPENID_CLIENT_ID,OPENID_REDIRECT_URI,OPENID_USERNAME_CLAIM_TYPE,OPENID_GROUPS_CLAIM_TYPE). OIDC handles identity; the DB stores connections/permissions (the two layer).forward-authvia the header extension (guacamole-auth-header, trusting e.g.X-authentik-username). Simplest to wire with the Authentik outpost.hola-adminsto Guacamole admins and keep the localguacadminas break-glass.Security
It's a bastion into internal RDP/SSH/VNC — treat it as sensitive. Gate behind SSO, restrict to admins where possible, and call this out in the README. (MFA can be left to Authentik at the gate rather than Guacamole's TOTP extension.)
Open questions
postgresvsmariadb(leaning postgres).native-oidc(OpenID ext) vsforward-auth(header ext) as the shipped default.How to add it (see repo README)
./bin/create-package.sh guacamole→ editsrc/guacamole/src/{compose.yaml,manifest.json}(ingressguacamole:8080,WEBAPP_CONTEXT=ROOT, auth mode).icons/guacamole.svg../bin/push-oci-package.sh guacamolethen./bin/build-catalog.sh.Acceptance
https://guacamole.<base>(served at root), SSO login via Authentik works, a test RDP/VNC/SSH connection to an internal host renders in the browser over websockets, and connections/history persist across a restart.Related: the Kasm/KasmVNC streamed-desktop issue (#32) — Guacamole is the gateway to existing hosts, KasmVNC is a streamed workstation; they're complementary.
🤖 Generated with Claude Code