Skip to content

Backup n8n with PostgreSQL

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

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/samob:/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.

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

A sample backup file is available:

  • Store backups in multiple locations
  • Schedule automated backups with cron
  • Test restore procedure before you need it
  • Keep encryption key in password manager