Guide
Dokploy Postgres backups, done properly
Dokploy has scheduled database backups to S3 built in. Here's the setup, the traps, and the restore test that turns a dump in a bucket into an actual backup.
Setup
- Destination: in Dokploy, add an S3 destination (Settings → S3 Destinations). Any S3-compatible store works — Backblaze B2, Cloudflare R2, Wasabi, MinIO. Scope the access key to one bucket.
- Schedule: open your Postgres service → Backups → create a backup with a cron expression (
0 3 * * *for nightly), the destination, and a retention count. - Trigger one manually and check the object appears in the bucket before trusting the schedule.
The traps
- Backups on the same VPS are not backups. If the disk dies, the database and its "backups" die together. The S3 destination must be off the box.
- Retention is a file count. Keep-7 on an hourly schedule is 7 hours of history, not 7 days.
- Client-version drift: the dump is made with the tools inside the container. Restoring years later with older system tools fails with a header error — details and fix.
- Extra roles aren't in a single-database dump; export them once with
pg_dumpall --roles-onlyif you've created any.
Restore-test it tonight
docker run -d --name drill -e POSTGRES_PASSWORD=drill -p 5499:5432 postgres:16
pg_restore --no-owner -h localhost -p 5499 -U postgres -d postgres latest.dump
psql -h localhost -p 5499 -U postgres -c \
"SELECT relname, n_live_tup FROM pg_stat_user_tables ORDER BY n_live_tup DESC LIMIT 10;"
docker rm -f drill
Complete methodology with manifest counts and FK validation: the 5-step drill.
The drill, automated, on your own VPS
pgProof's agent is one container beside Dokploy: dumps on schedule, encrypts locally, pushes to your bucket, restore-tests every backup and emails you the proof. Your credentials never leave your server.
Join the early-access waitlist