Skip to main content

Overview

n8n is a workflow automation platform (fair-code, distributed under n8n’s Sustainable Use License). This template deploys a single n8n instance serving the editor, REST API, and webhooks on one HTTPS endpoint, backed by a bundled PostgreSQL database — the postgres-highly-available template by default, or the single-instance postgres template for lighter installs. The instance owner account is pre-provisioned from a secret at install, so there is never an unauthenticated setup page. Both the owner login and the credential-encryption key come from secrets you create before installing; neither passes through Helm values.
This template does not create a GVC. It deploys into an existing GVC that you already have.

What Gets Created

The highly available database also creates its own identities, policies, and start-script secrets (RELEASE_NAME-postgres-ha-*, RELEASE_NAME-etcd-*, RELEASE_NAME-patroni-startup, RELEASE_NAME-wal-g-backup-script); the single-instance database creates RELEASE_NAME-pg-identity and RELEASE_NAME-pg-policy.

Prerequisites

Two secrets must exist before you install. Secrets are org-level, so no GVC flag is involved.
1

Create the encryption key secret

An opaque secret with encoding plain whose payload is a long random key. n8n encrypts every credential it stores with it:
Set encryptionKey.secretName to this name. Back the key up outside Control Plane before installing — it can never be rotated. Everything n8n encrypts is bound to it: a changed key makes every stored credential undecryptable and n8n refuses to start on a key mismatch. Read it back any time with:
2

Hash the owner password

n8n accepts only a bcrypt hash for the owner password, never plaintext, so hash it first. htpasswd -B emits the $2y$ form, which n8n accepts:
3

Create the owner secret

A dictionary secret holding exactly the keys email and passwordHash:
Set owner.secretName to this name.
The owner secret is the login, at every restart. n8n re-applies the owner from this secret on every start (N8N_INSTANCE_OWNER_MANAGED_BY_ENV), so whatever hash it holds becomes the password the moment the workload restarts — it is not a one-time bootstrap. The account cannot be changed from inside n8n; to change the password, change the secret (see Rotating the Owner Password).
A missing prerequisite secret wedges the deployment silently. cpln helm install still succeeds, the resources are created, and the n8n workload never starts. cpln logs returns nothing at all, because the container never ran. The only place the reason appears is status.versions[].message, which names the missing secret:
Note this is get-deployments — plain cpln workload get has no versions key. Create the missing secret and the deployment recovers on its own, or force a redeployment to skip the wait:
The bundled database password is not a prerequisite: this template creates the database credentials secret itself from postgres.credentials.*. Change postgres.credentials.password before installing — it is used exactly as written. Optional database backups need a bucket and access setup for one provider, and backups to MinIO need one more dictionary secret — see Backing Up.

Installation

Once both secrets exist, install from the marketplace registry with the two secret names and a database password of your own:
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

n8n Instance

owner.firstName and owner.lastName are the owner’s display name and stay ordinary values; only the email and password hash live in the secret. The n8n image runs as a non-root user, and the chart makes the volume writable for it on first boot — nothing for you to do.

Access

With publicAccess.enabled: false, the editor and webhooks are reachable only from inside the GVC (per internalAccess) or through a port-forward — see Connecting.

Database

Exactly one of the two database modes must be enabled; the chart refuses to render otherwise. postgres.credentials.* feeds both modes — this template builds the database credentials secret from those three values and hands its name to whichever database is enabled, so there is nothing to create before installing. Change the password before you install; it is used exactly as written.
Secret names are org-wide, so if you run more than one n8n release in the same org, give each its own credentialsSecretName. A second release left on the default name is refused at install and creates nothing; the first release is unaffected.

Database Backups

Backups are provided by the bundled database and are off by default. Set the block that matches your database mode and complete the storage setup first — see Backing Up.

Connecting

The editor, REST API, and webhooks are all served on the n8n workload’s canonical endpoint, which is public by default (publicAccess.enabled: true). Read it from status.canonicalEndpoint:
Verify the instance is serving before you sign in:
Webhook URLs match the public address automatically. The canonical hostname is only known once the workload runs, so the chart boots n8n through a start script that reads CPLN_GLOBAL_ENDPOINT and sets N8N_HOST, WEBHOOK_URL, and N8N_EDITOR_BASE_URL to https://CANONICAL_ENDPOINT/. The URLs n8n shows in the editor are therefore the ones external callers use, with no extra configuration. With publicAccess.enabled: false those URLs still point at the canonical endpoint, which external callers cannot reach — in that mode, in-GVC callers use the internal address above, and you reach the editor through a port-forward:
Then open http://localhost:5678. The port-forward path has not been exercised against an n8n install.
Requests to the n8n workload time out after 30 seconds (timeoutSeconds on the workload), so a synchronous webhook response must finish within that window or the caller receives a 504 — the workflow itself still runs to completion. For long-running workflows, set the Webhook node to respond immediately, or add a Respond to Webhook node early, so the caller gets its response while the workflow keeps running.

First Run

There is no setup wizard: the owner account already exists when n8n first starts. Open https://CANONICAL_ENDPOINT and sign in with the email from your owner secret and the password you hashed into passwordHash. The owner’s email and password cannot be changed from inside n8n — the secret is authoritative at every start — so change them through the secret instead (Rotating the Owner Password).

Operations

Backing Up

There are three things worth protecting, and they are protected differently. The encryption key. Without it, a restored database is full of credentials nobody can decrypt. Keep a copy outside Control Plane:
The database holds your workflows, stored credentials (encrypted with the key), and execution history. Scheduled backups are provided by the bundled database — enable postgresHA.backup or postgres.backup to match your database mode (see Database Backups) and complete the storage setup for your provider before installing. The bucket, cloud account, and IAM policy steps are the bundled database’s own, documented on its page: postgres-highly-available Backup Prerequisites for HA mode, postgres Backup Prerequisites for single mode. Set the values under the n8n keys shown above (postgresHA.backup.aws.bucket, not backup.aws.bucket). In HA mode, postgresHA.backup.mode selects logical (scheduled pg_dump from a cron workload) or wal-g (continuous WAL archiving from a sidecar). Single mode takes scheduled logical dumps. Backups to MinIO or another S3-compatible endpoint need one more prerequisite — a dictionary secret holding the keys accessKey and secretKey, created before install and named by postgresHA.backup.minio.credentialsSecretName or postgres.backup.minio.credentialsSecretName:
The n8n volume (RELEASE_NAME-n8n-vs, mounted at /home/node/.n8n) holds instance config and binary execution data. The chart configures a final snapshot when the volume set is deleted, with snapshots retained for 7 days. Take one on demand with:

Restoring a Backup

Restoring the database follows the bundled database’s own procedure, run from a client with access to the backup bucket: postgres-highly-available Restoring a Backup in HA mode (connect through RELEASE_NAME-postgres-ha-proxy.GVC_NAME.cpln.local so the restore targets the current leader), or postgres Restoring a Backup in single mode (host RELEASE_NAME-postgres.GVC_NAME.cpln.local). The username and password are your postgres.credentials.* values. Two n8n-specific points:
  • The restored database only yields usable credentials if the instance runs with the same encryption key the backup was taken under. Create the encryption key secret with the saved key before pointing a new install at restored data.
  • Workflows, credentials, and execution records live in the database; files under /home/node/.n8n (binary execution data) are on the volume set and are not part of a database dump.
These restore paths have not been exercised against an n8n install. Restoring the n8n volume set from a snapshot (cpln volumeset snapshot restore) is likewise unverified for this template — check cpln volumeset snapshot --help and test on a throwaway release before relying on it.

Rotating the Owner Password

Because n8n re-applies the owner from the secret on every start, the owner password is rotated by changing the secret and restarting the workload — not from inside n8n. Hash the new password, apply the whole secret with the new hash, then force a redeployment (a changed secret is only picked up when the replica restarts):
The encryption key has no rotation path: changing ENCRYPTION_KEY_SECRET_NAME’s payload after first boot makes every stored credential undecryptable and n8n refuses to start.

Upgrading From 1.0.x

Version 1.1.0 moved the instance owner out of Helm values. 1.0.0 and 1.0.1 took owner.email and owner.password as values, used exactly as written, guarding a login form that is public by default.
This upgrade can change the password you log in with. n8n re-applies the owner from the secret at every start, so the hash you put in the secret becomes the login the moment the workload restarts. Hash the password you are using today, not a new one — unless changing it is what you intend.
A helm upgrade that still carries either removed key is refused at render, before anything is applied, and the error names the replacement:
1

Create the owner secret

Follow Prerequisites, hashing the password you log in with today.
2

Drop the removed keys from your values

Remove owner.email and owner.password and set owner.secretName. Leave encryptionKey.secretName, owner.firstName, and owner.lastName as they are.
3

Continue with the later sections

Then apply Upgrading From 1.1.0 and Upgrading From 1.2.0 or 1.3.0 as they apply to your database mode, and upgrade once.

Upgrading From 1.1.0

Version 1.2.0 changed how the single-instance database (postgres.enabled: true) gets its credentials. postgres.config.username, postgres.config.password, and postgres.config.database were removed; the same three values now live under postgres.credentials.*, and this template creates the credentials secret named by the new postgres.config.credentialsSecretName. Carrying the old keys fails at render with the bundled database’s own message:
Move the three values from postgres.config.* to postgres.credentials.*, keeping them identical to what the running database was initialised with, and ignore the message’s advice to create a secret — this template creates it. postgres.backup.minio.accessKey and secretKey were removed in the same version: backups to MinIO now need the prerequisite dictionary secret described in Backing Up, named by postgres.backup.minio.credentialsSecretName. Installs in HA mode have nothing to change in this step.

Upgrading From 1.2.0 or 1.3.0

Version 1.3.0 moved the highly available database (postgresHA.enabled: true, the default) to the same credentials model, and 1.3.1 completed it for MinIO backups. postgresHA.postgres.username, postgresHA.postgres.password, and postgresHA.postgres.database no longer exist; the HA database now reads the credentials secret this template creates from postgres.credentials.*, named by postgresHA.config.credentialsSecretName. Carrying the old block fails at render:
Use the credentials your cluster already has. They were applied when the database was first initialised and are what PostgreSQL still enforces. Putting new values in postgres.credentials.* does not change the running database — it gives n8n a password that no longer works.
1

Move the credentials

Delete postgresHA.postgres.* from your values and put the same three values under postgres.credentials.username, postgres.credentials.password, and postgres.credentials.database. The block sits under postgres: even though postgres.enabled stays false — it feeds both modes. Ignore the message’s advice to create a secret yourself; this template creates it.
2

Pick a secret name

postgresHA.config.credentialsSecretName defaults to my-n8n-db-credentials. Secret names are org-wide, so give each n8n release in the org its own.
3

MinIO backups only

postgresHA.backup.minio.accessKey and secretKey were removed. Create the prerequisite dictionary secret described in Backing Up and set postgresHA.backup.minio.credentialsSecretName to its name. 1.3.0 still listed the two removed keys in its values while the bundled database already refused them, which is why MinIO backups in HA mode need 1.3.1.
4

Upgrade

Run cpln helm upgrade with the updated values. The single n8n replica restarts, and the first upgrade after an install can also restart the bundled database — expect the editor and webhooks to be briefly unavailable. Workflows, credentials, and execution data are untouched.
This upgrade path has not been exercised against a live n8n install; if your database password is the shipped default change-me-n8n-db-password, treat it as compromised and change it inside PostgreSQL before putting the new value in postgres.credentials.password.

Scaling and Availability

  • n8n runs as a single replica (maxScale: 1) by upstream design for the standard mode this template ships; the knob to grow is resources, not a replica count.
  • The database is highly available by default — postgresHA.replicas: 3 Patroni replicas with automatic failover behind an HAProxy leader endpoint, so a database node loss does not take n8n down. Set postgresHA.enabled: false and postgres.enabled: true for a single-instance database when availability matters less than footprint.
  • Every helm upgrade restarts the single n8n replica, so the editor and webhooks are briefly unavailable; the first upgrade after an install can also restart the bundled database.
  • Volume capacity: grow volumeset.capacity (n8n) or postgresHA.volumeset.capacity / postgres.volumeset.capacity (database) in GiB; the minimum is 10.

Troubleshooting

Cause: a prerequisite secret named in your values does not exist, so the container never ran. Fix: read the message that names the missing secret, then create it:
The deployment recovers on its own once the secret exists, or run cpln workload force-redeployment RELEASE_NAME-n8n --gvc GVC_NAME to skip the wait.
Cause: both database modes are enabled, or neither is. Fix: set exactly one of postgresHA.enabled and postgres.enabled to true. The HAProxy endpoint must stay on in HA mode (postgresHA.proxy.enabled is refused when false).
Cause: your values still carry a key an earlier version took — owner.email / owner.password (removed in 1.1.0), postgres.config.username / password / database (removed in 1.2.0), or postgresHA.postgres.* and *.backup.minio.accessKey / secretKey (removed in 1.3.0 / 1.3.1). The render fails before anything is applied, and the running release is untouched. Fix: follow the matching section under Operations, starting with Upgrading From 1.0.x.
Cause: two n8n releases in the same org share a credentialsSecretName — secret names are org-wide, and the default my-n8n-db-credentials is owned by the first release. Nothing is shared or overwritten and the first release is unaffected. Fix: give the new release its own postgresHA.config.credentialsSecretName (or postgres.config.credentialsSecretName).
Cause: the owner secret holds a different hash than the password you were using. n8n re-applies the owner from the secret on every start, so the secret’s hash is the login. Fix: sign in with the password that matches the hash in the secret, or put the hash of the password you want there and force a redeployment — see Rotating the Owner Password.
Cause: N8N_ENCRYPTION_KEY no longer matches the key the instance was first started with; n8n refuses to start on a mismatch. Fix: put the original key back in the encryption key secret and force a redeployment. If the original key is gone, the stored credentials cannot be recovered — start a fresh install and re-enter them.
Cause: the workflow took longer than 30 seconds to produce its synchronous response (timeoutSeconds on the workload). The workflow still completes. Fix: set the Webhook node to respond immediately or add a Respond to Webhook node early in the workflow.
Cause: n8n starts before the bundled database is accepting connections and exits until it is; its retry is the database wait. Fix: nothing — it settles on its own once the database is up. Investigate only if cpln workload get-deployments RELEASE_NAME-n8n --gvc GVC_NAME -o yaml never reports ready.

Important Notes

  • Back up the encryption key secret before installing — it cannot be rotated; losing or changing it makes every stored credential undecryptable and n8n fails to start on a mismatch.
  • Create both prerequisite secrets before installing — a missing one wedges the deployment with no log output; cpln workload get-deployments RELEASE_NAME-n8n --gvc GVC_NAME -o yaml is the one command that names it.
  • The owner secret is the login at every restart — change the password through the secret plus a forced redeployment, never from inside n8n, and when upgrading hash the password you use today.
  • Change postgres.credentials.password before installing — it is used exactly as written and feeds both database modes.
  • Run only one n8n release per credentialsSecretName — secret names are org-wide; a second release on the same name is refused at install.
  • Synchronous webhook responses must finish within 30 seconds — see Connecting.
  • Every upgrade restarts the single n8n replica — expect a brief editor and webhook outage; the first upgrade after an install can also restart the bundled database.
  • Uninstall deletes the database and n8n volume sets — all workflows, credentials, and execution data; enable backups if the data matters.
  • n8n is fair-code under the Sustainable Use License — free to self-host, not OSI open source.

External References

n8n Documentation

Official n8n documentation

Environment Variables

n8n deployment environment variables reference

Webhook Endpoints

Webhook and endpoint configuration reference

User Management

Owner account and user management guide

Sustainable Use License

The fair-code license n8n is distributed under

n8n Template

View the source files, default values, and chart definition