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.
Short answer: workflow JSON files alone are not enough. They do not recreate the complete instance state, and encrypted credentials are unusable without the key that encrypted them.
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 the 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 when filesystem or external storage is used | 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 before writing the runbook
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. For the standard Docker volume shown in n8n's installation guide, a generic sequence looks like this:
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
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. Adapt the connection values and run the tool from a host or database container that can reach PostgreSQL:
pg_dump --format=custom --file=n8n-2026-07-18.dump n8n
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, and can be included explicitly when your retention requirement needs them.
docker exec -u node n8n \ n8n export:entities \ --outputDir=/home/node/.n8n/cli-backup
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/
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. If that exceptional path is necessary, isolate, encrypt, restrict, and delete the files after the migration.
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.
- Record the target. Use the same n8n version first, the same database type, and compatible custom-node versions. Upgrade only after the restored instance works.
- Create fresh infrastructure. Prepare a new Docker volume or empty PostgreSQL database rather than clearing production.
- Restore the original encryption key. Put the protected
N8N_ENCRYPTION_KEYor original n8n settings in place before n8n reads the restored credentials. - Restore the database. Extract the stopped SQLite volume archive into the new volume, or restore the PostgreSQL dump into the new database.
- Restore the surrounding state. Reapply deployment settings, binary storage, custom nodes, public URL settings, and reverse-proxy configuration.
- Start without production traffic. Keep DNS, proxy routing, and outbound side effects isolated while checking startup and migration logs.
- Verify the application. Confirm login, projects, workflows, credentials, node availability, execution history required by policy, and binary files that should still exist.
- Run one safe test. Use test credentials or a non-destructive workflow and confirm that a credential can decrypt and authenticate.
- Publish deliberately. Review which workflows should be published before switching traffic. Imported workflows can have different active-state behavior depending on the import path and deployment mode.
Restore a SQLite archive into a new volume
A new volume keeps the original recoverable while you inspect the restore. This example extracts the archive created above without deleting the production 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
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
Real deployments may need explicit host, user, role, ownership, TLS, and schema options. Test the exact command your operator will use and document it beside the backup job 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 | Users, projects, settings, retained executions, and complete credential state are not restored as one instance |
| 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 | Execution records may exist while retained documents or images are missing |
| Restoring straight over production | A bad archive or wrong configuration can remove the working recovery path |
| Never testing the restore | Missing keys, permissions, node packages, and undocumented steps appear during the incident |
Common questions
Where does Docker store self-hosted n8n data?
n8n's standard Docker example mounts a named n8n_data volume at /home/node/.n8n. Your Compose file may use a different volume or bind mount, so inspect the deployment rather than assuming the example name.
Does exporting workflows back up credentials?
Not by itself. n8n provides separate workflow and credential export commands, plus the broader export:entities command. For same-instance disaster recovery, the database, original encryption key, config, and storage remain the stronger complete backup set.
Can I restore into a newer n8n version?
Restore the recorded version first when possible. This separates backup problems from application migrations. After the restored instance passes its checks, read the intervening release notes, take another backup, and perform the upgrade as a separate controlled change.
Sources checked
- n8n Docker persistence and PostgreSQL guidance
- n8n supported databases and SQLite location
- n8n encryption-key behavior
- n8n Server CLI export and import commands
- n8n binary-data storage modes
- PostgreSQL SQL dump documentation
- SQLite online backup documentation
n8n partner link
Prefer a managed recovery path?
I may earn a commission if you sign up through this link, at no extra cost to you.
Need the recovery path documented?
Send the database type, deployment shape, storage locations, and recovery target. I will help map a backup set and an isolated restore test without exposing production secrets.
Map the restore