Skip to content

Backup n8n with PostgreSQL

This guide explains how to backup a self-hosted n8n instance running in Docker with PostgreSQL database.

  • n8n 2.12.3
  • PostgreSQL 15.15

Last updated: 19.mar.2026

ComponentContents
PostgreSQL databaseWorkflows, credentials (encrypted), execution history, users
n8n_data volumeConfig file, binary uploads, custom nodes, SSH keys
compose.yamlEnvironment variables, encryption key, database credentials
  • n8n running in Docker with PostgreSQL
  • Access to the server
  • postgres-main container running (or your PostgreSQL container name)

The database contains all workflows and credentials:

Terminal window
docker exec <postgres_container> pg_dump -U <db_user> <db_name> > n8n-db-<date>.sql
Terminal window
docker exec postgres-main pg_dump -U n8n_user n8n > n8n-db-18-mar-2026.sql

The volume contains the encryption key file and binary data:

Terminal window
docker run --rm \
-v n8n_data:/data \
-v /home/<user>:/backup \
alpine tar -czvf /backup/n8n-data-<date>.tar.gz -C /data .
Terminal window
docker run --rm \
-v n8n_data:/data \
-v /home/<username>:/backup \
alpine tar -czvf /backup/n8n-data-18-mar-2026.tar.gz -C /data .

Copy the compose file which contains the encryption key:

Terminal window
cp /opt/docker/n8n/compose.yaml n8n-compose-<date>.yaml
Terminal window
cp /opt/docker/n8n/compose.yaml n8n-compose-18-mar-2026.yaml

Bundle all components into a single backup file:

Terminal window
tar -czvf n8n-<date>.tar.gz \
n8n-db-<date>.sql \
n8n-data-<date>.tar.gz \
n8n-compose-<date>.yaml
Terminal window
tar -czvf n8n-18-mar-2026.tar.gz \
n8n-db-18-mar-2026.sql \
n8n-data-18-mar-2026.tar.gz \
n8n-compose-18-mar-2026.yaml

Check the backup contents:

Terminal window
tar -tzvf n8n-<date>.tar.gz

Expected output:

n8n-db-18-mar-2026.sql
n8n-data-18-mar-2026.tar.gz
n8n-compose-18-mar-2026.yaml

The N8N_ENCRYPTION_KEY is essential for restoring credentials. It’s stored in:

  1. compose.yaml as environment variable
  2. n8n_data volume in /config file

If lost, encrypted credentials cannot be recovered. Store the encryption key in a password manager separately from backups.

n8n backups contain sensitive data:

  • Database credentials and passwords
  • Encryption key in compose.yaml
  • Encrypted workflow credentials

Do not store n8n backups in public locations. Keep them in:

  • /home/<user>/ (local only)
  • Private cloud storage with encryption
  • Offline backup media

Do not upload n8n backups to publicly accessible web servers or documentation sites.

Store the encryption key separately in a password manager.

Terminal window
docker network create proxy
mkdir -p /opt/docker/n8n
Terminal window
tar -xzvf n8n-<date>.tar.gz
Terminal window
cp n8n-compose-<date>.yaml /opt/docker/n8n/compose.yaml

Important: Ensure N8N_ENCRYPTION_KEY matches the original.

Terminal window
docker volume create n8n_data
docker run --rm \
-v n8n_data:/data \
-v $(pwd):/backup \
alpine tar -xzvf /backup/n8n-data-<date>.tar.gz -C /data
Terminal window
docker exec -it postgres-main psql -U postgres -c "CREATE USER n8n_user WITH PASSWORD '<your_password>';"
docker exec -it postgres-main psql -U postgres -c "CREATE DATABASE n8n OWNER n8n_user;"
docker exec -it postgres-main psql -U postgres -c "GRANT ALL PRIVILEGES ON DATABASE n8n TO n8n_user;"
Terminal window
cat n8n-db-<date>.sql | docker exec -i postgres-main psql -U n8n_user -d n8n
Terminal window
cd /opt/docker/n8n
docker compose up -d

After restoring, verify n8n is working:

  1. Check container status:

    Terminal window
    docker ps | grep n8n
  2. Check n8n logs:

    Terminal window
    docker logs n8n --tail 20
  3. Login to n8n UI - Verify workflows appear and credentials are accessible

  4. Test a workflow - Run a simple workflow to confirm execution works

  • Keep last 2 backups locally in /home/<username>/
  • Delete backups older than 30 days
  • Test restore quarterly
  • Store encryption key in password manager (separate from backup files)
  • Store backups in multiple private locations
  • Schedule automated backups with cron