Database backup¶
We use greenmask as a separate service for creating and restoring PostgreSQL backups. Backups are stored in S3-compatible object storage (Cloudflare R2).
Available commands¶
All backup-related tasks live under the prod.db.* namespace:
| Command | Description |
|---|---|
prod.db.backup |
Create a backup of the current database |
prod.db.backup.list |
List available backups |
prod.db.backup.clean |
Delete all but the 7 most recent backups |
prod.db.restore.latest |
Restore the most recent backup |
Requirements¶
The following environment variables must be set in .env for backup and restore commands to work:
# S3-compatible object storage (e.g. Cloudflare R2)
AWS_S3_ENDPOINT=https://uuid.r2.cloudflarestorage.com
AWS_S3_BUCKET=bucket
AWS_S3_REGION=us-east-1
AWS_S3_PREFIX=backups
AWS_S3_ACCESS_KEY_ID=uuid
AWS_S3_SECRET_ACCESS_KEY=uuid4
AWS_S3_FORCE_PATH_STYLE=true
# PostgreSQL connection
PGDATABASE=databasename
PGHOST=db
PGUSER=database_user
PGPASSWORD=password
Scheduling backups¶
Backups are scheduled via crontab on the production host.
Automated setup¶
From the project root, run:
This auto-detects the project directory and task binary path and installs the cron entries. It's idempotent — safe to run multiple times.
Manual setup¶
- Find the absolute path to the
taskbinary:
For example, on a snap install this will be /snap/bin/task.
- Add the following entries to the crontab (
crontab -e), adjusting the project path andtaskbinary path as needed:
# Daily backup at 02:00
0 2 * * * cd /home/appuser/project-name && /usr/local/bin/task prod.db.backup >> /home/appuser/db-backup.log 2>&1
# Daily cleanup at 03:00 (keeps the 7 most recent backups)
0 3 * * * cd /home/appuser/project-name && /usr/local/bin/task prod.db.backup.clean >> /home/appuser/db-backup.log 2>&1
Note: Each deployment also triggers a backup before the deployment starts, which is handled in the deployment scripts. Note: Production environments also have full VM snapshot backups via Hetzner, which provides 7 daily backup slots.