Skip to main content

Overview

FusionAuth is a self-hosted identity and access management platform: a user store with hosted login and registration pages, OAuth2 and OpenID Connect token issuance, SAML, MFA, and federation to external identity providers, managed through a browser admin UI. This template deploys one FusionAuth node together with a bundled PostgreSQL database that it creates, wires up and waits for — the only thing to prepare before installing is the secret holding the database credentials. The FusionAuth workload is publicly reachable by default so that applications can redirect users to it, and it keeps no state of its own: every user, tenant and application lives in the bundled database.
This template deploys into an existing GVC that you already have. It does not create or manage a GVC.

What Gets Created

Prerequisites

One dictionary secret must exist before you install — the database credentials. The bundled PostgreSQL initializes with them and FusionAuth connects with them, and the password never passes through Helm values:
Set postgres.config.credentialsSecretName to that name. Secret names are org-wide, so give each FusionAuth release its own secret.
  • database must be URL-safe (letters, digits, _): FusionAuth’s JDBC URL is assembled from it at container start. The snippet’s hex password is URL-safe too.
  • PostgreSQL reads the secret only when its data directory is first initialized — to change the password later, see Rotating the Database Password.
If the secret does not exist at install time, the deployment wedges silently. cpln logs returns zero lines — the containers never start. The only diagnostic is status.versions[].message (plain cpln workload get has no versions key):
Create the missing secret and the deployment recovers on its own after several minutes, or skip the wait with cpln workload force-redeployment RELEASE_NAME-fusionauth --gvc GVC_NAME.
Backups are optional and need a bucket plus a Control Plane cloud account — see Backing Up.

Installation

Once the database credentials secret exists, install the chart from the marketplace registry with its name set:
Or 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

Configuration

Each block below is the shipped default for that part of values.yaml.

Image and Resources

The image is a Control Plane-published build of FusionAuth 1.60.2 that includes the PostgreSQL client used by the start script. The block exposes only limits, so the names are the platform’s own cpu and memory.

Firewall

  • firewall.external.inboundAllowCIDR — who can reach the login pages and admin UI from the internet. Open to everyone by default; restrict it to your own address range while you complete the setup wizard if you cannot do so immediately after installing.
  • firewall.external.outboundAllowCIDR — egress is closed by default. Any external identity provider (Google, Microsoft, a remote SAML IdP), outbound email and webhooks to internet destinations need this opened — 0.0.0.0/0 or the provider’s address ranges.
  • firewall.internal.type — which workloads in your org can reach port 9011 directly:
A firewall change can take a few minutes to take effect — re-test before concluding it did not apply.

Bundled PostgreSQL

The database is the PostgreSQL template deployed as a dependency. It reads the credentials secret you created under Prerequisites, named by postgres.config.credentialsSecretName.
  • postgres.config.credentialsSecretName — the name of your prerequisite dictionary secret (username, password, database). Its values are applied only when the volume is first initialized; changing the secret afterwards does not change the database — see Rotating the Database Password. database also forms the JDBC URL FusionAuth connects with.
  • postgres.internalAccess.type — which workloads can reach port 5432. The default same-gvc is what the FusionAuth workload needs; none would cut it off from its own database.
  • postgres.resources — on a stateful workload maxCpu may not exceed four times minCpu; raising one without the other is rejected when the workload is applied.
There is no high-availability database option in this template: the dependency is the single-instance postgres template. A node failure reschedules the server and reattaches the same volume, so the exposure is minutes of downtime, not data loss.

PostgreSQL Backup

A cron workload runs pg_dumpall on the schedule and uploads a gzip-compressed SQL dump of the database to your bucket, authenticating with the username and password from your credentials secret. Provider setup steps are under Backing Up.
postgres.backup.image must match the server’s major version: tag 18.1.0 for postgres:18, 17.1.0 for postgres:17. Backups require PostgreSQL 17 or later.

Connecting

Complete the setup wizard immediately after installing. Inbound traffic is open to 0.0.0.0/0 by default and FusionAuth has no administrator until the wizard is finished, so whoever reaches the endpoint first creates that account. If you cannot do it right away, install with firewall.external.inboundAllowCIDR restricted to your own address and widen it afterwards.
Read the public endpoint from the workload, then confirm FusionAuth is up — /api/status answers 200 without an API key once the node is serving:
Give browser-facing applications the public address (authorization and login redirects must be reachable by the user’s browser), and give server-side code inside the GVC the internal address for token exchange and API calls. The OpenID Connect discovery document is at /.well-known/openid-configuration on either host, and at /TENANT_ID/.well-known/openid-configuration once you have more than one tenant.

First Run

Open the public endpoint in a browser; with no users yet, FusionAuth shows its setup wizard instead of a login page.
1

Create the administrator

Fill in the wizard — it creates the first administrator account — and you are signed into the admin UI as that user.
2

Set the tenant issuer

Under Tenants → Default → General, set Issuer to the HTTPS URL users and applications will use — the canonical endpoint, or your custom domain once configured. It is the iss claim in every token FusionAuth signs, so set it before applications start validating tokens, and configure those applications to expect the same value.
3

Register your application

Under Applications, create one per client and fill in its Authorized redirect URLs, Authorized request origin URLs and Logout URL with your application’s addresses. The generated client Id and client secret go into your application’s OAuth2 configuration.
4

Create an API key

Under Settings → API Keys, create a key for server-side calls to the management API. Store it in a Control Plane secret for the workloads that use it; FusionAuth never writes it anywhere.
5

Add external identity providers (optional)

Under Settings → Identity Providers, configure Google, Microsoft, SAML or other federation. These need outbound access — set firewall.external.outboundAllowCIDR first, or every social login silently does nothing.

Operations

Backing Up

Backups are off by default and are provided by the bundled PostgreSQL template’s backup job. Enable them with postgres.backup.enabled: true, pick a postgres.backup.provider, and complete that provider’s setup first. The job writes postgres-TIMESTAMP.sql.gz objects under the configured prefix in your bucket on every run of postgres.backup.schedule. The dump is a pg_dumpall of the whole server — every FusionAuth tenant, application, user and key.
The backup job is the same one the standalone PostgreSQL template ships. It has not been exercised end to end through this template — rehearse a backup and a restore before relying on it.

AWS S3

  1. Create an S3 bucket. Set postgres.backup.aws.bucket to its name and postgres.backup.aws.region to its region.
  2. If you do not have one yet, create a Control Plane cloud account for the AWS account holding the bucket. Set postgres.backup.aws.cloudAccountName to its name.
  3. Create an IAM policy scoped to exactly that bucket, replacing YOUR_BUCKET_NAME:
  1. Set postgres.backup.aws.policyName to that policy’s name. The template attaches it to the database identity and nothing else — the bucket in your policy is the only storage the backup job can reach.

GCS

  1. Create a GCS bucket. Set postgres.backup.gcp.bucket to its name.
  2. Create a Control Plane cloud account for the GCP project holding the bucket, and set postgres.backup.gcp.cloudAccountName to its name.
  3. Grant the cloud account’s service account the Storage Admin (roles/storage.admin) role. The template additionally binds the identity to roles/storage.objectAdmin on exactly the bucket in postgres.backup.gcp.bucket.

Restoring a Backup

This restore path has not been exercised against this template. It follows from what the chart configures (a pg_dumpall dump, restored with psql) and what the backup image contains, but no restore has been run end to end here. Rehearse it on a throwaway release before you need it.
Each backup is a gzip-compressed pg_dumpall script that recreates the roles and databases it contains, so it is restored by connecting to the postgres maintenance database as the username from your credentials secret. Because the script creates the FusionAuth database rather than merging into it, restore into a server where that database does not exist — a fresh install, or one whose database you have dropped. Run the following from a client that can reach both the bucket and the database. The simplest client is your own machine with a tunnel to the database workload open in another terminal, using --host=127.0.0.1:
1

Stop FusionAuth from holding connections and drop the database

FusionAuth keeps a connection pool open, so drop the database with FORCE (PostgreSQL 13 and later), substituting the database value from your credentials secret:
FusionAuth will log database errors until the restore completes and it is redeployed in the last step.
2

Stream the dump into the server

An already exists error for the role the server created at first boot is expected; the rest of the script loads normally.
3

Redeploy FusionAuth

Force a redeployment so FusionAuth reconnects to the restored database with a clean pool:

Rotating the Database Password

The database reads the password from your credentials secret only when its volume is first initialized, and FusionAuth resolves the secret only when a replica starts. So rotate in three moves: change it inside PostgreSQL, update the secret, then right away restart FusionAuth.
1

Change the password inside PostgreSQL

With a tunnel open (cpln port-forward RELEASE_NAME-postgres 5432:5432 --gvc GVC_NAME), connect with the current password and run:
2

Update the secret

Export it, change only password, and apply it:
3

Restart FusionAuth so it picks the new value up

A running replica keeps the password it started with, so force a redeployment right away:
Do not redeploy the database: PostgreSQL reads the secret only when it is first initialized, so restarting it only adds downtime. Connections FusionAuth already has open keep working after ALTER ROLE; new ones fail until its redeploy finishes, so redeploy right away and rotate in a quiet window.

Upgrading From 2.3.x

postgres.config.username, postgres.config.password and postgres.config.database were removed. A values file that still carries an old key fails the render. Put the values your database was initialized with into the database credentials secret under Prerequisites (keys username, password and database), set postgres.config.credentialsSecretName to its name, and remove the three keys.

Upgrading From 2.4.0

postgres.credentials was removed in 2.5.0: the database credentials are now a prerequisite secret, the same one the postgres template requires on its own. Carrying the old key forward fails the render. This applies to upgrades from 2.4.0 and 2.4.1. 2.4.x created the database secret itself, so this upgrade deletes it. Before upgrading, create a secret under a new name holding the values your database was initialized with — not new ones, or FusionAuth loses its database connection:
(username and test were the 2.4.x defaults; use your own values if you overrode them.) Your current values are in postgres.credentials of the installed release, and also in the old secret (cpln secret reveal my-fusionauth-db-credentials -o yaml, or the name your release set in credentialsSecretName) until the upgrade deletes it. If you installed 2.4.0 and never overrode the password, it is literally password — put that in the new secret, and rotate it afterwards as described in Rotating the Database Password. Then upgrade with postgres.config.credentialsSecretName set to the new name and postgres.credentials removed. The upgrade restarts the bundled PostgreSQL too (it now reads the new secret), so FusionAuth can briefly lose its database; it reconnects by itself. The new version of a workload can also wait several minutes with is not allowed to reveal the secret in get-deployments while access to the new secret propagates; the previous version keeps serving meanwhile, and it clears by itself.

Scaling and Availability

  • The FusionAuth tier is a serverless workload that autoscales on request concurrency between one and three replicas; this is fixed in the template, not a value. Running more than one FusionAuth node has not been verified with this template; FusionAuth’s own multi-node guidance expects every node to share the same database and matching configuration, so treat the single-node shape as the supported one.
  • The database is a single instance — there is no high-availability option in this template. A node failure reschedules it onto the same volume: minutes of downtime, no data loss.
  • The first cpln helm upgrade after an install can restart the bundled database, and FusionAuth is unreachable while it comes back. Later upgrades with unchanged values do not.
  • Every upgrade that touches the database restarts it, and FusionAuth with it. Plan upgrades as a short login outage.

Troubleshooting

Symptom: the FusionAuth workload is not ready several minutes after install, and its logs repeat:
Cause: the start script waits for the bundled database by design, for up to five minutes, before launching FusionAuth. On a fresh install the database is still initializing its volume.Fix: usually none — wait for Starting FusionAuth.... If the script instead exits with PostgreSQL did not become ready after 300s. Exiting., the database itself is the problem: check cpln workload get-deployments RELEASE_NAME-postgres --gvc GVC_NAME -o yaml and its logs with cpln logs '{gvc="GVC_NAME", workload="RELEASE_NAME-postgres"}' --limit 50 --since 10m.
Symptom: RELEASE_NAME-fusionauth and RELEASE_NAME-postgres never reach ready, and cpln logs returns zero lines.Cause: the database credentials secret named by postgres.config.credentialsSecretName does not exist. The containers never start, so there is nothing to log.Fix: read status.versions[].message, which names the missing secret, then create it as in Prerequisites. The deployment recovers on its own after several minutes, or force a redeployment to skip the wait.
Symptom: cpln helm upgrade from 2.3.x stops at render with a message from the PostgreSQL template saying that config.username (or config.password, config.database) was removed and that you should create a dictionary secret.Cause: your values still carry postgres.config.username, postgres.config.password or postgres.config.database, which were removed.Fix: create the database credentials secret with the values your database was initialized with, as shown in Upgrading From 2.3.x, and upgrade again. The running release is unaffected until the upgrade succeeds.
Symptom: after the upgrade FusionAuth logs database authentication failures and never becomes ready.Cause: the new credentials secret holds a password other than the one the database was initialized with — for a 2.4.0 install that never overrode it, that password is literally password.Fix: put the password the database was initialized with into the secret, as in Upgrading From 2.4.0, then force a redeployment of RELEASE_NAME-fusionauth.
Symptom: clicking a Google, Microsoft or SAML login button returns to the login page or errors, and outbound requests from FusionAuth never arrive at the provider.Cause: firewall.external.outboundAllowCIDR is empty by default, so FusionAuth has no internet egress.Fix: set firewall.external.outboundAllowCIDR to 0.0.0.0/0 or the provider’s address ranges and upgrade. Allow a few minutes for the change to take effect.
Symptom: an application validating FusionAuth tokens reports an iss mismatch, or an OIDC library refuses the discovery document.Cause: the tenant Issuer (Tenants → Default → General) does not match the URL the application was configured to expect — commonly because it was left at its default rather than set to the public endpoint or custom domain.Fix: set the issuer to the HTTPS URL applications use, as in First Run, and make the application’s expected issuer identical. Tokens issued before the change carry the old value.

Important Notes

  • Complete the setup wizard immediately after installing. Inbound is open to 0.0.0.0/0 by default and there is no administrator until the wizard is finished — whoever gets there first creates that account.
  • Create the database credentials secret before installing. A missing secret leaves the workloads waiting with zero log lines; status.versions[].message from cpln workload get-deployments RELEASE_NAME-fusionauth --gvc GVC_NAME -o yaml names it.
  • Rotating the database password needs ALTER ROLE plus a forced redeployment — PostgreSQL keeps the password it was initialized with, and a running workload keeps the values it started with; see Rotating the Database Password.
  • Egress is closed by default. External identity providers, outbound email and internet webhooks need firewall.external.outboundAllowCIDR opened.
  • Set the tenant issuer before applications validate tokens — it is the iss claim in every token, and changing it later invalidates the expectation in every client.
  • cpln helm uninstall deletes the volume set and with it every tenant, application and user. Take a backup first; the volume set keeps only a final snapshot for seven days.
  • Upgrading from 2.3.x or 2.4.x needs a new secret and a values change — see Upgrading From 2.3.x and Upgrading From 2.4.0.

External References

FusionAuth Documentation

Official FusionAuth documentation

OAuth2 and OpenID Connect

Authorization code flow, endpoints and token handling

Identity Providers

Federating logins to Google, Microsoft, SAML and other providers

Tenants and the Issuer

Tenant configuration, including the issuer used to sign tokens

FusionAuth Template

View the source files, default values, and chart definition