Skip to content
Advertisement
Automation

Self-Host n8n with Docker: License, Backups, Security

AI Tools Tutorial Team20 min readDocumentation and user reports

Pricing and features verified August 2026

Photograph of circuit macro

Photo by Lenharth Systems via stocksnap (CC0)

Self-hosting n8n on Docker is the easy part. Staying legally self-hosted, and being able to restore the thing, is what most guides skip. n8n's Community Edition is free but licensed under the Sustainable Use License, which limits you to internal business or non-commercial use — hosting clients' workflows on your instance needs an Enterprise license. Lose the encryption key and every stored credential becomes unreadable, even from a perfect database backup. Here is the full setup, license line first.

Key takeaways

  • Community Edition is fair-code, not open source — hosting your clients' workflows on your instance needs an Enterprise license
  • Set N8N_ENCRYPTION_KEY yourself; a Postgres backup without that key restores workflows but not credentials
  • SSRF protection is off by default, so an HTTP Request node can reach a cloud metadata endpoint until you turn it on
  • Use N8N_WEBHOOK_URL — WEBHOOK_URL is deprecated, and n8n's own compose example still shows the old one
  • n8n 3.0 (scheduled for October 2026) drops npm and npx installs, so Docker is the migration path, not a preference

Should you self-host n8n at all?#

n8n Cloud's Starter plan is 20€/month billed annually (checked August 2026) and includes 2,500 workflow executions per month; Pro is 50€/month billed annually for 10,000. Self-hosting removes that line item and replaces it with a server bill plus your own hours on TLS, upgrades, backups and incidents.

Those tiers count workflow executions with unlimited steps, so the arithmetic flips at high volume rather than high complexity. A sixty-node workflow costs the same as a three-node one.

n8n Community Edition (self-hosted)

Best for: Teams with data-residency rules, high execution counts, or workflows that need filesystem and LAN access

4.3

Pricing
Free to run under the Sustainable Use License; paid features need a license key. Check current Cloud pricing at n8n.io/pricing

n8n's docs state that all self-hosted installations use the same core product, with Business and Enterprise keys adding features on top. The specific limitation to plan around: SSO, Environments, External Secrets, Projects and workflow sharing are not in the free edition, so multi-team access control is the first wall you hit.

Three situations where self-hosting wins:

  • Regulated or resident data. Records that cannot leave your network or your jurisdiction never reach a vendor's servers if the automation runs on yours.
  • Execution volume. Cloud tiers are priced by executions per month. When your workflow count is high and each run is cheap in compute, a server you already pay for wins.
  • Local access. Nodes that read the filesystem, reach an internal database, or call a service that only exists on your LAN cannot work from a hosted runner.

Where it does not win: a two-person team running a handful of workflows, anyone without a person who patches servers, and anyone who needs SSO or per-project permissions, since those are paid features either way. The same discipline we apply to evaluating any tool before buying applies here — the free license is not the whole cost.

What works

  • No per-execution ceiling — your server is the limit, not a plan tier
  • Data and credentials stay on infrastructure you control
  • Filesystem, LAN and internal-database nodes actually work
  • Same core product as Cloud, per n8n's own docs

What does not

  • You own TLS renewals, upgrades, patching and 3am incidents
  • SSO, Projects, Environments and workflow sharing are excluded from the free edition
  • Code-node isolation in external mode now needs the separate n8nio/runners image, so hardening costs extra containers
  • n8n's recommended way to test an update — Environments — is a paid Business or Enterprise feature
Advertisement

The license line: what you can and cannot charge for#

n8n is fair-code, not open source. The company says so directly, pointing out that Open Source Initiative licenses cannot include limitations on use, so n8n does not call itself open source. The license is the Sustainable Use License, Version 1.0.

It carries three restrictions. You may use or modify the software for internal business purposes, or for non-commercial and personal use. You may distribute it only free of charge and for non-commercial purposes. You may not alter, remove or obscure licensing and copyright notices.

n8n's plain-English gloss is the useful test: all use is allowed unless you are selling a product, service or module in which the value "derives entirely or substantially from n8n functionality." The two examples n8n names as not allowed are white-labeling n8n and offering it to your customers for money, and hosting n8n and charging people money to access it.

Two more details worth knowing. Files with .ee. in the filename, or .ee in the directory name, are carved out of the Sustainable Use License entirely and governed by a separate LICENSE_EE.md requiring a valid Enterprise license. And breach terminates your license automatically, with reinstatement possible within 30 days of notice if you stop the violation.

This is not legal advice, and nothing replaces reading the license yourself. The point is narrower: that boundary sits exactly where most agency business models want to operate, and finding it after you have signed clients is expensive.

What the free self-hosted edition includes#

Community Edition covers almost the complete feature set. The exclusions are specific: Custom Variables, Environments, External secrets, External storage for binary data, Log streaming, Multi-main mode, Projects, SSO via SAML or LDAP, workflow and credential sharing, and Git-based version control. Two of those exclusions are narrower than they look — plain logging is included even though log streaming is not, and queue mode is included even though multi-main mode is not.

There is a middle tier most people miss. Register your Community edition with an email address and n8n returns a free license key that adds exactly three things — Folders for organizing workflows, Debug in editor for copying and pinning execution data, and Custom execution data for annotating execution metadata.

Everything above that — SSO, environments, external secrets, log streaming, projects — sits on the Business and Enterprise plans and needs a paid key. Apply it in the UI under Settings then Usage and plan, or set N8N_LICENSE_ACTIVATION_KEY, which has no effect if the instance already has an activated license. If your network is locked down, allowlist the full range of Cloudflare IP addresses, because n8n's license server sits behind Cloudflare and the specific addresses change.

Advertisement

What changed in n8n 2.0, and why most guides are stale#

n8n 2.0 shipped in December 2025 — the company's blog dates the 2.0.0 beta to 8 December and stable 2.0.x to 15 December. n8n characterizes it as a hardening release across security, reliability and performance rather than a feature release, and says the changes apply to self-hosted, Cloud and Enterprise alike.

The headline change is that task runners are on by default, so Code node executions run in isolated environments with limited access. N8N_RUNNERS_ENABLED=true was the documented way to opt in early before 2.0; on 2.x it sets what is already the default. n8n's own Docker install page still carries it in the example docker run command, which is why it keeps propagating.

One consequence catches people mid-upgrade: because Code node executions now run on task runners in secure mode, $evaluateExpression() inside a Code node returns null or errors, since secure mode disables evaluating strings as code. Expressions in ordinary node fields are unaffected.

n8n 2.x defaults that break configs copied from older tutorials
Setting or featureWhat changed in 2.0What you should do
N8N_RUNNERS_ENABLEDTask runners run by default, so the flag now sets the defaultHarmless to keep, pointless to add
N8N_BLOCK_ENV_ACCESS_IN_NODENow defaults to true — Code nodes cannot read env varsMove secrets into credentials, not process env
N8N_SKIP_AUTH_ON_OAUTH_CALLBACKFlipped from true to falseRe-test OAuth credential flows after upgrading
Execute Command, Local File TriggerDisabled by defaultRe-enable deliberately, or redesign the workflow
MySQL and MariaDBNo longer supported as storage backendsMigrate to PostgreSQL or SQLite before upgrading
N8N_CONFIG_FILES, QUEUE_WORKER_MAX_STALLED_COUNTRemoved entirelyMove config to environment variables
In-memory binary data modeThe default (in-memory) mode is removed, along with N8N_AVAILABLE_BINARY_DATA_MODESSet N8N_DEFAULT_BINARY_DATA_MODE to filesystem or s3
External task runnersThe runner is no longer inside the n8nio/n8n imageRun the separate n8nio/runners image
Pyodide Python Code nodeReplaced by a native Python task runnerPython Code nodes now need runners in external mode
n8n 2.x defaults that break configs copied from older tutorials

If you are still on 1.x, run n8n's Migration Report first. It shows workflow-level and instance-level issues to address before upgrading, and it lives under Settings then Migration Report — available since version 1.121.0, and visible to global admins only. If MySQL or MariaDB is behind your instance, the documented path is to move that data to PostgreSQL or SQLite with the database migration tool before you upgrade. Both beat discovering the MySQL removal from a container that will not start.

The docker compose file#

This adds Postgres to n8n's documented Traefik example and replaces the deprecated webhook variable. Create a directory, add these two files, point an A record at your server, and start it.

  1. Create the .env file

    Generate the encryption key with openssl rand -hex 32 and never regenerate it afterward.

    DOMAIN_NAME=example.com
    SUBDOMAIN=n8n
    SSL_EMAIL=you@example.com
    GENERIC_TIMEZONE=Europe/Berlin
    
    N8N_ENCRYPTION_KEY=paste-a-long-random-string-here
    POSTGRES_DB=n8n
    POSTGRES_USER=n8n
    POSTGRES_PASSWORD=another-long-random-string
  2. Write compose.yaml

    Every value below maps to a documented n8n environment variable. Nothing here is decorative.

    services:
      traefik:
        image: traefik:v3
        restart: unless-stopped
        command:
          - "--providers.docker=true"
          - "--providers.docker.exposedbydefault=false"
          - "--entrypoints.web.address=:80"
          - "--entrypoints.web.http.redirections.entrypoint.to=websecure"
          - "--entrypoints.web.http.redirections.entrypoint.scheme=https"
          - "--entrypoints.websecure.address=:443"
          - "--certificatesresolvers.le.acme.tlschallenge=true"
          - "--certificatesresolvers.le.acme.email=${SSL_EMAIL}"
          - "--certificatesresolvers.le.acme.storage=/letsencrypt/acme.json"
        ports:
          - "80:80"
          - "443:443"
        volumes:
          - traefik_data:/letsencrypt
          - /var/run/docker.sock:/var/run/docker.sock:ro
    
      postgres:
        image: postgres:17-alpine
        restart: unless-stopped
        environment:
          - POSTGRES_DB=${POSTGRES_DB}
          - POSTGRES_USER=${POSTGRES_USER}
          - POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
        volumes:
          - db_data:/var/lib/postgresql/data
        healthcheck:
          test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER} -d ${POSTGRES_DB}"]
          interval: 10s
          timeout: 5s
          retries: 10
    
      n8n:
        image: docker.n8n.io/n8nio/n8n:2.33.6
        restart: unless-stopped
        depends_on:
          postgres:
            condition: service_healthy
        ports:
          - "127.0.0.1:5678:5678"
        labels:
          - "traefik.enable=true"
          - "traefik.http.routers.n8n.rule=Host(`${SUBDOMAIN}.${DOMAIN_NAME}`)"
          - "traefik.http.routers.n8n.entrypoints=websecure"
          - "traefik.http.routers.n8n.tls.certresolver=le"
          - "traefik.http.services.n8n.loadbalancer.server.port=5678"
        environment:
          - NODE_ENV=production
          - N8N_HOST=${SUBDOMAIN}.${DOMAIN_NAME}
          - N8N_PORT=5678
          - N8N_PROTOCOL=https
          - N8N_WEBHOOK_URL=https://${SUBDOMAIN}.${DOMAIN_NAME}/
          - N8N_EDITOR_BASE_URL=https://${SUBDOMAIN}.${DOMAIN_NAME}/
          - N8N_PROXY_HOPS=1
          - N8N_ENCRYPTION_KEY=${N8N_ENCRYPTION_KEY}
          - DB_TYPE=postgresdb
          - DB_POSTGRESDB_HOST=postgres
          - DB_POSTGRESDB_PORT=5432
          - DB_POSTGRESDB_DATABASE=${POSTGRES_DB}
          - DB_POSTGRESDB_USER=${POSTGRES_USER}
          - DB_POSTGRESDB_PASSWORD=${POSTGRES_PASSWORD}
          - DB_POSTGRESDB_SCHEMA=public
          - EXECUTIONS_DATA_PRUNE=true
          - EXECUTIONS_DATA_MAX_AGE=168
          - EXECUTIONS_DATA_PRUNE_MAX_COUNT=5000
          - N8N_SSRF_PROTECTION_ENABLED=true
          - N8N_PUBLIC_API_DISABLED=true
          - N8N_PUBLIC_API_SWAGGERUI_DISABLED=true
          - N8N_ENFORCE_SETTINGS_FILE_PERMISSIONS=true
          - N8N_RESTRICT_FILE_ACCESS_TO=/files
          - N8N_DIAGNOSTICS_ENABLED=false
          - N8N_VERSION_NOTIFICATIONS_ENABLED=false
          - GENERIC_TIMEZONE=${GENERIC_TIMEZONE}
          - TZ=${GENERIC_TIMEZONE}
        volumes:
          - n8n_data:/home/node/.n8n
          - ./local-files:/files
    
    volumes:
      n8n_data:
      db_data:
      traefik_data:
  3. Start it and create the owner account

    Run docker compose up -d, then open your subdomain over HTTPS. The first account you create is the instance owner, so do this before the domain is public knowledge.

    Note the port binding: 127.0.0.1:5678:5678 publishes n8n to loopback only, matching n8n's own compose example. Traefik reaches it over the internal Docker network; the internet cannot.

Two deliberate choices. The image tag is pinned rather than floating, because n8n releases a new minor version most weeks — n8n@2.33.6 was published on 7 August 2026 and was the current stable when this was written. And Traefik mounts the Docker socket read-only, which is convenient and is also a real privilege concession; if that trade is unacceptable in your environment, terminate TLS at a load balancer instead.

Advertisement

Persistence: the encryption key is the whole ballgame#

n8n creates a random encryption key on first launch and saves it in the ~/.n8n folder. Credentials in the database are encrypted with that key. Those two facts together produce the failure mode nobody plans for.

Keep persisting /home/node/.n8n even when your database is Postgres. n8n's Docker install page is explicit that the directory holds encryption keys, instance logs, and source control feature assets. A compose file that drops the volume "because the data is in Postgres now" is one restart away from an unrecoverable instance.

Database: SQLite or Postgres, and stopping it eating the disk#

n8n supports exactly two databases. SQLite is the default, living at ~/.n8n/database.sqlite. PostgreSQL is enabled with DB_TYPE=postgresdb plus the DB_POSTGRESDB_* variables, with TLS available through DB_POSTGRESDB_SSL_CA, _SSL_CERT, _SSL_KEY and _SSL_REJECT_UNAUTHORIZED.

On versions, n8n supports the latest two actively maintained Postgres majors plus one more for compatibility — as of July 2026 that meant 17 and 18, plus 16. MySQL and MariaDB are no longer supported at all as of 2.0.

Execution data is what fills the disk. Pruning is on by default, but the defaults keep a lot of history, and the most common self-hosted disk incident is an executions table nobody looked at.

Execution data pruning variables, with n8n's documented defaults
VariableDefaultWhy you would change it
EXECUTIONS_DATA_PRUNEtrueLeave on. Turning it off means unbounded growth.
EXECUTIONS_DATA_MAX_AGE336 (hours, 14 days)Cut to 168 if you only debug the last week.
EXECUTIONS_DATA_PRUNE_MAX_COUNT10000Lower it on a small disk; 0 removes the limit entirely.
EXECUTIONS_DATA_SAVE_ON_SUCCESSallSet to none for high-frequency workflows that always succeed.
EXECUTIONS_DATA_SAVE_ON_ERRORallKeep at all — this is the data you debug with.
EXECUTIONS_TIMEOUT-1 (disabled)Set a ceiling so a hung workflow cannot run forever.
Execution data pruning variables, with n8n's documented defaults

Two related knobs control how often cleanup runs: EXECUTIONS_DATA_PRUNE_HARD_DELETE_INTERVAL (15 minutes) and EXECUTIONS_DATA_PRUNE_SOFT_DELETE_INTERVAL (60 minutes). Leave them alone.

Advertisement

Reverse proxy, HTTPS and the webhook URL problem#

The classic symptom: n8n shows you a webhook URL of localhost:5678 when your instance lives on a public domain. The cause is mechanical — n8n auto-constructs the URL from its own protocol, host and port, and behind a proxy the internal port (5678) does not match the external one (443).

N8N_WEBHOOK_URL fixes it by setting the base URL for both test and production webhooks directly. Set N8N_PROXY_HOPS to the number of proxies in the request path so forwarded headers parse correctly — 1 for the compose file above.

Add N8N_EDITOR_BASE_URL alongside it. n8n's deployment variable reference describes it as the public URL where users access the editor, also used for emails n8n sends and as the SAML redirect URL.

For TLS itself, n8n recommends a reverse proxy such as Traefik or a network load balancer in front of the instance, chiefly because that also handles certificate renewals. The alternative is passing certificates directly with N8N_SSL_CERT and N8N_SSL_KEY, where n8n warns you must keep the certificate renewed yourself. Choose the proxy.

Finally, avoid running n8n on a sub-path. n8n's docs warn that combining N8N_PATH with reverse proxies causes folder navigation issues and advise a subdomain instead.

Backups you have restored at least once#

n8n gives you the parts — a CLI that exports workflows and credentials, and a database you can dump — but assembling them into something you can restore from is your job. It needs three layers, because no single one is sufficient.

  1. Layer 1 — export workflows and credentials via the CLI

    Run n8n's CLI inside the container with docker exec -u node -it <container> <command>.

    docker exec -u node -it n8n \
      n8n export:workflow --backup --output=/home/node/.n8n/backups/latest/
    
    docker exec -u node -it n8n \
      n8n export:credentials --all --output=/home/node/.n8n/backups/creds.json

    The --backup flag writes one file per workflow, which makes diffs readable in Git. Import with n8n import:workflow --separate --input=backups/latest/.

  2. Layer 2 — dump the database

    A pg_dump captures executions, settings and the credential rows in encrypted form. Schedule it, ship it off the host, and check the file size is non-zero — a cron job writing zero-byte dumps every night is the classic silent backup failure.

  3. Layer 3 — the .n8n volume and the encryption key

    Back up the n8n_data volume, and store N8N_ENCRYPTION_KEY separately in a secrets manager. Separately matters: a backup archive containing both the encrypted credentials and the key that decrypts them is a single object an attacker can walk away with.

  4. Run the restore drill

    Bring up the same pinned image on a scratch host with your key, restore the dump, and open a credential. If it works, you have a backup. If you have never done this, you have a hypothesis.

Advertisement

Upgrades and rollback#

The upgrade itself is three commands from your compose directory: docker compose pull, docker compose down, docker compose up -d. Your data lives in volumes and Postgres, not in the container, so replacing the container is not the risky part.

The risky part is version drift. n8n's own advice is to update at least once a month, precisely to avoid jumping several versions at once and hitting a disruptive change. Read the release notes for breaking changes before each upgrade.

Rollback is why you pin. Change the tag back to the version you were on, run docker compose up -d, and you are running the old binary again — assuming no migration rewrote the schema, which is exactly what your pre-upgrade dump covers. n8n also suggests testing an update on a test version of your instance first, but the Environments feature it points at is a paid Business or Enterprise feature, so Community users test on a scratch host.

Security basics most self-hosted instances get wrong#

n8n's security overview names the practices; the individual how-to pages carry the variable names. Here is the working list, ordered by how often it is missed.

Turn on SSRF protection. n8n's documentation states plainly that SSRF protection is off by default. Set N8N_SSRF_PROTECTION_ENABLED=true and, with the default blocked ranges, n8n blocks RFC 1918 private networks, loopback, IPv6 unique-local ranges, and link-local addresses including the cloud provider metadata endpoint at 169.254.169.254. On a VPS, that endpoint is the difference between a misused HTTP Request node and leaked instance credentials.

Disable the public API if you do not use it. N8N_PUBLIC_API_DISABLED=true turns off the public REST API; N8N_PUBLIC_API_SWAGGERUI_DISABLED=true removes the API playground.

Block dangerous nodes. NODES_EXCLUDE takes an array of node names as a string. Some nodes, including Execute Command, are blocked by default in 2.x, but be explicit about anything else you do not want available:

NODES_EXCLUDE: "[\"n8n-nodes-base.executeCommand\", \"n8n-nodes-base.readWriteFile\"]"

Constrain file access. N8N_RESTRICT_FILE_ACCESS_TO ships with no default, so nothing is off-limits until you name the directories nodes may touch. Set it explicitly, semicolon-separated for several paths. N8N_BLOCK_FILE_ACCESS_TO_N8N_FILES defaults to true and should stay there.

Enforce 2FA. N8N_MFA_ENFORCED_ENABLED defaults to false. Set it to true to require two-factor authentication for all users.

Opt out of telemetry if policy requires it. n8n collects anonymous telemetry from self-hosted installations; N8N_DIAGNOSTICS_ENABLED=false and N8N_VERSION_NOTIFICATIONS_ENABLED=false turn it off. Note the trade-off — with version notifications off, nothing tells you an upgrade exists, so put it in a calendar.

Audit it. Run n8n audit through the CLI to surface risks; the related N8N_SECURITY_AUDIT_DAYS_ABANDONED_WORKFLOW setting defaults to 90 days for flagging abandoned workflows.

Never publish port 5678. Bind it to loopback and let the proxy be the only front door. And keep n8n's cloudflared tunnel feature out of production — n8n's own docs flag it as a local development and testing convenience that isn't safe in production, and warn the implementation may change between versions.

For Code node isolation beyond the default, n8n documents external mode, where task runners launch as separate containers and give Code node JavaScript a fully isolated environment away from the core n8n process. Since 2.0 that means running the separate n8nio/runners image. The same page adds three further hardening steps: run the runner as the unprivileged nobody user (UID and GID 65532), give the container a read-only root filesystem with a small emptyDir mounted at /tmp, and apply an AppArmor profile so the runner cannot read /proc/environ and leak credentials. If you accept untrusted workflow contributions, read that page before you go live. The broader vendor security checklist covers the questions to ask of every tool that touches this data.

When one container stops being enough#

At some point a single n8n process stops keeping up. n8n's answer is queue mode, which it describes as providing the best scalability: the main instance handles triggers and webhooks while separate workers execute workflows.

The shape of it: EXECUTIONS_MODE=queue on both main and worker instances, Redis as the mandatory message broker via QUEUE_BULL_REDIS_HOST and friends, workers started with docker run docker.n8n.io/n8nio/n8n worker, and optionally dedicated webhook processors started with the webhook command. Every instance must share the same N8N_ENCRYPTION_KEY, or workers cannot decrypt credentials.

Treat this as the boundary where self-hosting stops being cheap in time. Single-container n8n is a weekend. Queue mode with Redis, workers and a binary data store is infrastructure work with an on-call expectation attached.

Who this is not for#

Skip self-hosting if any of these describe you.

  • Nobody on the team patches servers. An unpatched automation server holding every API key you own is a worse outcome than a subscription.
  • You need SSO or per-project permissions now. Those are paid features on self-hosted too, so the free tier does not solve it.
  • You plan to resell hosted automation. Running clients' workflows and credentials on your instance requires an Enterprise license. Build it on their instance, or buy the license.
  • Your volume is small. A handful of workflows is not worth a server, a proxy, a backup job and an upgrade cadence.

Self-hosted n8n versus Make and Zapier#

The platform choice is upstream of the hosting choice, and self-hosting only exists as an option on one of the three. If you have not settled that question, the three-way comparison of n8n, Make and Zapier covers pricing models, connector coverage and the switching costs.

Once your instance is running, the next work is not more features. It is failure handling: idempotent writes, capped retries, and somewhere for failed items to land. That is covered in automation error handling, and the trigger side is in the webhook integration guide. For a worked build on top of a running instance, see the shared-inbox triage workflow.

The verdict#

Self-host n8n if you have a person who patches servers and at least one of three reasons: data that cannot leave your network, execution volume that makes Cloud tiers expensive, or nodes that need local access. Otherwise pay for Cloud and spend the hours on workflows instead.

If you do self-host, the decision rule for the two things that cost money is short. Set N8N_ENCRYPTION_KEY yourself and store it apart from your backups, because credentials are unrecoverable without it. And if a client's workflows and credentials will live on your instance rather than theirs, email license@n8n.io before you sign the contract, not after.

Frequently asked questions

Is self-hosted n8n really free, and what's the catch?

The Community Edition is free to download and run, but it is licensed under the Sustainable Use License, not an open source license. Use is limited to your own internal business purposes or non-commercial use. Custom Variables, Environments, External Secrets, SSO, Projects and workflow sharing are excluded from the free edition.

Can you charge clients for automations built on a self-hosted n8n instance?

n8n's help center draws the line at whose instance it is. Helping clients set up their own internal instances requires no commercial license. Hosting and managing your clients' workflows and credentials inside your own instance requires an Enterprise license. Embedding n8n into a product needs an Embed license. Confirm your case with license@n8n.io.

Does self-hosted n8n need PostgreSQL, or is SQLite good enough?

n8n supports exactly two databases: SQLite, the default at ~/.n8n/database.sqlite, and PostgreSQL. SQLite is fine for a single container you back up as a file. Choose Postgres when you want standard dump-and-restore tooling, a separately backed-up data tier, or a route to queue mode with multiple workers later.

What happens if the n8n encryption key is lost?

Stored credentials are encrypted with that key, so losing it leaves them unreadable even if your Postgres database restores cleanly. n8n generates a random key on first launch and saves it in the ~/.n8n folder. Set N8N_ENCRYPTION_KEY yourself, store it in a secrets manager, and keep the .n8n volume persisted.

Why do n8n webhook URLs show localhost:5678 instead of your domain?

n8n builds webhook URLs from its own host, protocol and port, which behind a reverse proxy do not match the public address — internal 5678 versus external 443. Set N8N_WEBHOOK_URL to your public base URL, along with N8N_HOST, N8N_PROTOCOL and N8N_PROXY_HOPS. Use N8N_WEBHOOK_URL, not the deprecated WEBHOOK_URL.

How do you update self-hosted n8n without losing workflows and credentials?

Back up first, read the release notes for breaking changes, then run docker compose pull, docker compose down and docker compose up -d in your compose directory. Your data survives because it lives in the n8n_data volume and your database, not in the container. n8n advises updating frequently so you never jump several versions at once.

Sources

  1. n8n Docs — Host n8n (deployment options)
  2. n8n Docs — Install with Docker
  3. n8n Docs — Docker Compose example with Traefik
  4. n8n Docs — Choose n8n's database
  5. n8n GitHub — LICENSE.md (Sustainable Use License v1.0)
  6. n8n Docs — Sustainable Use License
  7. n8n Help Center — Which license applies to a given use case
  8. n8n Docs — Community edition features
  9. n8n Docs — Manage your license
  10. n8n Pricing
  11. n8n Docs — Configure webhook URLs with a reverse proxy
  12. n8n Docs — Environment variables: Endpoints
  13. n8n Docs — Environment variables: Deployment
  14. n8n Docs — Set a custom encryption key
  15. n8n Docs — Environment variables: Executions
  16. n8n Docs — Environment variables: Security
  17. n8n Docs — Environment variables: SSRF protection
  18. n8n Docs — Security overview
  19. n8n Docs — Disable the public API
  20. n8n Docs — Block specific nodes
  21. n8n Docs — Control telemetry
  22. n8n Docs — Harden task runners
  23. n8n Docs — Set up SSL
  24. n8n Docs — Use the command line (CLI)
  25. n8n Docs — Update n8n
  26. n8n Docs — v2.0 breaking changes
  27. n8n Docs — Release notes 2.x
  28. n8n Docs — v3.0 breaking changes
  29. n8n Blog — Introducing n8n 2.0
  30. n8n Docs — Enable queue mode
  31. n8n Docs — Environment variables: Binary data
  32. GitHub API — n8n latest release
Advertisement

AI Tools Tutorial Team

Editorial

The editorial team behind aitoolstutorial.com. Every tool is checked against its vendor's own pricing and docs before anything is published, every source is linked at the foot of the article, and every recommendation names at least one thing the tool gets wrong.