Back to Home

Migration of n8n to Traefik 3.3 and Postgres 16: technical guide

Guide to migrating n8n from Traefik 1.x and Postgres 11 to current versions. Detailed solutions for encryption key issues, Docker API incompatibility, and permissions in Postgres 16. Saving data and accounts without downtime.

How to migrate n8n to Traefik 3.3 and Postgres 16 without data loss
Advertisement 728x90

Safe n8n Migration: Upgrading Traefik to 3.3 and Postgres to 16 Without Data Loss

Migrating n8n from outdated versions of Traefik and Postgres to a modern stack requires addressing critical compatibility issues. This article provides a technical guide to preserving data and credentials when upgrading from Traefik 1.x and Postgres 11 to the latest versions.

Preparation: Backup and Encryption Key

The key stage of migration is properly exporting data and preserving the encryption key. Without it, credentials will become inaccessible after the transfer. For n8n, this is critical: the system uses symmetric encryption to store tokens and passwords.

Perform these two mandatory actions:

Google AdInline article slot
  • Create a database dump in custom format for proper restoration:
docker exec -t postgres_db pg_dump -U root -d n8n -Fc > /tmp/n8n_backup.dump
docker cp postgres_db:/tmp/n8n_backup.dump ./n8n_backup.dump
  • Extract the current encryption key from the configuration. The source may be in two places:

- Variable N8N_ENCRYPTION_KEY in docker-compose.yml

- Parameter encryptionKey in file ~/.n8n/config

Ignoring this step will lead to a Needs first setup error after startup. The system will recognize the database but won't be able to decrypt the stored credentials.

Google AdInline article slot

Deploying the Stack: Traefik 3.3 Pitfalls

When deploying Traefik 3.3, a critical incompatibility issue with the Docker API arises. The router defaults to an outdated API version (1.24), while modern Docker daemons require version 1.41 or higher. This results in 404 errors when trying to discover containers.

Solution — force the API version in environment variables:

environment:
  - DOCKER_API_VERSION=1.41

This change makes Traefik interact correctly with Docker Engine. Without it, the router can't see the n8n and Postgres containers, making automatic route setup via Docker Provider impossible.

Google AdInline article slot

Note the network isolation: all services must be in the same custom network (n8n_net). This ensures stable interaction between containers without routing conflicts. Example of correct configuration:

networks:
  n8n_net:
    name: n8n_net

services:
  traefik:
    networks:
      - n8n_net
  n8n:
    networks:
      - n8n_net
  postgres_db:
    networks:
      - n8n_net

Restoring the Database in Postgres 16: Fixing Permissions Issues

Postgres 16 introduces changes to the default security policy. The public schema now has restricted permissions, causing a permission denied for schema public error when starting n8n.

After restoring the dump, run:

docker cp n8n_backup.dump postgres_db:/tmp/
docker exec -i postgres_db pg_restore -U root -d n8n -1 /tmp/n8n_backup.dump

Then grant full permissions on the schema to the database owner:

docker exec -it postgres_db psql -U root -d n8n -c "GRANT ALL ON SCHEMA public TO root;"

This is necessary because n8n actively uses the public schema for storing metadata. Skipping this step will cause the n8n container to crash repeatedly.

Fixing Credentials: Avoiding the "Needs first setup" Error

Even when correctly passing N8N_ENCRYPTION_KEY via environment variables, n8n may ignore it. The reason is a conflict between the environment variable and the local config file. On first startup, the system generates a new ~/.n8n/config file that overrides the key from variables.

Solution:

  • Delete the config file inside the container:
docker exec -it n8n rm /home/node/.n8n/config
  • Restart the service:
docker compose restart n8n

This forces n8n to use the key from environment variables instead of the local file. Make sure the original N8N_ENCRYPTION_KEY variable is specified in docker-compose.yml.

Additional Nuances: Background Processes and SQLite

During migration, issues may arise with background tasks using SQLite (e.g., Telegram parsers based on Telethon). After transfer, you'll see sqlite3.OperationalError: database is locked.

Cause — residual journaling files (.session-journal, .session-wal) that lock the database. Solution:

  • Install the psmisc utility:
apt install psmisc -y
  • Force-kill processes holding the lock:
fuser -k -v /root/parser_folder/session_name.session
  • Delete temporary files:
rm -f /root/parser_folder/session_name.session-journal
rm -f /root/parser_folder/session_name.session-wal
  • Restart the service:
systemctl restart service_name.service

Important: Deleting journals doesn't affect the main session file. Telegram authorization remains intact.

Key Points

  • Encryption key is mandatory — without the original N8N_ENCRYPTION_KEY, all Credentials will become inaccessible.
  • Traefik requires explicit API specification — the DOCKER_API_VERSION=1.41 parameter is critical for container discovery.
  • Postgres 16 restricts permissions — manually issue GRANT ALL ON SCHEMA public.
  • n8n local config conflicts — deleting ~/.n8n/config resolves the encryption key issue.
  • SQLite locks require cleanup — removing .journal and .wal files restores background processes.

After completing all steps, n8n will start up with all workflows, webhooks, and credentials preserved. Migration between major software versions always carries risks, but following these procedures minimizes downtime and data loss.

— Editorial Team

Advertisement 728x90

Read Next