Backups and restore
Back up a self-hosted Nodaro with one command, restore it with another and downgrade safely. Learn what the archive holds and how to protect its key.
A self-hosted Nodaro is backed up with one command and restored with another. The backup archive holds everything the stack cannot regenerate: the database, your media, the instance encryption key and your .env. The restore is also the only way to downgrade, because the database migrations only move forward. Returning to an earlier version means restoring the backup you took before the update.
What a backup contains
tools/community-backup.sh writes one tar.gz archive:
| In the archive | What it is |
|---|---|
db.dump | Postgres, in pg_dump's custom format: workflows, users, jobs and media records |
minio-data.tar | Your generated media: images, videos and audio |
encryption-key | The instance key that encrypts provider keys and social sign-in tokens. A database restored without it holds rows nobody can read. |
env | Your .env: provider keys and secrets |
manifest.json | The app version and the time of the backup, for the restore script |
Redis is left out on purpose: it holds only short-lived job state.
The archive is a credential
It contains your .env and the encryption key. The script restricts the file to its owner (chmod 600). Keep it that way, and store the archive like a password. On Windows, chmod has no real effect: keep the file out of synced folders and shared drives, and restrict it with NTFS permissions if other people use the computer.
Take a backup
From your install directory, where docker-compose.community.yml is, with the stack running:
tools/community-backup.sh
# -> ./backups/nodaro-backup-<date>-v<version>.tar.gz| Option | What it does |
|---|---|
tools/community-backup.sh /path/to/backups | Writes the archive to another directory |
COMPOSE_FILE=my-compose.yml tools/community-backup.sh | Uses a compose file with another name |
The script prints what went into the archive. If the encryption key is missing, it says so loudly and exits with an error, so a scheduled job notices. That archive cannot restore your provider keys.
The database dump is always consistent. Media written while the backup runs may miss the archive. For a guaranteed-consistent media snapshot, stop the app first:
docker compose -f docker-compose.community.yml stop nodaroOn Windows, run the scripts from Git Bash, the shell that Git for Windows installs. PowerShell and the bash of WSL break the container paths.
When to back up
Before every major version update, where the first number changes, and on whatever schedule your data deserves. A cron line works as it is:
0 3 * * * cd /path/to/install && tools/community-backup.sh >> backup.log 2>&1Restore a backup
tools/community-restore.sh backups/nodaro-backup-<date>-v<version>.tar.gzThe restore replaces the database and the media with the archive's contents, so it asks you to type RESTORE before it touches anything. Then it:
- Stops the app and the database clients,
authandrest, because their open connections would block the restore. - Restores Postgres and checks that it works, instead of trusting exit codes. Some harmless messages from the Supabase image are expected and printed.
- Restores the media and checks that the buckets are back and MinIO is healthy. Then it restores the encryption key and checks its size on the volume. Then it restores your
.env, after saving any existing.envaside. A failed check stops the script before the app starts: starting without the right key would create a new one and make every restored provider key unreadable for good. - Starts everything again and waits for the app's own health check. The script reports success only once the app is up, and exits with an error otherwise.
When it finishes, open http://localhost:3000/setup. Every card should be green.
Downgrade a version
There is no migration rollback. To return to an earlier version:
- Restore the backup taken before the update, as above.
- Pin the older image, for example
ghcr.io/nodaroai/nodaro-community:v1.25.1, inNODARO_IMAGEor indocker-compose.community.yml. ExactvX.Y.Ztags never move. - Run
docker compose -f docker-compose.community.yml up -d nodaro.
See Updating for the tags.
Back up a managed deployment
Outside the compose stack, four things hold state:
| What | How to protect it |
|---|---|
| Supabase Postgres: workflows, profiles, jobs and media records | Use Supabase's point-in-time recovery, on paid plans, or run pg_dump regularly. This is the backup that matters most. |
| The storage bucket: generated images, videos and audio | Enable bucket versioning and a long lifecycle rule so deleted files can be recovered. Add cross-region replication for disaster recovery if you need it. |
| Redis | Nothing to back up. It holds only short-lived job state. If you lose it, runs in progress fail, and everything else recovers from Postgres on the next start. |
The instance encryption key, NODARO_ENCRYPTION_KEY | Keep it with the Postgres backups. Without it, the restored rows of provider keys, social sign-in tokens and Webhook Output credentials cannot be read. The tiles then show missing and the keys must be entered again; nothing else breaks. |
If Postgres is down during a migration or a recovery, the API restarts in a loop until it can reach the database. Once Postgres is back, restart the Nodaro container.
Troubleshooting
the db service is not running. Start the stack first:docker compose -f docker-compose.community.yml up -d.- Provider keys show
missingafter a restore. The database was restored without its matchingencryption-key, or with a different one. Restore from an archive that has the key, or enter the keys again on/setup. - Restore verification failed. The script refuses to leave a half-restored database silently. Run the restore again. If it fails repeatedly, the archive may be truncated: compare its size with the original.
could not read the encryption keyduring a backup on Windows. You are not in Git Bash, or the app container is not running. Run the backup again from Git Bash with the stack up. The archive the script warned about is not a usable backup.media restore verification FAILEDorencryption key verification FAILED. The script stopped on purpose and did not start the app. Check the volume it names, fix the cause, usually a stopped container or a full disk, and run the restore again. It is safe to repeat.
Frequently asked questions
Related
Updating
Database
Provider keys
Troubleshooting
Last updated on
Scaling
Scale a self-hosted Nodaro beyond one container. Split the API, media workers, render workers and orchestrator, and tune concurrency, Redis and storage.
Troubleshooting
Fix common problems of a self-hosted Nodaro, starting at /setup. Symptoms and fixes for startup errors, ports, CORS, migrations, storage, queues and keys.