Data and backups
All of your instance's state is in one place, which makes both backup and recovery a file operation. The routine backup commands are in Operating. This page is the recovery side and the one mistake that can't be undone.
Where the data is
Everything lives under ./data/ next to your compose file, one folder per
service:
-
data/dbis the databases (the platform database plus one per workspace). -
data/filesis uploads and images. -
data/backupsis the nightly database dumps the stack writes for you. -
data/caddyis issued certificates. -
data/modulesis installed module code. -
A copy of
./data/taken while the stack is stopped is a full backup. No named volumes, so moving to a new disk is onersync. -
Never copy
data/dbwhile Postgres is running. That produces a torn snapshot that may not restore. On a live instance, back up with the nightly dumps instead (below), or stop the stack first.
Restoring the whole instance
From a folder copy, restore is the reverse of backup: bring the stack down, put the tree back, bring it up.
docker compose down
mv data data.broken-$(date +%F) # keep the old tree until the restore is proven
cp -a /path/to/backup/data ./data
docker compose up -d
- Only delete
data.broken-*after you have logged in and seen your records. If the backup path was wrong or the copy failed, that directory is still your instance. - Restore the
.envanddocker-compose.ymlfrom the same backup too, so the config matches the data. In particular the.envyou restore must carry the sameTENANT_CREDS_ENCRYPTION_KEYthe data was encrypted with (see below).
Restoring from a database dump
Your backup is a SQL dump (one of the stack's nightly files under
data/backups/daily/, or a hand-run pg_dumpall) rather than a folder copy.
Restore it into an empty database directory with the app stopped:
docker compose stop api web
mv data/db data/db.broken-$(date +%F)
docker compose up -d db # a fresh, empty Postgres
sleep 10
gunzip -c data/backups/daily/cobblr-<stamp>.sql.gz \
| docker compose exec -T db psql -U cobblr -d cobblr_meta
docker compose up -d
- A dump restores the databases but not uploaded files or certificates. The folder copy is the complete one.
- Keep
data/db.broken-*until you have logged in and seen your records.
Why empty and stopped
An empty directory with the app stopped means nothing is writing mid-restore and nothing collides with objects that already exist.
The encryption key
Losing TENANT_CREDS_ENCRYPTION_KEY is unrecoverable.
- Keep a copy of the key somewhere off this box: a password manager, or an encrypted note. Store it wherever you keep the recovery material for anything else you couldn't rebuild.
- When you restore, restore the
.envthat goes with the data, so the key comes along.
What the key protects and what happens without it
TENANT_CREDS_ENCRYPTION_KEY encrypts the per-workspace credentials Cobblr
stores (the keys and tokens you enter for integrations and connected services).
It is derived into an AES-256 key and used to encrypt those values at rest.
If you change the key, or restore a database without the matching key, every stored credential becomes undecryptable ciphertext. The data isn't corrupted and the rest of the instance runs, but each affected integration has to be reconnected with its secret re-entered.
The reasoning and the operator-side discipline for this key are in Secrets and keys.
A backup didn't run
data/backups is empty or stale.
- Check the container:
docker compose ps backupanddocker compose logs backup. - The usual causes are a
.envmissingPOSTGRES_PASSWORDchanges, or a full disk.
- What the stack does on its own: the
backupcontainer writesdata/backups/daily/cobblr-<stamp>.sql.gzonce a day, keeps a weekly copy on Sundays, and prunes to 30 daily and 12 weekly files (retention is configurable). - A dump smaller than a sanity floor is treated as failed rather than kept, because an empty "successful" dump is worse than none.
- The nightly dump lives on the same disk as the instance, so it survives a bad upgrade but not a dead drive. Copy it off the box on a schedule, which is the part you still own: see Backups and restore tests.
- For restorable snapshots of a single workspace, and off-box destinations like Google Drive, use the in-app tools in Backup and export. Those are separate from the whole-instance folder copy: one is a workspace's own data on demand, the other is everything on the box.