Skip to main content

Overview

n8n is a workflow automation platform (fair-code, distributed under the Sustainable Use License). This template deploys an n8n instance backed by a highly available PostgreSQL cluster by default. The editor, REST API, and webhook endpoints are served on one public HTTPS endpoint, and the instance owner account is pre-provisioned at install — 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, which matters here because the n8n login form sits on a public endpoint by default.
Upgrading an install created with 1.0.0 or 1.0.1 is a breaking change, and it can change the password you log in with. owner.email and owner.password no longer exist; the owner now comes from a dictionary secret holding email and a bcrypt hash of the password. Because n8n re-applies the owner from that secret on every start, hashing a new password during the upgrade silently replaces your current login. Hash the password you are already using. See Upgrading From 1.0.x.

Architecture

  • n8n — A single-replica stateful workload serving the editor, REST API, and webhooks on port 5678. Public URLs are derived from the canonical endpoint at start, so webhook URLs work out of the box.
  • PostgreSQL (HA, default) — The postgres-highly-available template as a subchart: 3× Patroni PostgreSQL, 3× etcd, and a HAProxy leader-routing endpoint n8n connects through.
  • PostgreSQL (dev/lightweight, optional) — The single-instance postgres template instead, for lighter non-HA deployments.
  • Owner managed from a secret — The owner account is applied from your prerequisite secret at every start, so n8n never opens an unauthenticated setup page and the account cannot be edited from inside the app.

What Gets Created

  • Stateful n8n Workload — Single replica serving the editor, API, and webhooks on port 5678.
  • Database Workloads — HA mode: a stateful Patroni PostgreSQL workload, a stateful etcd workload, and a standard HAProxy leader-routing workload. Single mode: one stateful PostgreSQL workload.
  • Volume Sets — 10 GiB persistent storage for n8n instance config and binary execution data (/home/node/.n8n), plus the database subchart’s own volume sets.
  • Secrets — A start-script secret that derives public URLs at runtime, plus the database credentials created by the subchart. The owner login and the encryption key are not created here — they live in the two secrets you create.
  • Identity & Policy — A least-privilege policy granting the n8n identity reveal on exactly the secrets it uses, including your two pre-created secrets.
  • Cron Backup Workload (optional) — When database backups are enabled.
This template does not create a GVC. You must deploy it into an existing GVC.

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 the name you used, and store a copy of the key somewhere safe outside Control Plane.
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 the name you used.
4

Read a secret back later

-o yaml is required; without it the command prints the secret’s metadata table rather than its contents:
The owner is re-applied from the secret on every start (N8N_INSTANCE_OWNER_MANAGED_BY_ENV). Two consequences, both measured on a live instance:
  • Editing the secret and restarting the workload is how you rotate the password. After a rotation, the old password returned 401 and the new one 200.
  • The account cannot be changed from inside n8n. A password change through the API is refused with 403 This account is managed via environment variables and cannot be modified through the API.
So whatever is in the secret is the login, at every restart. Put the password you actually want there.
Losing the encryption key makes every credential n8n has stored permanently undecryptable, and the key must never change after first boot — n8n fails to start on a key mismatch. Back it up before installing.
A missing prerequisite secret wedges the install rather than failing it. cpln helm install still exits 0 and reports success, the resources are created, and the workload then never starts. Because the container never ran, cpln logs returns zero lines, which reads as a broken platform rather than a missing prerequisite.The only diagnostic is status.versions[].message, which names the missing secret:
It is get-deployments — plain cpln workload get has no versions key at all. Creating the missing secret clears the wedge on its own, but slowly: recovery across the catalog has been measured between 5.5 and 10.5 minutes, so poll rather than time-boxing it. A forced redeployment shortcuts it to roughly 90 seconds.
For optional database backups, you also need a bucket and access setup for one of the supported providers — see Backing Up. Once both secrets exist, install the template using 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

Upgrading From 1.0.x

Version 1.1.0 moved the instance owner out of Helm values. 1.0.0 and 1.0.1 shipped the owner’s email and password as values, used exactly as written, guarding a login form that is public by default.
This is the one upgrade in this batch that can change your password. Everywhere else, an existing credential keeps working untouched. Here it does not: 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 rejected before anything is applied. A real cpln helm upgrade carrying the old keys failed at render, created no Helm revision, and left the running release healthy and untouched:
Leaving owner.secretName empty is refused the same way.
To upgrade an existing install:
1

Create the owner secret

Follow Prerequisites, hashing the password you log in with today so the login does not change.
2

Drop the removed keys from your values

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

Upgrade

The single replica restarts and the editor and webhooks are briefly unavailable — see Important Notes. Workflows, credentials, and execution data on the volume set are untouched.

Choosing a Database Mode

Exactly one of the two database modes must be enabled — the chart enforces this at render and fails the install with a clear message otherwise.

Configuration

The default values.yaml for this template:

n8n Instance

  • image — The n8n container image.
  • resources — CPU and memory for the n8n container. minCpu / minMemory are the reservation; maxCpu / maxMemory are the limit.
  • encryptionKey.secretName — Name of your pre-created opaque secret holding the credential-encryption key. See Prerequisites.
  • owner.secretName — Name of your pre-created dictionary secret holding email and passwordHash. The owner is re-applied from it on every start, so editing the secret and restarting the workload is how you rotate the login — and the account cannot be edited from inside n8n. See Prerequisites.
  • owner.firstName / owner.lastName — Display name for the owner account. These remain ordinary values; only the email and password moved into the secret.
  • timezone — IANA timezone applied to Schedule triggers and $now expressions (e.g. America/Chicago).
  • volumeset.capacity — Volume size in GiB (minimum 10) for instance config and binary execution data.

Access

  • publicAccess.enabled — Serve the editor, API, and webhooks on the canonical *.cpln.app HTTPS endpoint. Set to false for an internal-only instance (external requests are blocked at the edge; in-GVC callers still reach it per internalAccess).
  • internalAccess.type — Internal firewall scope of the n8n workload:

Database

Enable exactly one of postgresHA (production, default) or postgres (dev/lightweight) — see Choosing a Database Mode. In both modes, change the database password before installing (postgres.credentials.password). n8n is wired to the active database automatically — the HAProxy leader endpoint in HA mode, or the single instance directly in dev mode. If you run more than one release of this template in the same organization, give each its own postgres.config.credentialsSecretName. Secret names are organization-wide, so a second release left on the default name is refused at install and creates nothing — the first release is unaffected.
Template version 1.0.0 did not compact the etcd cluster inside the bundled highly available database, so etcd’s backend grows with time alone and goes read-only once it reaches its 2 GiB quota — after roughly 110 days — taking PostgreSQL failover with it. Only installs running the HA database are affected (postgresHA.enabled, the default here); see etcd History Compaction for the mechanism and the symptoms. Upgrade to 1.0.1 or later to turn compaction on: that stops further growth but cannot shrink a backend that has already grown, and a cluster that has already raised a NOSPACE alarm needs operator recovery rather than an upgrade.

Connecting

Webhooks

Webhook URLs are derived from the canonical endpoint at startup, so the URLs shown in the editor are the ones external callers use — no extra configuration needed.
Synchronous webhook responses must finish within 30 seconds — the platform edge times out longer responses with a 504, although 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 right away while the workflow keeps running.

Backing Up

Database backups are optional and disabled by default. Enable them with postgresHA.backup.enabled or postgres.backup.enabled (matching your database mode), and complete the storage setup for your provider before installing. The values below are shown under backup.* — set them within the enabled database block.
1

Create a bucket

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

Set up a Cloud Account

If you do not have one, create a Cloud Account for your AWS account. Set backup.aws.cloudAccountName to its name.
3

Create a bucket-scoped IAM policy

Create an AWS IAM policy with the JSON below (replace YOUR_BUCKET), then set backup.aws.policyName to the policy’s name:
In HA mode, backup.mode selects logical (scheduled pg_dump via a cron workload) or wal-g (continuous WAL archiving). The single-instance mode takes scheduled logical dumps.

Important Notes

  • Back up the encryption-key secret — losing it permanently bricks every credential n8n has stored; never change it after first boot (n8n fails to start on a key mismatch).
  • Create both prerequisite secrets before installing. A missing one wedges the deployment with no log output at all; Prerequisites gives the one command that diagnoses it.
  • The owner secret is authoritative at every restart — it is not a one-time bootstrap. Changing it changes the login; see Upgrading From 1.0.x.
  • Change the bundled database password (postgres.credentials.password) before installing — it is used exactly as written. It stays a value deliberately: it is internal plumbing between n8n and its own database that nobody types.
  • The n8n main instance is single-replica by upstream design — the default HA PostgreSQL backend removes the database as a failure point.
  • Upgrades restart the single replica — expect roughly a minute of editor/webhook downtime per Helm upgrade. The first upgrade after an install also re-applies the bundled database, which can add a couple of minutes.
  • Access changes take time to propagate — after toggling publicAccess or internalAccess, re-test over roughly 30 seconds to 5 minutes before concluding the knob is broken.
  • Synchronous webhook responses must finish within 30 seconds — see Webhooks.
  • 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, but 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