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
- What n8n keeps where. By default, n8n stores credentials, executions and workflows in an SQLite database [2]. The database file sits in the
.n8nfolder, next to a file calledconfigthat 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 volumen8n_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]. - The key that matters most. On first launch, n8n creates a random encryption key, saves it in the
.n8nfolder 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 withN8N_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_FILEto 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. - The official Compose setup. n8n's guide for Linux servers works in a directory
n8n-composewith an.envfile forDOMAIN_NAME,SUBDOMAIN,GENERIC_TIMEZONEandSSL_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 folderlocal-files, which you create by hand so it gets the right ownership, shows up in the container as/files, andN8N_RESTRICT_FILE_ACCESS_TO=/filesrestricts file access to that path [1]. The result runs athttps://<subdomain>.<domain>; plain HTTP is not supported in this setup [1]. - 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 asn8nio/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]. - 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:5678instead [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. - 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 headersX-Forwarded-For,X-Forwarded-HostandX-Forwarded-Proto[10].N8N_WEBHOOK_URLsets the public address for webhooks. It exists from n8n 2.30.0, and the olderWEBHOOK_URLhas been deprecated since 2.35.0 [1][10].N8N_HOSTandN8N_PROTOCOL=httpscomplete 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. - 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.
- 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=falseswitches it off, but then Ask AI in the Code node is not available [7]. - Backups in two layers. The full backup is the
.n8nfolder 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 fromN8N_CUSTOM_EXTENSIONSif you use them [4]. The light layer is the CLI export:export:workflow --backupandexport:credentials --backupwrite 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--decryptedwrites 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]. - Restore, and test it. A full restore goes like this: stop n8n, restore the
.n8nfolder and custom nodes, restore the database, restore the configuration includingN8N_ENCRYPTION_KEYif 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 offersexport:entitiesandimport:entities[12]. Our recommendation: restore once into a second, separate instance before you need it. - 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
-vtodocker compose down: that flag also removes the named volumes declared in the Compose file,n8n_dataincluded [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. - 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 -dThe 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 -dRestore (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 -dFor the light layer, the counterpart is import:workflow --separate and import:credentials --separate with the same paths [4][12].
Checklist
- Map
/home/node/.n8nto a volume, and never rundocker compose downwith-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=1andN8N_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
.n8nfolder 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.