DEV Community

Cover image for How to Back Up and Restore Self-Hosted n8n
Stepan Nikonov
Stepan Nikonov

Posted on Originally published at floxolab.com

How to Back Up and Restore Self-Hosted n8n

A workflow export is not a full instance backup. Protect the database, encryption key, deployment configuration, and binary storage, then prove that they work together on an isolated restore.

A recoverable self-hosted n8n backup has four core parts: the database, the original encryption key, the deployment configuration and secrets, and any binary-data storage your executions still need.

Back up the persistent .n8n volume even when PostgreSQL stores the main database. n8n documents that this directory can still contain the encryption key, logs, and source-control assets.

What must be in the backup

Asset Why it matters Typical location
Database Workflows, encrypted credentials, users, projects, settings, and retained execution data ~/.n8n/database.sqlite or PostgreSQL
Encryption key Decrypts credentials stored in the database ~/.n8n settings or N8N_ENCRYPTION_KEY
Deployment config Restores database connection, public URL, proxy, timezone, pruning, and execution behavior Compose file, environment settings, secret references, proxy config
Binary data Restores retained files handled by executions Persistent filesystem, database, or configured external store
Custom and community nodes Allows restored workflows to load the same node types and versions Package list, custom-node directory, container image, or build manifest

Do not put the raw encryption key, database password, OAuth secrets, or an unredacted environment file in a public repository. Keep a sanitized deployment definition in version control and protect the actual secrets in a restricted password manager, secret store, or encrypted backup.

Choose the database path first

Self-hosted n8n uses SQLite by default. The database file is ~/.n8n/database.sqlite. PostgreSQL is the other supported database option. The backup and restore commands must match the database your instance actually uses.

SQLite: capture a consistent persistent volume

The simplest small-instance method is a short maintenance window: stop the n8n application, archive its persistent volume, then start it again. Stopping writes avoids treating an arbitrary live file copy as a consistent database backup.

docker compose stop n8n
docker run --rm \
  -v n8n_data:/data:ro \
  -v "$PWD/backups:/backup" \
  alpine tar czf /backup/n8n-data-2026-07-18.tgz -C /data .
docker compose start n8n
Enter fullscreen mode Exit fullscreen mode

Replace the service and volume names with the names in your deployment. If downtime is not acceptable, use a storage snapshot or SQLite-aware backup process that guarantees a consistent result. Do not assume that copying database.sqlite while executions are writing to it is safe.

PostgreSQL: use a database dump

PostgreSQL's official documentation recommends pg_dump for logical backups. A custom-format dump works with pg_restore and is practical for restoring into a fresh database:

pg_dump --format=custom --file=n8n-2026-07-18.dump n8n
Enter fullscreen mode Exit fullscreen mode

The dump does not replace the n8n persistent volume or explicit encryption key. It also does not capture the Compose file, environment settings, proxy configuration, or filesystem binary data. Store those as separate parts of the same dated backup set.

Add native n8n exports as a second recovery layer

n8n's Server CLI can export all database entity types. Its documentation positions this tooling for backups and migrations, including moves between SQLite and PostgreSQL. Execution-history data tables are excluded by default because they can be large.

docker exec -u node n8n \
  n8n export:entities \
  --outputDir=/home/node/.n8n/cli-backup
Enter fullscreen mode Exit fullscreen mode

Workflow and credential exports are also useful for selective recovery or versioned copies:

n8n export:workflow --backup --output=backups/workflows/
n8n export:credentials --backup --output=backups/credentials/
Enter fullscreen mode Exit fullscreen mode

Avoid decrypted credential exports for routine backups. n8n supports a --decrypted flag for migrations to a different secret key, but the resulting files expose every sensitive value in plain text.

A safe restore runbook

First restore into an isolated instance with no production webhooks, schedules, email sends, payment calls, or CRM writes. The first recovery test should never overwrite the only production copy.

  1. Record the target. Use the same n8n version first, the same database type, and compatible custom-node versions.
  2. Create fresh infrastructure. Prepare a new Docker volume or empty PostgreSQL database rather than clearing production.
  3. Restore the original encryption key. Put the protected N8N_ENCRYPTION_KEY or original n8n settings in place before n8n reads the restored credentials.
  4. Restore the database. Extract the stopped SQLite volume archive into the new volume, or restore the PostgreSQL dump into the new database.
  5. Restore the surrounding state. Reapply deployment settings, binary storage, custom nodes, public URL settings, and reverse-proxy configuration.
  6. Start without production traffic. Keep DNS, proxy routing, and outbound side effects isolated while checking startup and migration logs.
  7. Verify the application. Confirm login, projects, workflows, credentials, node availability, required execution history, and retained binary files.
  8. Run one safe test. Use test credentials or a non-destructive workflow and confirm that a credential can decrypt and authenticate.
  9. Publish deliberately. Review which workflows should be published before switching traffic.

Restore SQLite into a new volume

docker volume create n8n_restore_data
docker run --rm \
  -v n8n_restore_data:/data \
  -v "$PWD/backups:/backup:ro" \
  alpine tar xzf /backup/n8n-data-2026-07-18.tgz -C /data
Enter fullscreen mode Exit fullscreen mode

Point a separate restore Compose file at n8n_restore_data. Do not bind it to the production hostname or webhook route until the checklist passes.

Restore PostgreSQL into a fresh database

createdb n8n_restore
pg_restore --dbname=n8n_restore n8n-2026-07-18.dump
Enter fullscreen mode Exit fullscreen mode

Real deployments may need explicit host, user, role, ownership, TLS, and schema options. Test the exact command your operator will use and document it without embedding the password.

Restore-test checklist

  • The backup job has a timestamp, size, success state, and failure alert.
  • The database and encryption key come from the same recoverable setup.
  • The restore starts on a separate hostname, volume, and database.
  • Credential nodes open without decryption errors and one test authentication succeeds.
  • Required custom or community nodes load at the expected versions.
  • Published workflows, schedules, and webhook paths are reviewed before traffic moves.
  • Required retained binary files can be opened.
  • The restore time and missing manual steps are recorded for the next test.

Common backup failures

Mistake What breaks during recovery
Only exporting workflow JSON The complete instance state is not restored
Database without the original key Credentials remain encrypted but cannot be used
Copying a live SQLite file casually The backup may not represent one consistent database state
Skipping binary storage Retained documents or images may be missing
Restoring straight over production A bad archive or wrong config can remove the working recovery path
Never testing the restore Missing keys, permissions, packages, and manual steps appear during the incident

Sources


Originally published on FloxoLab.

Top comments (0)