Treat N8N_ENCRYPTION_KEY like the master key to your vault. Lose it and every stored credential in n8n stays locked forever
What is N8N_ENCRYPTION_KEY
What you’ll learn: What this key does, where it lives, and why every instance must share the same value
N8N_ENCRYPTION_KEY is the secret n8n uses to encrypt and decrypt credentials
- n8n is an open-source workflow automation platform
- The key protects credentials such as API keys, passwords, and tokens
- Encryption at rest means data is encrypted on disk in your database
Key facts
- n8n encrypts credentials before saving them to the DB
- If you do not set a key, n8n may auto-generate one and save it in
~/.n8n/config - That convenience can break upgrades, container rebuilds, or cluster moves
Think of it as a house key. Copies must match, and every door in the house needs the same key
Where it fits
- The key protects credentials at rest in SQLite or Postgres
- All app instances must load the identical key to use those credentials
- Queue or worker setups require perfect key parity across all nodes
Transition: Here is how the key flows through save and load operations
flowchart TD
A[Save credential] --> B[Use key]
B --> C[Encrypt data]
C --> D[DB store]
E[App start] --> F[Load key]
F --> G[Decrypt on use]
classDef trigger fill:#e1f5fe,stroke:#01579b
classDef process fill:#fff3e0,stroke:#ef6c00
classDef action fill:#e8f5e8,stroke:#2e7d32
class A,E trigger
class B,C,F process
class D,G action
Auto vs explicit
A simple rule: explicit beats implicit in production
| Approach | Upsides | Risks |
|---|---|---|
Auto-generated in ~/.n8n/config | Fast local start | Easy to lose, breaks migrations, hidden in volumes |
| Explicit env var or secret | Predictable, portable, auditable | Needs setup and backup |
Best for
- Auto-generated: throwaway development
- Explicit env var or secret: production and all teams
Transition: With the why covered, let us set it up safely
Set up the key
What you’ll learn: How to generate a strong key, persist it, and make multiple instances share it
Generate a strong key
Use a 256-bit random value
# 32 bytes as 64 hex chars
openssl rand -hex 32
# Optional: print a fingerprint to compare across nodes
printf "$N8N_ENCRYPTION_KEY" | sha256sum
- A fingerprint is a short hash that helps confirm parity across nodes without revealing the key
- Use a secret manager, which is a system for secure storage and auditing of sensitive values
One secure key, many instances. Keep the value identical across main, workers, and webhooks
Single instance
- Generate the key and store it in your secret manager
- Export it before starting n8n
- Persist
~/.n8nso config and files survive reboots
export N8N_ENCRYPTION_KEY="<64-hex-chars>"
npx n8n
If you use a .env, source it in your systemd service or shell profile
Docker or Compose
- Put the key in your
.envor your secret store - Mount a persistent volume for
/home/node/.n8n - Pass the key to main and worker containers if you scale later
version: "3.8"
services:
n8n:
image: n8nio/n8n:latest
env_file: .env
environment:
- N8N_ENCRYPTION_KEY=${N8N_ENCRYPTION_KEY}
volumes:
- n8n_data:/home/node/.n8n
ports:
- "5678:5678"
volumes:
n8n_data:
Keep the key value stable across updates and rollbacks
Queue workers
- Use one shared secret for every instance such as main, workers, and webhooks
- Inject the same key everywhere
- Automate a fingerprint check in health probes
services:
n8n:
environment:
- EXECUTIONS_MODE=queue
- N8N_ENCRYPTION_KEY=${N8N_ENCRYPTION_KEY}
worker:
image: n8nio/n8n:latest
environment:
- N8N_ENCRYPTION_KEY=${N8N_ENCRYPTION_KEY}
command: n8n worker
If one node differs, decryption fails mid-execution
Transition: If things go wrong, use this quick path to diagnose and fix
flowchart TD
A[Start issue] --> B{Key drift}
B -->|Yes| C[Restore key]
B -->|No| D{Volume issue}
D -->|Yes| E[Fix mount]
D -->|No| F[Check env var]
F --> G[Re-deploy]
classDef alert fill:#f3e5f5,stroke:#7b1fa2
classDef process fill:#fff3e0,stroke:#ef6c00
class A,B,D alert
class C,E,F,G process
Troubleshoot key errors
What you’ll learn: How to identify key mismatches and restore access fast
Mismatching encryption keys
Likely cause: the running key differs from the one that encrypted the DB
- Confirm the env var inside the process or container
- Compare fingerprints across nodes
- Check for an auto-generated key in
~/.n8n/config
Remediation checklist
- Stop all instances
- Restore the original key value everywhere
- Restart one node, verify credentials open, then roll out
Docker upgrade shows empty creds
Symptoms: workflows exist but credentials error or look missing after a redeploy
- A fresh container started without the old key
- The volume path changed or was re-created
- The app generated a new key silently
Fix steps
- Inspect the previous stack and find the original key or config file
- Reattach the correct volume path
- Export the key to
N8N_ENCRYPTION_KEYand restart
Config and volume hiccups
- The
~/.n8ndirectory changed owners or was reset - File permissions block reads in containers
Try
# On host or container
ls -la /home/node/.n8n
# Fix ownership if needed
chown -R node:node /home/node/.n8n
Then relaunch with the known-good key
Original key lost
Hard truth: you cannot decrypt old credentials without the exact key
- Rotate operationally, not cryptographically, by generating a new key
- Recreate credentials in n8n using sources of truth
- Document and back up the new key immediately
Backup saves days and sometimes weeks
Transition: Some teams prefer file-based secrets. Here is what to know
N8N_ENCRYPTION_KEY_FILE guide
What you’ll learn: Intended behavior, current reliability, and safe workarounds
This feature loads the key from a file path, which fits Docker or Kubernetes secrets
- Kubernetes or K8s is a container orchestration platform
- A secret file is mounted into the container filesystem and read at runtime
Intended behavior
- Set
N8N_ENCRYPTION_KEY_FILE=/path/to/secret - n8n reads the file content as the key
- You avoid placing secrets directly in env vars which are environment variables
Reported bug and cause
- Config precedence and load order can skip reading from the file
- Result: the app acts as if no key exists or falls back to a different value
- Impact appears across multiple recent versions depending on image or build
Practical impact in Docker and K8s
| Method | Works Reliably Today? | Notes |
|---|---|---|
| N8N_ENCRYPTION_KEY (env) | ✅ | Least surprise in most environments |
| N8N_ENCRYPTION_KEY_FILE (file) | ⚠️ | May be ignored in some builds or versions |
Use file-based secrets for storage, then export to env at runtime
Safe workarounds
- Bootstrap script reads the mounted secret and exports the env var
- Keep the secret in your manager such as Kubernetes Secret, Docker Secret, or Vault
- Ensure every pod or container runs the same bootstrap
#!/usr/bin/env sh
set -euo pipefail
if [ -n "${N8N_ENCRYPTION_KEY_FILE:-}" ] && [ -f "$N8N_ENCRYPTION_KEY_FILE" ]; then
export N8N_ENCRYPTION_KEY="$(cat "$N8N_ENCRYPTION_KEY_FILE")"
fi
exec n8n
Note: behavior may change. Review release notes before switching back to _FILE
erDiagram
Instance ||--o{ Credential : uses
Database ||--o{ Credential : stores
Instance {
int id
string hostname
string key_fingerprint
datetime created_at
}
Credential {
int id
string name
string value_encrypted
datetime created_at
}
Database {
int id
string engine
string host
datetime created_at
}
Transition: With setup and operations covered, let us lock in durable practices
Production playbook
What you’ll learn: How to prevent silent key changes and run reliable migrations and restores
Key generation and access
- Generate with
openssl rand -hex 32and store in your secret manager - Limit read access and log access via IAM or RBAC
- IAM is identity and access management; RBAC is role-based access control
- Never commit keys to Git, images, or notes
Avoid silent key changes
- Always set
N8N_ENCRYPTION_KEYexplicitly in every environment - Pin your volumes and do not let
~/.n8nbe ephemeral by accident - Add a startup probe that logs a key fingerprint for parity checks
Migration and DR checklist
- DR means disaster recovery
- Back up DB and the encryption key before any change
- Stand up target infrastructure and inject the same key first
- Restore the DB, start a single node, and verify credentials
- Scale workers and confirm fingerprints match
- Document the runbook and store it with incident docs
Bottom line: set one strong key, keep it safe, and make every n8n instance use it. That habit turns upgrades and failovers into routine work, not rescue missions