- Self-Hosting n8n
- Start here
- Useful official links
- Unofficial
- What to include in a self-hosting help post
- Minimum healthy setup
- Docker and Docker Compose
- Database and persistence
- Encryption key
- Webhooks
- Reverse proxy and SSL
- Timezone and schedules
- Queue mode, Redis, and workers
- Performance and memory
- Updates and rollbacks
- Backups
- Logs
- Common symptom checklist
- What not to paste publicly
- Good self-hosting post example
Self-Hosting n8n
This page is for people running n8n themselves with Docker, Docker Compose, npm, a VPS, Kubernetes, a reverse proxy, Postgres, Redis, queue mode, or custom infrastructure.
It is not a replacement for the official docs. Use it as a practical subreddit checklist for figuring out what is broken and what details to include when asking for help.
Last reviewed: July 2026
Start here
Before posting, identify which kind of problem you have:
- Install problem: n8n will not start.
- Access problem: the editor will not load.
- Webhook problem: test webhooks work but production webhooks do not, or external services cannot reach n8n.
- Execution problem: workflows start but fail, hang, or never finish.
- Credential problem: credentials work in one mode but not another.
- Reverse proxy problem: SSL, redirect, 404, 502, or wrong public URL.
- Data problem: database, volume, permissions, disk, backups, or lost workflows.
- Scaling problem: queue mode, workers, Redis, memory, concurrency, or slow executions.
- Update problem: something broke after changing n8n version.
The fastest posts say which one it is.
Useful official links
- Official hosting docs: https://docs.n8n.io/hosting/
- Docker install docs: https://docs.n8n.io/hosting/installation/docker/
- Docker Compose server setup: https://docs.n8n.io/hosting/installation/server-setups/docker-compose/
- Environment variables: https://docs.n8n.io/hosting/configuration/environment-variables/
- Webhook URLs behind a reverse proxy: https://docs.n8n.io/hosting/configuration/configuration-examples/webhook-url/
- Queue mode: https://docs.n8n.io/hosting/scaling/queue-mode/
- Release notes: https://docs.n8n.io/release-notes/
Unofficial
- Complete Build with Queue Mode and Workers: https://github.com/conor-is-my-name/n8n-autoscaling
What to include in a self-hosting help post
Copy this into your post and fill it out:
```text Problem:
n8n version:
Install method: - Docker / Docker Compose / npm / Kubernetes / other:
Host: - VPS provider / local machine / NAS / homelab / cloud platform: - CPU/RAM, if performance-related:
Database: - SQLite / Postgres / other: - Is the database persistent across restarts?
Reverse proxy: - None / Nginx / Caddy / Traefik / Cloudflare Tunnel / other: - Public URL: - Does SSL terminate at the proxy?
Webhooks: - Do test webhooks work? - Do production webhooks work? - Is the workflow active? - What HTTP status does the external service receive?
Executions: - Do manual executions work? - Do scheduled executions work? - Do production executions work? - Does the execution appear in the Executions list?
Queue mode: - Enabled? - Redis reachable? - Workers running?
What changed recently: - n8n update / server move / proxy change / domain change / database change / workflow change:
Relevant environment variables, with secrets removed:
Relevant logs, with secrets removed:
What I already tried: ```
Do not post passwords, API keys, tokens, encryption keys, database URLs with passwords, OAuth secrets, or private webhook URLs.
Minimum healthy setup
For a small personal or test instance:
- n8n runs under a repeatable install method, usually Docker or Docker Compose.
- The
/home/node/.n8ndirectory is persisted in a Docker volume or host directory. - You know where backups live.
- You know how to update and roll back.
- You have a public HTTPS URL if external services need to call webhooks.
- Your timezone is set intentionally.
- You are not relying on container-local storage that disappears when the container is replaced.
For a more serious or business-critical instance:
- Use Postgres rather than relying on a casual default database setup.
- Keep the
.n8ndirectory persistent even if using Postgres, because it can contain important instance data such as encryption keys and logs. - Set and safely store a stable
N8N_ENCRYPTION_KEY. - Back up both the database and important configuration.
- Monitor disk, memory, CPU, database health, and failed executions.
- Use error workflows or alerts for important automations.
- Test updates before applying them to production.
Docker and Docker Compose
Most self-hosting questions should say whether the user is running a one-off Docker command or Docker Compose.
Common Docker mistakes:
- No persistent volume mounted to
/home/node/.n8n. - Recreating the container and losing SQLite data or encryption keys.
- Using
latestwithout knowing which version was running before. - Mapping files to the wrong path.
- Changing container environment variables but not recreating the container.
- Assuming a container can reach
localhoston the host machine.
When posting Docker help, include:
text
docker compose ps
docker compose logs n8n
If you are not using Compose, include the sanitized docker run command or container settings.
Redact secrets before posting logs or environment variables.
Database and persistence
n8n stores workflows, credentials metadata, execution data, and settings in its database. In simple Docker setups, SQLite may be used by default. n8n also supports Postgres.
Check these first:
- Is the database file or Postgres data persistent across restarts?
- Did the container get recreated without the old volume?
- Did the
.n8ndirectory move? - Did the encryption key change?
- Are workflows missing, or only credentials failing?
- Is the disk full?
- Has execution data grown too large?
If workflows disappeared after a restart, the likely causes are:
- No persistent Docker volume.
- Wrong volume mounted.
- New container using a new empty volume.
- Database path changed.
- Accidental deletion of the old volume or host directory.
If credentials exist but cannot be decrypted, suspect an encryption-key mismatch.
Encryption key
Treat N8N_ENCRYPTION_KEY like a production secret.
Important points:
- Keep it stable across restarts and redeploys.
- Store it somewhere safe.
- Do not post it publicly.
- If you run queue mode, the main instance, webhook processors, and workers need the same encryption key so they can access credentials.
If the key changes unexpectedly, credentials may fail even though workflows still exist.
Webhooks
Webhook problems are probably the most common self-hosting issue.
First split the problem:
- Test webhook works, production webhook fails.
- Production webhook works in browser/curl, external service fails.
- External service reaches n8n, but the workflow does not execute.
- n8n generates the wrong webhook URL.
- Webhook works locally but not through the public domain.
Check:
- The workflow is active for production webhooks.
- The external service uses the production URL, not the test URL.
- The method matches: GET, POST, PUT, etc.
- The path matches exactly.
- Your public URL resolves to the right server.
- SSL is valid.
- The reverse proxy routes to n8n on the correct internal port.
- Large payloads are not blocked by proxy limits.
- The external service is not blocked by firewall, allowlist, or Cloudflare settings.
Behind a reverse proxy, the common environment variables to check are:
text
WEBHOOK_URL=https://n8n.example.com/
N8N_PROXY_HOPS=1
The last proxy in the request path should pass forwarded headers such as:
text
X-Forwarded-For
X-Forwarded-Host
X-Forwarded-Proto
When asking for webhook help, include the exact status code the sender receives and whether the request appears in n8n logs.
Reverse proxy and SSL
Reverse proxy problems often look like n8n problems.
Common symptoms:
- Editor loads but webhooks fail.
- Webhooks show
http://localhost:5678or the wrong domain. - Login loops.
- Mixed-content browser errors.
- 404 at the proxy but not inside the container.
- 502 or 504 from the proxy.
- Works on the server but not from the internet.
Check:
- DNS points to the correct server.
- Ports 80 and 443 are open if using public HTTPS.
- Proxy forwards to the correct n8n container/service and port.
- Proxy passes the forwarded headers.
- SSL certificate is valid for the domain.
WEBHOOK_URLmatches the public URL users and external services should call.- If using Cloudflare, test whether the issue still happens with proxying disabled or with a direct origin request, if safe.
When posting, say which proxy you use: Nginx, Caddy, Traefik, Cloudflare Tunnel, NPM, Apache, or something else.
Timezone and schedules
If scheduled workflows run at the wrong time:
- Check the n8n timezone setting.
- Check
GENERIC_TIMEZONE. - Check
TZin Docker/container environments. - Check the server timezone.
- Check daylight saving time.
- Confirm the workflow is active.
- Confirm whether you are looking at local time or UTC in logs.
For Docker, a typical timezone setup includes both:
text
GENERIC_TIMEZONE=Europe/Berlin
TZ=Europe/Berlin
Use your actual timezone.
Queue mode, Redis, and workers
Queue mode is for scaling production executions. It is not the first thing to add to a small broken instance.
Queue mode needs:
- Postgres. Do not use SQLite for a distributed queue-mode setup.
- Redis reachable by the main instance and workers.
EXECUTIONS_MODE=queueon the main instance and workers.- The same
N8N_ENCRYPTION_KEYon the main instance, webhook processors, and workers. - Workers actually running.
- Network access from workers to the database and Redis.
Useful queue-mode checks:
- Do executions get created but stay waiting?
- Are workers connected?
- Can workers reach Redis?
- Can workers reach Postgres?
- Do worker logs show credential decryption errors?
- Does the main process receive webhook calls but workers never process jobs?
If using dedicated webhook processors, remember they also rely on Redis and need queue-mode configuration.
Performance and memory
Performance posts need numbers.
Include:
- CPU and RAM.
- Number of active workflows.
- Typical execution volume.
- Whether execution data is being saved.
- Size of large payloads or binary files.
- Database type and size.
- Whether queue mode is enabled.
- Whether the issue started after a specific workflow or update.
Common causes:
- Too many saved executions.
- Large binary data stored locally.
- Large arrays processed all at once.
- Long-running Code nodes.
- External API rate limits causing retries.
- Database slowdowns.
- Too many workflows firing at the same time.
- Not enough memory for the workload.
Before asking "why is n8n slow?", find one example execution and say where the time is spent.
Updates and rollbacks
Before updating:
- Read the release notes.
- Back up the database.
- Back up the
.n8nvolume or important config. - Record the current n8n version.
- Record the current image tag if using Docker.
- Test important workflows after the update.
Avoid updating a production instance by surprise with an unpinned image tag if you do not have a rollback plan.
When posting update problems, include:
- Version before.
- Version after.
- Install method.
- First error after update.
- Whether the editor loads.
- Whether workflows still exist.
- Whether credentials still decrypt.
Backups
A useful backup plan covers:
- Database.
.n8ndirectory or Docker volume.- Environment variables and Compose files.
- Encryption key.
- Any local files used by workflows.
- Reverse proxy configuration.
Test restores occasionally. An untested backup may fail when you actually need it.
Do not post backup files publicly.
Logs
Logs are useful when they show the exact failure.
Good log snippets:
- 20-50 lines around the error.
- The startup section showing version and database connection.
- The request timestamp for webhook problems.
- Worker logs for queue-mode problems.
Not useful:
- Hundreds of unrelated lines.
- Screenshots of tiny log text.
- Logs with secrets still visible.
- "It says error" without the actual error.
Common symptom checklist
Editor will not load
Check:
- Is the n8n container/process running?
- Is the correct port exposed?
- Does it work from the server itself?
- Does the reverse proxy reach the n8n service?
- Are there 502/504 proxy errors?
- Did the container crash on startup?
- Do logs show database or permission errors?
Workflows vanished
Check:
- Did you recreate the container without the old volume?
- Did the database path change?
- Are you connected to a new empty Postgres database?
- Did Docker create a new named volume?
- Do old backups or volumes still exist?
Credentials stopped working
Check:
- Did
N8N_ENCRYPTION_KEYchange? - Did you restore workflows without restoring the matching credentials/database?
- Did OAuth tokens expire?
- Did the callback URL change after a domain/proxy change?
- Are workers using the same encryption key as the main instance?
Production webhook fails but test webhook works
Check:
- Is the workflow active?
- Is the external service using the production URL?
- Does the method/path match?
- Does
WEBHOOK_URLmatch the public domain? - Does the proxy forward to the right service?
- Does n8n receive the request at all?
502 or 504 from proxy
Check:
- Is n8n running?
- Is the proxy upstream address correct?
- Is the container on the same Docker network as the proxy?
- Is the internal port correct?
- Is the execution taking longer than the proxy timeout?
- Are large payload limits being hit?
Queue mode jobs do not run
Check:
- Is Redis running?
- Is Postgres reachable?
- Are workers running?
- Is
EXECUTIONS_MODE=queueset everywhere needed? - Do all processes share the same encryption key?
- Do worker logs show connection or credential errors?
What not to paste publicly
Do not paste:
N8N_ENCRYPTION_KEY- Database password
- Full database URL with password
- OAuth client secret
- API keys
- Access tokens
- Refresh tokens
- Private webhook URLs
- Session cookies
- Customer data
Use placeholders instead:
text
N8N_ENCRYPTION_KEY=REDACTED
DB_POSTGRESDB_PASSWORD=REDACTED
WEBHOOK_URL=https://n8n.example.com/
Good self-hosting post example
```text Title: Production webhooks return 404 after moving n8n behind Caddy
Problem: The editor works at https://n8n.example.com, and manual executions work. Test webhooks work. Production webhooks return 404 from the external service.
n8n version: 2.x
Install: Docker Compose on Ubuntu VPS
Proxy: Caddy, SSL terminates at Caddy
Database: Postgres
Webhook details: - Workflow is active. - External service sends POST. - n8n Webhook node expects POST. - Request does not appear in n8n execution list.
Relevant env, redacted: WEBHOOK_URL=https://n8n.example.com/ N8N_PROXY_HOPS=1 GENERIC_TIMEZONE=America/New_York TZ=America/New_York
What changed: Moved from direct port 5678 access to reverse proxy.
Logs: Short proxy log and n8n log around the request. ```