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 — there is no database or secret to prepare before installing. 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.What Gets Created
Prerequisites
None for a default install. The bundled database’s credentials secret is created by the chart from your values, so there is nothing to create beforehand. Backups are optional and need a bucket plus a Control Plane cloud account — see Backing Up.Installation
Install the chart from the marketplace registry, choosing the bundled database password — it is used exactly as given and is baked into the database the first time it starts:--set postgres.config.credentialsSecretName= to a name of your own; see Configuration.
Or follow the instructions for your preferred method:
UI
CLI
Terraform
Pulumi
Configuration
Each block below is the shipped default for that part ofvalues.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 owncpu 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/0or the provider’s address ranges.firewall.internal.type— which workloads in your org can reach port9011directly:
Bundled PostgreSQL
The database is the PostgreSQL template deployed as a dependency. Unlike a standalone PostgreSQL install, this chart creates the credentials secret for you from the three values underpostgres.credentials and hands the database its name, so the keys below are values rather than a secret you create.
postgres.credentials.*— applied only when the volume is first initialized. Changing them afterwards changes the secret but not the database; see Rotating the Database Password.usernameanddatabaseship asusernameandtestand are deliberately left alone across upgrades because an existing data directory was initialized with them;databasealso forms the JDBC URL FusionAuth connects with.postgres.config.credentialsSecretName— the name of the dictionary secret the chart creates. Secret names are org-wide, so a second FusionAuth release left on the default is refused at install (the secret is owned by the first release) and creates nothing — the first release is untouched.postgres.internalAccess.type— which workloads can reach port5432. The defaultsame-gvcis what the FusionAuth workload needs;nonewould cut it off from its own database.postgres.resources— on a stateful workloadmaxCpumay not exceed four timesminCpu; raising one without the other is rejected when the workload is applied.
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 runspg_dumpall on the schedule and uploads a gzip-compressed SQL dump of the database to your bucket, authenticating with the username and password the chart wrote into the 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
/api/status answers 200 without an API key once the node is serving:
/.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.Create the administrator
Set the tenant issuer
iss claim in every token FusionAuth signs, so set it before applications start validating tokens, and configure those applications to expect the same value.Register your application
Create an API key
Add external identity providers (optional)
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 withpostgres.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.
AWS S3
-
Create an S3 bucket. Set
postgres.backup.aws.bucketto its name andpostgres.backup.aws.regionto its region. -
If you do not have one yet, create a Control Plane cloud account for the AWS account holding the bucket. Set
postgres.backup.aws.cloudAccountNameto its name. -
Create an IAM policy scoped to exactly that bucket, replacing
YOUR_BUCKET_NAME:
- Set
postgres.backup.aws.policyNameto 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
-
Create a GCS bucket. Set
postgres.backup.gcp.bucketto its name. -
Create a Control Plane cloud account for the GCP project holding the bucket, and set
postgres.backup.gcp.cloudAccountNameto its name. -
Grant the cloud account’s service account the Storage Admin (
roles/storage.admin) role. The template additionally binds the identity toroles/storage.objectAdminon exactly the bucket inpostgres.backup.gcp.bucket.
Restoring a Backup
Each backup is a gzip-compressedpg_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:
Stop FusionAuth from holding connections and drop the database
FORCE (PostgreSQL 13 and later), substituting the database value from your credentials secret:Stream the dump into the server
- AWS S3
- GCS
already exists error for the role the server created at first boot is expected; the rest of the script loads normally.Redeploy FusionAuth
Rotating the Database Password
The database readspostgres.credentials.password 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, change the value so the chart rewrites the secret, then restart FusionAuth.
Change the password inside PostgreSQL
cpln port-forward RELEASE_NAME-postgres 5432:5432 --gvc GVC_NAME), connect with the current password and run:Upgrade the release with the new value
postgres.credentials.password to the new password in your values and run cpln helm upgrade with your usual arguments. The chart rewrites the credentials secret; nothing else changes.Restart FusionAuth so it picks the new value up
Upgrading From 2.3.x
The bundled PostgreSQL moved to thepostgres 3.4.1 template, which no longer takes database credentials as values. This template absorbed that change rather than passing it on — there is no new prerequisite, only a rename:
Upgrading From 2.4.0
One thing changed: the defaultpostgres.credentials.password is change-me-fusionauth-db instead of password. The database initialized its data directory with whatever password was in force at first boot, and a new default does not change it, so:
- If you already set your own password, nothing changes — upgrade normally.
- If you never overrode it, your database’s password is literally
password. Do one of these before upgrading, or FusionAuth fails to authenticate after the upgrade:
Keep it working as-is
postgres.credentials.password: password explicitly in your values. The upgrade is then a no-op for the database.Or rotate it properly (recommended)
password was a published default, so treat it as compromised. Follow Rotating the Database Password, using the new password as the value you upgrade with.postgres.credentials.username and postgres.credentials.database are deliberately unchanged for the same reason — they are baked into the initialized data directory, and database also forms the JDBC URL.
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 upgradeafter 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
FusionAuth container appears stuck right after install
FusionAuth container appears stuck right after install
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.Second install is refused: managed by a different release
Second install is refused: managed by a different release
my-fusionauth-db-credentials, and secret names are org-wide. The second install is refused and creates nothing; the first release is untouched.Fix: install the second release with --set postgres.config.credentialsSecretName= set to a name of its own.Upgrade fails telling you to create a dictionary secret
Upgrade fails telling you to create a dictionary secret
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 renamed in 2.4.0.Fix: do not create a secret — this template creates it. Rename the keys as shown in Upgrading From 2.3.x and upgrade again. The running release is unaffected until the upgrade succeeds.FusionAuth cannot authenticate to the database after upgrading to 2.4.1
FusionAuth cannot authenticate to the database after upgrading to 2.4.1
postgres.credentials.password, so the database was initialized with the old default password while the new chart wrote change-me-fusionauth-db into the secret.Fix: follow Upgrading From 2.4.0 — either pin the old value explicitly or rotate the password inside PostgreSQL first.Tokens are rejected because the issuer does not match
Tokens are rejected because the issuer does not match
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/0by default and there is no administrator until the wizard is finished — whoever gets there first creates that account. - Change
postgres.credentials.passwordbefore the first install. It is used exactly as given and applied only when the volume is first initialized; afterwards rotate withALTER ROLEas in Rotating the Database Password. - Give each release its own
postgres.config.credentialsSecretName. Secret names are org-wide; a second release left on the default is refused at install. - Egress is closed by default. External identity providers, outbound email and internet webhooks need
firewall.external.outboundAllowCIDRopened. - Set the tenant issuer before applications validate tokens — it is the
issclaim in every token, and changing it later invalidates the expectation in every client. cpln helm uninstalldeletes 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.0 needs a values change — see Upgrading From 2.3.x and Upgrading From 2.4.0.
firewall.external.outboundAllowCIDRis empty by default, so FusionAuth has no internet egress.Fix: setfirewall.external.outboundAllowCIDRto0.0.0.0/0or the provider’s address ranges and upgrade. Allow a few minutes for the change to take effect.