Skip to main content

Overview

Apache Guacamole is a clientless remote desktop gateway: users open RDP, VNC, SSH, and telnet sessions to internal machines in a plain browser tab, with no client, plugin, or VPN to install. This template deploys the Guacamole web application together with the guacd protocol daemon in one workload, backed by a bundled PostgreSQL that holds users, connections, permissions, and session history. The gateway runs as a single replica and is private by default — you reach the UI over a port forward and opt in to publishing it. The administrator login is not a template value. It comes from a dictionary secret you create before installing, so it never passes through Helm and never lands in the release.
This template deploys into an existing GVC that you already have — it does not create or manage a GVC.

What Gets Created

Your admin secret is not created by the template — see Prerequisites.
guacd listens on port 4822 and that port is deliberately not published. The protocol daemon is unauthenticated — anything that can reach it can drive an arbitrary RDP, VNC, or SSH session — so only the web application running beside it in the same workload can reach it. Do not “fix” this by declaring the port.

Prerequisites

One secret must exist before you install. It holds the Guacamole administrator login. The values never pass through Helm, so they do not land in the release. Secrets are org-level, so no GVC flag is involved.
1

Create the admin secret

A dictionary secret holding exactly two keys — username and password. They become the Guacamole administrator account, replacing the well-known stock guacadmin account before the web application ever serves a request:
Set admin.secretName to this name.
2

Read the secret back later

Pass -o yaml. A bare cpln secret reveal prints only a summary table, not the values:
Create the secret before installing, or the deployment wedges silently. The template refuses to render when admin.secretName is blank, but a name that points at a secret which does not exist installs “successfully” and then never starts. No container runs, so cpln logs returns zero lines. The one place the reason appears is status.versions[].message:
Use get-deployments — plain cpln workload get has no versions key. Creating the missing secret lets the deployment recover on its own; cpln workload force-redeployment RELEASE_NAME-guacamole --gvc GVC_NAME skips the wait.
The administrator credentials are applied on first boot only. They seed the database once. Rotating the secret afterwards does not change your login — change the password in the Guacamole UI instead (see First Run).
Nothing else is required for a default install: the bundled database password is internal plumbing that this template turns into a secret for you. Scheduled database backups need a bucket and, for AWS or GCP, a Control Plane cloud account — see Backing Up.

Installation

Once your admin secret exists, install from the marketplace registry, pointing admin.secretName at it and replacing the bundled database password:
Installing a second Guacamole release in the same org? Also set postgres.config.credentialsSecretName to a name no other release uses — secret names are org-wide. Other ways to install and manage the template:

UI

Browse, install, and manage templates visually

CLI

Manage templates from your terminal

Terraform

Declare templates in your Terraform configurations

Pulumi

Declare templates in your Pulumi programs

Configuration

Guacamole Web Application

guacd Protocol Daemon

guacd:1.6.0 has RDP, VNC, SSH, and telnet compiled in. The Kubernetes protocol is not included.

Admin Account

admin.secretName is required. The secret is read on first boot only; afterwards, change the password in the Guacamole UI, not in the secret.

Logging

warn is deliberately not an option: guacd spells that level warning while the web application spells it warn, so no single value covers both containers. The chart rejects anything outside the four listed values at render.

Access

A change to either access knob takes a couple of minutes to take effect after the upgrade reports success. These knobs govern inbound traffic to Guacamole. They do not restrict which hosts guacd may dial: a remote desktop gateway needs outbound reach to the machines its connections target, so egress stays open. Control what a user can connect to through the connections and permissions you create inside Guacamole.

Bundled PostgreSQL

The database is the postgres template as a subchart, so every knob of that template is available under postgres.*. The chart builds the credentials secret from postgres.credentials.* for you — nothing to create before installing. postgres.image also sets the image of the schema-init container, so psql always matches the server version.
postgres.credentials.password seeds the database on first boot and is not updated by later value edits. Uninstalling the release deletes the volume set; reinstall to reset.

Connecting

Guacamole is served at /, not at /guacamole/. With the default private install, reach the UI from your machine through a tunnel and open http://localhost:8080:

First Run

A default install is closed to the internet. Sign in through a port forward first, set your own password, add a connection, and publish the UI only if you want it reachable from outside the GVC.
1

Wait for the gateway to report ready

PostgreSQL comes up first, then the schema-init container loads the schema and writes your administrator account, and only then does the web application start serving. Expect the first boot to take a few minutes.
While it waits, the gateway’s logs show guacamole: waiting for the schema and admin account to be applied...; the boot is finished when schema-init: bootstrap complete, idling and guacamole: schema ready, starting Tomcat appear:
2

Sign in over a port forward

cpln port-forward is a top-level command, not a cpln workload subcommand:
Open http://localhost:8080 and sign in with the username and password from your admin secret. The stock guacadmin / guacadmin login is never valid here — the stock account is replaced by yours before the web application starts.
3

Change the administrator password

Open the Guacamole menu (top right) → Settings → Preferences and use Change Password. The password now lives in the database; the secret you created is not consulted again after the first boot, so leaving it unchanged there does not weaken anything.
4

Add a connection

A fresh install has no connections and looks empty until you add one. Go to Settings → Connections → New Connection, choose a protocol (RDP, VNC, SSH, or telnet), and set the target host and port. For a machine running as a workload in the same GVC, use its fully qualified internal name as the hostname — WORKLOAD_NAME.GVC_NAME.cpln.local — with the service’s port (for example 22 for SSH). A bare short name does not reliably resolve. Then grant users access to the connection under Settings → Users.
5

Publish the UI, if you want it public

Upgrade the release with publicAccess.enabled set to true. The canonical *.cpln.app hostname then appears under status.canonicalEndpoint:
Allow a couple of minutes for the change to take effect before concluding it did not work.

Operations

Backing Up

Scheduled backups of the bundled PostgreSQL are off by default. Enabling postgres.backup.enabled: true adds one cron workload, RELEASE_NAME-postgres-backup, that runs pg_dumpall on the schedule and uploads a gzipped dump to your bucket under the configured prefix. The dump covers everything Guacamole persists: users, connections, connection parameters, permissions, and session history. Pick a postgres.backup.provider and complete the matching setup before installing or upgrading with it on.
1

Create a bucket

Create an S3 bucket. Set postgres.backup.aws.bucket and postgres.backup.aws.region to match.
2

Set up a cloud account

If you do not have one, create a cloud account for the AWS account holding the bucket. Set postgres.backup.aws.cloudAccountName to its name.
3

Create a bucket-scoped IAM policy

Create an IAM policy with the JSON below (replace YOUR_BUCKET_NAME) and set postgres.backup.aws.policyName to its name. The template attaches it to the PostgreSQL identity and nothing else — the bucket in your policy is the only storage the backup job can reach:
postgres.backup.image must match the PostgreSQL major version in postgres.image. If you move off the defaults, change both together. The full per-provider walkthrough lives on the postgres template page.
The database dump does not include your admin secret, which lives in the secret you created. The PostgreSQL volume set RELEASE_NAME-pg-vs takes no scheduled snapshots; a final snapshot is taken when the volume set is deleted and kept 7 days.

Restoring a Backup

Each backup is a gzipped plain-SQL pg_dumpall archive. Restoring means replaying that SQL into the bundled PostgreSQL. The one transport that carries a dump into the container intact is cpln workload exec with --stdin and a base64 wrapper on both ends — raw binary piped through exec is corrupted:
Two constraints make this a planned operation: the archive contains CREATE ROLE and CREATE DATABASE statements, so a straight replay collides with the guacamole database the schema-init container already created on first boot; and no user should be signed in while you drop and recreate that database before the replay — every session is cut when its rows disappear.
This restore path has not been exercised against this template end to end. Rehearse it on a throwaway release before you depend on it. Restoring from a volume set snapshot is likewise unverified here.

Scaling and Availability

This template runs exactly one replica, and there is no replicas knob. Guacamole keeps authentication tokens in each web application’s memory with no cross-instance sharing, so a second replica would randomly sign users out. Any restart — an upgrade, a replica reschedule, or a forced redeployment — therefore drops active desktop sessions and signs everyone out. Reconnecting re-establishes the session. Nothing persisted is lost: users, connections, permissions, and history all live in PostgreSQL on the RELEASE_NAME-pg-vs volume set, which survives restarts, redeploys, and upgrades under the same release name.
The first helm upgrade after an install can restart the bundled PostgreSQL even when its values are unchanged, so expect a brief interruption.
Rotating a secret the workload references does not restart it; the old value stays in force until you run cpln workload force-redeployment RELEASE_NAME-guacamole --gvc GVC_NAME. For the admin credentials specifically, even a redeployment does not change your login — those are applied on first boot only.

Troubleshooting

Symptom: cpln helm install reported success, cpln logs returns nothing, and cpln workload get-deployments RELEASE_NAME-guacamole --gvc GVC_NAME -o yaml shows The secret ADMIN_SECRET_NAME no longer exists. Workload updates are paused until the secret is added or the reference to the secret removed. under status.versions[].message.Cause: The prerequisite admin secret named by admin.secretName does not exist.Fix: Create it (see Prerequisites). The deployment recovers on its own once the secret exists; cpln workload force-redeployment RELEASE_NAME-guacamole --gvc GVC_NAME skips the wait.
Symptom: The workload is not ready and its logs repeat guacamole: waiting for the schema and admin account to be applied... without ever reaching schema-init: bootstrap complete, idling.Cause: The schema-init container is almost always still waiting on PostgreSQL — its own log line reads schema-init: waiting for postgres at RELEASE_NAME-postgres.GVC_NAME.cpln.local:5432 ....Fix: Check that RELEASE_NAME-postgres is ready with cpln workload get-deployments RELEASE_NAME-postgres --gvc GVC_NAME -o yaml, then follow the bootstrap with a server-side filter:
Symptom: Installing a second Guacamole release fails with cannot be updated because it is being managed by a different release and creates nothing.Cause: Both releases use the same postgres.config.credentialsSecretName. Secret names are org-wide, and the first release owns that one. Nothing is shared, overwritten, or deleted.Fix: Set postgres.config.credentialsSecretName to a distinct name for the second release and install again.
Symptom: You changed username or password in the admin secret (and even forced a redeployment), yet the original credentials still sign in and the new ones are rejected.Cause: The admin credentials seed the database on first boot only. Once the schema exists the schema-init container logs schema-init: guacamole schema already present, skipping bootstrap and leaves the account alone — otherwise every restart would overwrite a password changed in the UI.Fix: Change the password in the Guacamole UI under Settings → Preferences, or as an administrator under Settings → Users.
Symptom: Guacamole’s documented stock login returns an invalid-credentials error.Cause: Expected. The stock account is renamed and re-hashed to the username and password in your admin secret before the web application starts serving.Fix: Sign in with the values from cpln secret reveal ADMIN_SECRET_NAME -o yaml.
Symptom: guacamole: logLevel must be 'trace', 'debug', 'info' or 'error', got 'warn'.Cause: warn is excluded because guacd spells that level warning and the web application spells it warn, so no single value covers both containers.Fix: Use info or error.
Symptom: After a helm upgrade, a forced redeployment, or a replica reschedule, every user is back at the login page and open desktop sessions ended.Cause: Expected. Guacamole holds authentication tokens in the web application’s memory, and the template runs one replica — see Scaling and Availability.Fix: Sign in again and reconnect. Users, connections, and history are intact in PostgreSQL.
Symptom: Opening a connection fails with a hostname-resolution error from guacd.Cause: The connection’s hostname is a bare workload name. Short names do not reliably resolve.Fix: Edit the connection and set the hostname to the fully qualified form WORKLOAD_NAME.GVC_NAME.cpln.local.

Important Notes

  • Create the admin secret before installing — admin.secretName must name an existing dictionary secret with username and password. A missing secret wedges the deployment silently; see Prerequisites for the one command that shows the reason.
  • The admin credentials are first-boot only. Rotating the secret afterwards does not change your login. Change the password in the Guacamole UI instead.
  • guacadmin / guacadmin is never valid here — the stock account is replaced by yours before the web application starts.
  • Rotating any referenced secret does not restart the workload. The old value stays in force until you run cpln workload force-redeployment RELEASE_NAME-guacamole --gvc GVC_NAME.
  • Single replica by design, with no replicas knob. Any restart drops active desktop sessions and signs everyone out; see Scaling and Availability.
  • Public access is off by default. Reach the UI over cpln port-forward until you deliberately publish it. Access changes take a couple of minutes to take effect.
  • guacd’s port 4822 is intentionally unpublished because the protocol daemon is unauthenticated. Only the web application in the same workload can reach it.
  • Only RDP, VNC, SSH, and telnet are available in guacd:1.6.0. The Kubernetes protocol is not compiled in.
  • Use fully qualified internal names — WORKLOAD_NAME.GVC_NAME.cpln.local — both for reaching Guacamole from other workloads and for the connection targets you configure in it.
  • Keep guacamole.image and guacd.image on the same tag — the web application and the protocol daemon are versioned together upstream.
  • Change postgres.credentials.password before installing and give each release its own postgres.config.credentialsSecretName — secret names are org-wide, and a second release on the same name is refused at install.
  • Uninstalling deletes the volume set and every user, connection, and history row in it; your admin secret is yours and survives.

External References

Guacamole Manual

The official Apache Guacamole administrator and user guide

Administration

Managing users, connections, groups, and permissions

Configuring Guacamole

Connection parameters for RDP, VNC, SSH, and telnet

PostgreSQL Authentication

How Guacamole stores users and connections in PostgreSQL

Guacamole Template

View the source files, default values, and chart definition