Backups
Back up your NocoDB instance: Postgres data, attachments, and config.
Back up three things to fully protect your NocoDB instance: the Postgres database (your data and metadata), the attachments volume (uploaded files), and your config files (so you can rebuild the stack quickly).
What to back up
| Item | Where it lives | Why |
|---|---|---|
| Postgres database | Bundled: postgres_data named volume / External: your DB host | Contains all your bases, tables, rows, users, comments |
| Attachments | nocodb_data named volume (mounted at /usr/app/data) | Files users uploaded to attachment fields |
| Configuration | docker-compose.yml, docker.env, nocodb/db.json | Lets you rebuild the same stack on a fresh server |
Named volumes persist across restarts and docker compose down. But a volume on the same host is not a backup. Always copy database dumps and attachment archives off the server.
Bundled Postgres
If you used --pg=bundled (or the Quickstart compose), back up the database container with pg_dump:
cd nocodb # your deployment directory
docker compose exec db pg_dump -U nocodb nocodb > backup-$(date +%Y%m%d).sqlRestore on a fresh stack:
cat backup-20260509.sql | docker compose exec -T db psql -U nocodb nocodbSchedule daily backups with cron:
# /etc/cron.d/nocodb-backup
0 3 * * * root cd /opt/nocodb && docker compose exec -T db pg_dump -U nocodb nocodb | gzip > /backups/nocodb-$(date +\%Y\%m\%d).sql.gzExternal (managed) Postgres
If you're using RDS, Cloud SQL, Azure Database, or another managed service, use the provider's snapshot/backup mechanism. Managed providers handle this far better than pg_dump:
- AWS RDS: Automated backups (recommended) + manual snapshots before major upgrades.
- Google Cloud SQL: Automated backups and on-demand backups.
- Azure Database for PostgreSQL: Backup and restore.
For self-managed external Postgres, run pg_dump from a host that can reach your DB.
Attachments
If your NocoDB stores attachments on the local filesystem (default), they live in the nocodb_data named volume. Compose prefixes volume names with the deployment directory, so confirm the real name first:
docker volume ls | grep _nocodb_data # e.g. nocodb_nocodb_dataBack it up with a throwaway helper container that mounts the volume read-only:
docker run --rm \
-v nocodb_nocodb_data:/data:ro \
-v "$(pwd)":/backup \
alpine tar -czf /backup/attachments-$(date +%Y%m%d).tar.gz -C /data .If you've configured S3-compatible object storage (NC_S3_* env vars), your attachments live in that bucket rather than the nocodb_data volume, so the volume backup above doesn't apply. Back up the bucket instead, using your storage provider's tools: enable bucket versioning, lifecycle or cross-region replication rules, or scheduled bucket snapshots.
Config files
Track these three files in version control:
docker-compose.yml
docker.env
nocodb/db.jsonIf your server is destroyed, restoring is: provision new server → install Docker → git clone your config repo → docker compose up -d → restore Postgres dump → restore attachments tarball.
Don't commit secrets. docker.env and nocodb/db.json contain credentials. Use a private repo, encrypt with git-crypt or sops, or store secrets separately and template the files at deploy time.
Restoring on a new server
- Provision a fresh Linux VM with Docker.
- Run the Single-server install with the same domain settings.
- Stop NocoDB so the database is idle:
docker compose stop nocodb worker. - Restore Postgres:
cat backup.sql | docker compose exec -T db psql -U nocodb nocodb. - Restore attachments into the volume:
docker run --rm -v nocodb_nocodb_data:/data -v "$(pwd)":/backup alpine tar -xzf /backup/attachments.tar.gz -C /data. - Restart:
docker compose start nocodb worker.
Recovery time scales with the size of your database dump and attachments; a small instance restores in minutes.