# Update and back up a self-hosted n8n

> Back up everything a self-hosted n8n needs to recover, including the encryption key, and update n8n safely with Docker.

Source: https://viralistic.nl/help/n8n/self-hosting-maintenance

Running n8n yourself means you own two jobs that n8n Cloud does for you: backups and updates. Both are simple once you have a routine. This article is for whoever looks after a self-hosted instance running in Docker. If that is nobody yet, decide who it is before you put important workflows on it.

## What a complete backup contains

| Part                | Where it lives                                     | Why it matters                                                    |
| ------------------- | -------------------------------------------------- | ----------------------------------------------------------------- |
| The `.n8n` folder   | The Docker volume mounted at `/home/node/.n8n`     | Holds the encryption key, and with SQLite also the whole database |
| PostgreSQL database | Your database server, if you use one               | Workflows, credentials, users, executions                         |
| Configuration       | Your `compose.yml`, `.env` or `docker run` command | Database settings, `WEBHOOK_URL`, custom encryption key           |
| Custom nodes        | Folders you configured for custom nodes            | Workflows that use them break without them                        |

> **Warning:** Credentials are encrypted with the key in the `.n8n` folder (or in `N8N_ENCRYPTION_KEY`). A database backup without that key is useless for credentials. Store the key safely, separate from the server.

## Back up the Docker volume

With the default SQLite database, stop n8n first, so the database file is not copied halfway through a write.

1. Find your volume name:

   ```bash
   docker volume ls
   ```

2. Stop n8n, archive the volume, and start n8n again:

   ```bash
   docker stop n8n
   docker run --rm -v n8n_data:/data -v "$PWD":/backup alpine \
     tar czf /backup/n8n-data-$(date +%F).tar.gz -C /data .
   docker start n8n
   ```

   With Docker Compose, use `docker compose stop` and `docker compose start` instead, and your own volume name.

3. If you use PostgreSQL, also make a dump with `pg_dump` using your database's own backup tooling.
4. Copy the backup files off the server, for example to object storage.

## Export workflows and credentials as files

For an extra, readable copy, export workflows and credentials with the n8n command line. This example writes into the volume, so the files survive container restarts:

```bash
docker exec -u node n8n n8n export:workflow --backup --output=/home/node/.n8n/backups/workflows/
docker exec -u node n8n n8n export:credentials --backup --output=/home/node/.n8n/backups/credentials/
```

These exports are handy to move workflows to another instance. They do not include users, execution history, variables or settings, so they do not replace the full backup above.

## Test your restore

A backup you never restored is a hope, not a backup. Once per quarter:

1. Start a fresh n8n container on a test machine.
2. Restore the volume archive (and database dump) into it.
3. Open n8n, check that workflows are there and that a credential still connects.

## Update n8n safely

### Before you update

1. Read the release notes for every version between yours and the target, on the [n8n releases page](https://github.com/n8n-io/n8n/releases). Pay attention to breaking changes in major versions.
2. Make a full backup.
3. Pick a quiet moment. Workflows do not run while n8n restarts.

> **Note:** n8n 3.0 requires Docker for self-hosted installs and no longer supports running n8n with npm. Before a major upgrade, read n8n's breaking changes page for that version and check the migration report in your instance settings.

### Pin a version

Use a specific version tag instead of `latest`, such as `n8nio/n8n:<version>`. Then you decide when to upgrade, and you know exactly which version to go back to.

### Update with Docker Compose

1. Change the version in your `compose.yml` or `.env`.
2. Pull and restart:

   ```bash
   docker compose pull
   docker compose up -d
   ```

If you used the one-line installer, rerun it with the upgrade flag: `curl -fsSL https://get.n8n.io | sh -s -- --upgrade`.

### Update a plain docker run setup

1. Pull the new image: `docker pull n8nio/n8n:<version>`.
2. Stop and remove the old container: `docker stop n8n` and `docker rm n8n`. Your data stays in the volume.
3. Start it again with your usual `docker run` command and the new tag.

### After the update

1. Log in and confirm the new version number.
2. Open the Executions overview and watch the next scheduled and webhook runs.
3. Check that triggers are still active, especially email and app triggers.

If something is badly wrong, go back to the previous image tag and restore your backup. Updates can migrate the database, so going back to an older version usually means restoring the backup as well.

## A maintenance routine

| How often | Task                                                             |
| --------- | ---------------------------------------------------------------- |
| Daily     | Automatic backup of volume and database, copied off the server   |
| Monthly   | Update to the latest stable version, after reading release notes |
| Quarterly | Test a restore, review users and unused credentials              |

If you would rather have us host and maintain your instance, book a strategic call: https://calendly.com/marrallisa/30min

## Next steps

- [Get n8n: cloud or self-hosted](https://viralistic.nl/help/n8n/get-n8n)
- [Error handling and alerts](https://viralistic.nl/help/n8n/error-handling)
- [Connect your apps with credentials](https://viralistic.nl/help/n8n/credentials)
