Skip to content
Bytearium

No ads or affiliate links active

AI & automation

Self-hosting n8n: Docker, updates and backups

Self-host n8n with Docker Compose: pin the image, keep port 5678 local, back up the encryption key, update without data loss, licence limits.

One update, and suddenly every credential stored in n8n is "broken". Often nothing is broken at all: the encryption key simply stayed behind in a container that no longer exists.

The short answer

How do you self-host n8n, the workflow automation tool, without losing data in updates and restores? Run the official image with Docker Compose, keep /home/node/.n8n in a volume, publish port 5678 only on 127.0.0.1 and let a reverse proxy handle HTTPS [1][2]. Pin the image to a fixed version: as of 25 Oct 2026, the current stable release is 2.44.6 [2][3]. Back up the .n8n folder before every update, because it holds the key that decrypts every stored credential [4]. Under the Sustainable Use License, self-hosting is free for your own internal business purposes and for personal or non-commercial use. Making n8n available to customers so they can connect their accounts and build workflows is not covered [5].

How it works

  1. What n8n keeps where. By default, n8n stores credentials, executions and workflows in an SQLite database [2]. The database file sits in the .n8n folder, next to a file called config that holds the encryption key, and next to binary and execution data if those are stored on disk [4]. In the official Docker setup, that folder is the volume n8n_data, mounted at /home/node/.n8n [1][4]. Keep the volume even after a move to PostgreSQL. The folder still holds encryption keys and instance logs, and n8n advises keeping it on a persistent volume [2].
  2. The key that matters most. On first launch, n8n creates a random encryption key, saves it in the .n8n folder and uses it to encrypt credentials before they go into the database [6][7]. Without that key, neither a restored database nor an encrypted credential export can be decrypted [4]. You can set your own key with N8N_ENCRYPTION_KEY, but only as long as no key is in the settings file yet [6]. n8n can also read individual variables from a separate file if you add _FILE to the name [7], which keeps the key out of the Compose file. In queue mode, every worker needs the same key [6]. Keep a copy of the key in your password manager, separate from the backups.
  3. The official Compose setup. n8n's guide for Linux servers works in a directory n8n-compose with an .env file for DOMAIN_NAME, SUBDOMAIN, GENERIC_TIMEZONE and SSL_EMAIL [1]. A DNS A record points the subdomain to your server [1]. Two services run: Traefik, a reverse proxy that manages the TLS certificates and redirects HTTP to HTTPS, and n8n itself [1]. A folder local-files, which you create by hand so it gets the right ownership, shows up in the container as /files, and N8N_RESTRICT_FILE_ACCESS_TO=/files restricts file access to that path [1]. The result runs at https://<subdomain>.<domain>; plain HTTP is not supported in this setup [1].
  4. Pin the version. The official file just says image: n8nio/n8n, without a tag [1]. Docker then pulls the default tag, which n8n's documentation describes as the latest stable version [2]. Stable is meant for production; beta is the most recent release and may be unstable [2]. As of 25 Oct 2026, stable is 2.44.6, released on 22 Oct 2026, and beta is 2.45.3 [2][3]. n8n uses semantic versioning: a new major version can bring incompatible changes that need action from you [8]. According to n8n's archived 2.x release notes, a new minor version comes out most weeks [9]. Our reading: with a fixed tag such as n8nio/n8n:2.44.6, nothing changes behind your back when Docker pulls images, and you decide when to update. The same goes for Traefik, whose image the official file also leaves without a tag [1].
  5. Port 5678 stays on localhost. The official file publishes n8n as 127.0.0.1:5678:5678 [1]. 127.0.0.1 is the loopback address, so only programs on the server itself can reach that port, and the internet reaches n8n only through the proxy. The quick-start command on n8n's Docker page uses -p 5678:5678 instead [2]. That's fine on your own computer; don't copy it to a server. Our guide to Docker on a VPS explains how published ports and the host firewall interact.
  6. Behind the reverse proxy. n8n needs to know that it sits behind a proxy. Set N8N_PROXY_HOPS=1, and let the last proxy pass on the headers X-Forwarded-For, X-Forwarded-Host and X-Forwarded-Proto [10]. N8N_WEBHOOK_URL sets the public address for webhooks. It exists from n8n 2.30.0, and the older WEBHOOK_URL has been deprecated since 2.35.0 [1][10]. N8N_HOST and N8N_PROTOCOL=https complete the setup [1][7]. If you also run n8n's instance-level MCP server behind the same proxy, the proxy has to forward the MCP request headers too [10]. Our reverse proxy guide covers Caddy, Traefik and nginx.
  7. At home or on a VPS. Our assessment: if workflows receive webhooks from online services, those services need a public address, and that's the main reason for a VPS with its own subdomain. If n8n only calls out, for example on a schedule or to your own devices, it can stay in your home network, and you reach the editor through a VPN. The same applies when a workflow talks to a local language model through n8n's Ollama Chat Model node [17]: keep the model and n8n in the same network. Either way, the editor should never be reachable from the internet without HTTPS.
  8. Lock the door. A new instance starts with creating the owner account, the main account of the instance, and according to n8n's backup guide, the first person to complete that setup becomes the owner [4]. So create it before the instance is reachable from the internet (our reading). n8n's security documentation covers two-factor authentication, security audits, disabling the public REST API, telemetry, blocking individual nodes and SSRF protection [11]. Telemetry is on by default. N8N_DIAGNOSTICS_ENABLED=false switches it off, but then Ask AI in the Code node is not available [7].
  9. Backups in two layers. The full backup is the .n8n folder plus, if you use one, the PostgreSQL database. Stop n8n before you copy the folder: copying the SQLite file while n8n writes to it can produce an inconsistent backup [4]. Back up PostgreSQL with its own tools, and include external storage, custom paths for binary data and the directories from N8N_CUSTOM_EXTENSIONS if you use them [4]. The light layer is the CLI export: export:workflow --backup and export:credentials --backup write one file per workflow or credential [4][12]. It contains no users, execution history, variables or instance settings, the encryption key included, so it isn't enough to rebuild an instance [4]. An export with --decrypted writes credentials in plain text, and n8n warns that all sensitive information is then visible [12]. Protect such a file like the credentials themselves, and delete it after use [4].
  10. Restore, and test it. A full restore goes like this: stop n8n, restore the .n8n folder and custom nodes, restore the database, restore the configuration including N8N_ENCRYPTION_KEY if you set it, then start n8n [4]. If you import only workflows and credentials, create the owner account first. Imported workflows arrive deactivated, and workflows with the same IDs are overwritten [4]. To move from SQLite to PostgreSQL, n8n offers export:entities and import:entities [12]. Our recommendation: restore once into a second, separate instance before you need it.
  11. Updates without data loss. n8n recommends updating frequently, at least once a month, reading the release notes for breaking changes and testing the update on a test instance first [13]. Its backup guide recommends a full backup before updating [4]. With Docker Compose, the update itself is pull, down and up [2]. Never add -v to docker compose down: that flag also removes the named volumes declared in the Compose file, n8n_data included [14]. Our reading: once a new version has migrated the database, going back to the old tag is not a reliable rollback. Restore the backup from before the update instead.
  12. The licence in plain words. n8n uses the Sustainable Use License, a fair-code licence that n8n created in 2022 [5]. You may use and modify the software for your own internal business purposes or for non-commercial or personal use, and distribute it only free of charge for non-commercial purposes [5]. Making n8n available to your customers so they connect their accounts and build workflows is not covered [5]. Consulting and support services, such as building n8n workflows for others, are allowed [5]. Source files with .ee. in their name fall under the n8n Enterprise License [5]. This is a summary, not legal advice: for edge cases, ask n8n or a lawyer.

A worked example (a plan, not tested)

We run n8n in Docker ourselves (as of 25 Oct 2026). What follows is not a copy of our setup but a plan built from the documentation, and we didn't run these commands for this guide. It assumes a server with Docker Compose, a reverse proxy already running on the same host, and the official directory n8n-compose with its .env file [1]. Compared with the official file, the plan has a fixed tag, no Traefik service and N8N_PROXY_HOPS=1 for the existing proxy, which forwards to 127.0.0.1:5678 [1][10]. No key or password appears in the file.

services:
  n8n:
    image: n8nio/n8n:2.44.6
    restart: always
    ports:
      - "127.0.0.1:5678:5678"
    environment:
      - N8N_ENFORCE_SETTINGS_FILE_PERMISSIONS=true
      - N8N_HOST=${SUBDOMAIN}.${DOMAIN_NAME}
      - N8N_PORT=5678
      - N8N_PROTOCOL=https
      - NODE_ENV=production
      - N8N_WEBHOOK_URL=https://${SUBDOMAIN}.${DOMAIN_NAME}/
      - N8N_PROXY_HOPS=1
      - GENERIC_TIMEZONE=${GENERIC_TIMEZONE}
      - TZ=${GENERIC_TIMEZONE}
      - N8N_RESTRICT_FILE_ACCESS_TO=/files
    volumes:
      - n8n_data:/home/node/.n8n
      - ./local-files:/files

volumes:
  n8n_data:

Back up (plan). Compose names containers after the pattern project-service-number, takes the directory name as the default project name, and docker compose ps -a lists the containers [15][18][19]. Here the name is n8n-compose-n8n-1. The tar call follows Docker's own example for backing up a volume [16]:

cd ~/n8n-compose
docker compose ps -a
docker compose stop n8n
mkdir -p backup
docker run --rm --volumes-from n8n-compose-n8n-1 -v "$(pwd)/backup":/backup ubuntu tar cvf /backup/n8n-data-2026-10-25.tar /home/node/.n8n
docker compose up -d

The second layer runs while n8n is up. The files land in ./local-files/backups on the host [1][12]:

docker exec -u node -it n8n-compose-n8n-1 n8n export:workflow --backup --output=/files/backups/workflows/
docker exec -u node -it n8n-compose-n8n-1 n8n export:credentials --backup --output=/files/backups/credentials/

Update (plan): make the full backup, change the tag in compose.yaml to the version from the release notes, then run:

docker compose pull
docker compose down
docker compose up -d

Restore (plan): stop n8n, unpack the archive into the volume, start again. The command mirrors Docker's restore example [16], and --strip 3 removes the path home/node/.n8n stored in the archive. Files created after the backup stay in the volume, so a restore into a fresh, empty volume is cleaner, and that's exactly what a test restore on a second instance gives you.

docker compose stop n8n
docker run --rm --volumes-from n8n-compose-n8n-1 -v "$(pwd)/backup":/backup ubuntu bash -c "cd /home/node/.n8n && tar xvf /backup/n8n-data-2026-10-25.tar --strip 3"
docker compose up -d

For the light layer, the counterpart is import:workflow --separate and import:credentials --separate with the same paths [4][12].

Checklist

  • Map /home/node/.n8n to a volume, and never run docker compose down with -v.
  • Copy the encryption key into your password manager, separate from the backups.
  • Pin the n8n and Traefik images to fixed version tags.
  • Publish port 5678 only on 127.0.0.1, and reach the editor through the reverse proxy with HTTPS.
  • Set N8N_PROXY_HOPS=1 and N8N_WEBHOOK_URL, and have the proxy pass on the X-Forwarded headers.
  • Create the owner account before the instance goes online, and turn on two-factor authentication.
  • Stop n8n, back up the .n8n folder and the database, then update, at least once a month.
  • Test a restore on a second instance before you need it.
  • Read the Sustainable Use License before you offer n8n to customers.

Related pages: Docker Compose: define a stack in one file; Docker on a VPS: firewall and hardening; Reverse proxy for a homelab; Homelab backups with restic or Borg; Large language model / LLM.

Primary sources

These sources are the basis of this page. That does not mean every claim was checked individually; whether a review record exists is shown above under “Status”. The interpretation and checklist are our own work.

There is no documented review record for this version yet. The text relies on the sources listed.

How this page was made: Bytearium creates these pages with the help of AI and is responsible for publishing them. AI can be wrong, so we show our sources and review status openly.

  1. n8nDocker Compose
  2. n8nDocker
  3. n8n on GitHubRelease n8n@2.44.6
  4. n8nBackup and restore
  5. n8nCommunity license
  6. n8nSet a custom encryption key
  7. n8nDeployment environment variables
  8. n8nRelease notes
  9. n8nRelease notes 2.x
  10. n8nConfigure webhook URLs with reverse proxy
  11. n8nSecurity
  12. n8nCLI commands
  13. n8nUpdate n8n
  14. Dockerdocker compose down
  15. Dockerdocker compose ps
  16. DockerVolumes
  17. n8nOllama Chat Model
  18. DockerConfigure pre-defined environment variables in Docker Compose
  19. DockerSpecify a project name

This page has no ads and no affiliate links.