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, the guacd protocol daemon, and a bundled PostgreSQL that holds users, connections, permissions, and session history. The install is private by default: publicAccess.enabled is false, because this gateway fronts your internal machines. You reach the UI over a port forward, sign in, and then opt in to publishing it — see First Run. 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.

Architecture

  • Gateway workload — One standard workload running three containers and mounting no volume set. It is pinned to a single replica by design; see Sessions and Restarts.
    • guacamole — Tomcat serving the web UI, the REST API, and the browser tunnel on HTTP port 8080. It is served at /, not /guacamole/, and honors the forwarded client address so connection history records the real client IP rather than the mesh proxy.
    • guacd — The protocol daemon that speaks RDP, VNC, SSH, and telnet on the wire, reached by the web application over loopback 127.0.0.1:4822.
    • schema-init — Loads the database schema and writes the administrator account on first boot, then idles. Tomcat does not start serving until it has finished.
  • PostgreSQL — The postgres template as a subchart, running PostgreSQL 18. It holds every byte Guacamole persists: users, connections, connection parameters, permissions, and session history.

What Gets Created

  • Standard Guacamole Workload — (RELEASE_NAME-guacamole): the three containers above, on port 8080, fixed at one replica.
  • Stateful PostgreSQL Workload — Single-replica PostgreSQL, automatically connected to Guacamole.
  • Volume Set — The PostgreSQL data volume. The gateway workload itself has no volume set.
  • Database Credentials Secret — A dictionary secret named by postgres.config.credentialsSecretName, which this template creates from postgres.credentials.* and hands to the bundled database. There is nothing for you to create here.
  • Script Secrets — (RELEASE_NAME-guacamole-start and RELEASE_NAME-guacamole-init): two opaque secrets holding the shell scripts the containers run. Neither contains a credential.
  • Identity & Policy — An identity for the gateway workload with reveal scoped to exactly four secrets: your admin secret, the database credentials secret, and the two script secrets. No cloud bindings are attached. The PostgreSQL subchart brings its own identity and policy.
This template does not create a GVC. You must deploy it into an existing GVC.
guacd’s port 4822 is deliberately not published. The protocol daemon is unauthenticated — anything that can reach it can drive an arbitrary RDP, VNC, or SSH session. Containers in one workload share a network namespace, so the web application reaches it on loopback while nothing outside the replica can. Do not “fix” this by declaring the port.

Prerequisites

One secret must exist before you install. Its values never pass through Helm, so they never 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 Tomcat ever serves a request.
Set admin.secretName to the name you used. Nothing else is required for a default install — the database password is internal plumbing that this template turns into a secret for you.
2

Read the secret back later

The -o yaml is required — plain cpln secret reveal prints only a summary table, not the values:
Create the secret before installing. The template refuses to render when the name is blank, but a name pointing at a secret that does not exist installs “successfully” and then wedges: every resource reports created, the workload never becomes ready, and cpln logs returns zero lines because no container ever starts. The only diagnostic is status.versions[].message:
It names the missing secret: The secret <name> no longer exists. Workload updates are paused until the secret is added or the reference to the secret removed. The command is get-deployments — plain cpln workload get has no versions key at all. Creating the secret recovers the workload on its own: poll for 5.5 to 10.5 minutes rather than time-boxing it (9 minutes 46 seconds measured here). cpln workload force-redeployment RELEASE_NAME-guacamole --gvc GVC_NAME skips the wait.
The administrator password is applied on first boot only. It seeds the database once, so rotating the secret afterwards does not change your login — this was verified by rotating the secret, forcing a redeployment into a container proven to hold the new value, and confirming the original password still authenticated. Change the password in the Guacamole UI instead. That behavior is deliberate: otherwise every restart would silently overwrite a password changed in the UI.

Installation

To install, follow the instructions for your preferred method:

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

First Run

A default install is closed to the internet: the canonical endpoint returns 403. Sign in through a port forward first, add a connection, and publish the UI only if you want it reachable from outside the GVC.
1

Wait for the workload to report ready

PostgreSQL comes up first, then the schema-init container loads the schema and writes your administrator account, and only then does Tomcat start serving. A default install typically reaches ready in about a minute and a half.
If the workload sits waiting for the schema, read the schema-init container’s logs first — it is almost always still waiting on PostgreSQL.
2

Reach the UI over a port forward

cpln port-forward is a top-level command, not a cpln workload subcommand. It tunnels through Control Plane infrastructure and is independent of the firewall settings:
Then open http://localhost:8080 and sign in with the username and password from your admin secret. Guacamole is served at /, not at /guacamole/.
3

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, and set the target host and port. For a machine in the same GVC, use the fully qualified internal name — WORKLOAD_NAME.GVC_NAME.cpln.local — because a bare short name does not reliably resolve.
4

Publish the UI, if you want it public

Upgrade the release with publicAccess.enabled: true. The canonical *.cpln.app hostname then appears under status.canonicalEndpoint:
Allow up to a few minutes for the firewall change to take effect before concluding it did not work.
guacadmin / guacadmin, Guacamole’s well-known stock account, is never valid here. The stock row is renamed and re-hashed to your credentials before Tomcat binds a port, so it is not left behind alongside your account.

Supported Protocols

The guacd:1.6.0 image has RDP, VNC, SSH, and telnet compiled in. The Kubernetes protocol is not included. Each connection you create names a protocol plus a target host and port, and guacd dials that host from inside the GVC — so the gateway reaches private machines that are not exposed to the internet, and every session is written to Guacamole’s connection history with who connected, to what, and when.

Configuration

The default values.yaml for this template:

Images and Resources

  • guacamole.image / guacd.image — The two official images. Keep the tags equal: the web application and the protocol daemon are versioned together upstream.
  • guacamole.resources — CPU and memory bounds for Tomcat. The JVM sizes its heap at roughly a quarter of maxMemory, so raise maxMemory to give the heap more room.
  • guacd.resources — CPU and memory bounds for the protocol daemon. Raise maxMemory for many concurrent RDP sessions; each active session costs memory here rather than in Tomcat.
  • postgres.image — Also sets the image of the schema-init container, so psql always matches the server version. One value drives both.

Admin Account

admin.secretName names the dictionary secret holding username and password. It is required and must exist before you install — see Prerequisites for the command and the failure mode. The credentials are applied on first boot only; change the password in the Guacamole UI afterwards, not in the secret.

Logging

logLevel sets verbosity for both containers from one value: trace, debug, info (default), or error. The chart rejects anything else at render.
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. Use error or info.

Access

  • publicAccess.enabled — Serve the UI on the auto-assigned *.cpln.app HTTPS endpoint. It is false by default, because this gateway fronts your internal machines: with it off, external requests are refused at the edge with a 403, and you reach the UI over a port forward. Turning it on was measured at 25 seconds to take effect.
  • internalAccess.type — Controls which workloads in Control Plane can reach Guacamole over the internal network:
Firewall changes are not instantaneous. After an upgrade that flips publicAccess.enabled or internalAccess.type reports success, requests can keep hitting the old rules for anywhere from half a minute to a few minutes. Re-test after a pause rather than concluding the knob did not work.
This firewall governs inbound traffic to Guacamole. It does not restrict which hosts guacd may dial out to: 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.

Backing Database

The bundled PostgreSQL is the postgres template as a subchart, and every one of its knobs is available under the postgres key. postgres.credentials.* are internal plumbing — no human types this password anywhere — so this template builds the credentials secret from them rather than asking you to create it. Change postgres.credentials.password before installing: it seeds the database on first boot and cannot be changed by editing values afterwards.
Give each release its own postgres.config.credentialsSecretName. Secret names are organization-wide, so a second release left on the default name is refused at install with cannot be updated because it is being managed by a different release. Nothing is shared, overwritten, or deleted — the first release is unaffected, and the second creates nothing.

Sessions and Restarts

This template runs exactly one replica, and there is no replicas knob. Guacamole keeps authentication tokens in each Tomcat’s memory with no cross-instance sharing, and the platform offers no session affinity, so a second replica would randomly sign users out. The consequence is worth stating precisely, because it is not downtime: So any restart — an upgrade, a replica reschedule, or a forced redeployment — 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.
Rotating a prerequisite secret does not restart this workload. Editing the admin secret was polled for nearly seven minutes with no workload version change, no error, and a healthy ready: true the whole time — the old value simply stayed in force. Run cpln workload force-redeployment RELEASE_NAME-guacamole --gvc GVC_NAME to pick up a rotated secret. For the admin credentials specifically, even a redeployment will not change your login — those are first-boot only.

Connecting

Backing Up

The bundled database is the postgres template, so every backup option that template has is already available here — there is nothing extra to install. Backups are off by default and cover everything Guacamole persists: users, connections, connection parameters, permissions, and session history.
Complete the storage setup for your provider before enabling backups: the bucket, a Control Plane cloud account, and the access grant. The full per-provider walkthrough — including the exact IAM policy JSON, the GCP role, the MinIO credentials secret, and how to restore — lives in the postgres template documentation.
postgres.backup.image must match the PostgreSQL major version in postgres.image. If you move off the defaults, change both together.

Important Notes

  • The admin secret must exist before you install. A missing one wedges the deployment silently with no log output at all; see Prerequisites for the one diagnostic that names it.
  • The admin password is 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 renamed and re-hashed before Tomcat binds a port. If it ever works, that is a bug, not a leftover.
  • Rotating any prerequisite secret does not restart the workload. The old value stays in force, with no error and a healthy status, until you run cpln workload force-redeployment.
  • Single replica by design, and there is no replicas knob. A restart keeps the endpoint up but drops active desktop sessions and signs everyone out. See Sessions and Restarts.
  • Public access is off by default. Expose this gateway deliberately, and reach the UI over cpln port-forward until you do. Firewall changes take from half a minute to a few minutes to take effect.
  • guacd’s port 4822 is intentionally unpublished because the protocol daemon is unauthenticated. Only the web application in the same replica can reach it.
  • Only RDP, VNC, SSH, and telnet are available in guacd:1.6.0. The Kubernetes protocol is not compiled in.
  • Use the fully qualified internal nameWORKLOAD_NAME.GVC_NAME.cpln.local — both for reaching Guacamole and for the connection targets you configure in it.
  • Give each release its own postgres.config.credentialsSecretName, and change postgres.credentials.password before installing. The password seeds the database on first boot and cannot be changed by editing values afterwards.
  • Data survives restarts and upgrades; uninstalling deletes it. Users, connections, and history live in the PostgreSQL volume set, which goes with the release. Your admin secret is yours and survives an uninstall.
  • A fresh install looks empty until you add a connection — that is expected, not a broken deploy. See First Run.

External References

Guacamole Manual

The official Apache Guacamole administrator and user guide

Administration

Managing users, connections, groups, and permissions

Using Guacamole

Connecting, the menu, clipboard, and file transfer

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