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
Related Posts
n8n Environment Variables: Complete Configuration Reference
A practical, production-focused guide to n8n environment variables: what each setting does, defaults, examples, when to change them, plus a copy‑paste .env and fixes.
n8n Encryption Key: Complete Guide to N8N_ENCRYPTION_KEY, Credential Security & Recovery
A practical guide to n8n credential security. Learn N8N_ENCRYPTION_KEY fundamentals, setup for Docker/Kubernetes/systemd, best practices, recovery drills, and a real case study.
GitOps Backups for n8n: 30‑Minute Schedule + One‑Click Restore
Set up two n8n flows: a Git backup every 30 minutes and a manual restore. Copy‑paste CLI, node configs, and security best practices for safe rollbacks.
n8n Docker Setup: Encryption Key, Volumes & Backup Guide
Complete guide to setting up N8N_ENCRYPTION_KEY in Docker, troubleshooting the _FILE variant issue, configuring persistent volumes, and backing up workflows and credentials safely.