Backups
Dump a self-hosted Doska's database and attachments with backup.sh, and restore them into an empty stack.
Backup works with database and files in the local folder, if you have s3 setup and/or managed separate database, this guide doesn't apply.
Run backup.sh from your Doska directory any time:
./backup.shinstall.sh downloads it for you. If you set the stack up by hand, fetch it
first:
curl -O https://raw.githubusercontent.com/romenkova/doska/main/backup.sh
chmod +x backup.shIt writes two files to ./backups/, both stamped with the same timestamp:
| File | What's in it |
|---|---|
doska-<stamp>.sql.gz | The bundled Postgres. |
doska-files-<stamp>.tar.gz | Card attachments, from the files volume. |
install.sh runs this for you before it redeploys over an existing database.
Restoring
Database
Restore the database into an empty one, with only db running. A booted
server has already migrated the schema and seeded the admin account, and the
dump would land on tables and rows that already exist:
docker compose -f docker-compose.selfhost.yml down --volumes
docker compose -f docker-compose.selfhost.yml up -d --wait db
gunzip -c backups/doska-XXXX.sql.gz | \
docker compose -f docker-compose.selfhost.yml exec -T db \
psql -v ON_ERROR_STOP=1 -U doska doskaKeep
ON_ERROR_STOP=1. Without itpsqlexits 0 even when every statement failed. Restoring onto a database that isn't empty prints a wall of errors and still looks like it succeeded.
Attachments
Put the attachments back into the recreated volume, before the server starts:
docker compose -f docker-compose.selfhost.yml up -d --no-start server
gunzip -c backups/doska-files-XXXX.tar.gz | \
docker run --rm -i -v <project>_doska-files:/data alpine tar xf - -C /data
docker compose -f docker-compose.selfhost.yml up -d<project> is the compose project name, by default the lowercased name of the
directory you run from (with anything outside a-z0-9_- dropped, and any
leading - or _ stripped), or COMPOSE_PROJECT_NAME if you set one.
docker compose config | head -1 prints the one in effect.
Restore both halves from the same timestamp. The database holds the rows that name the files, so a mismatched pair leaves cards pointing at blobs that aren't there.
What the script does
- Checks that
dockerand eitherdocker composeordocker-composeare available, and thatdocker-compose.selfhost.ymlsits in the current directory, otherwise you are not in your Doska directory and it stops. - Works out the compose project name (
COMPOSE_PROJECT_NAME, or the lowercased name of the directory, normalised the way compose normalises it), that is the prefix on the volumes. - Creates
./backups/and takes one timestamp, shared by both files. - Database. Skipped if
.envsetsDATABASE_URL(yours to back up through your provider), or if thedoska-pgdatavolume doesn't exist yet. Otherwise it starts thedbservice, waits up to 30s forpg_isready, and runspg_dumpinto a temp file before gzipping it tobackups/doska-<stamp>.sql.gz. Ifpg_dumpfails, nothing is written. - Attachments. Skipped if there is no
doska-filesvolume. Otherwise a throwawayalpinecontainer mounts the volume read-only and tars it tobackups/doska-files-<stamp>.tar.gz.