Dokku: Set Up Postgres Backups To Hetzner S3

If you’re using dokku for your deployments (it’s awesome) and were wondering how to set up automatic backups of your dokku postgres instances to Hetzner S3, here’s how you do it.

TLDR

dokku postgres:backup-auth <dokku_postgres_service_name>  <hetzner_s3_access_key> <hetzner_s3_secret_key> <hetzner_s3_region> s3v4 https://<hetzner_s3_region>.your-objectstorage.com

Example

In this example, we’re assuming that we’ve created out Hetzner S3 bucket for dokku backups in the Falkenstein region, fsn-1.

dokku postgres:backup-auth mypg <hetzner_s3_id> <hetzner_s3_key> fsn1 s3v4 https://fsn1.your-objectstorage.com

Test the setup by running a one-time backup

Note that we didn’t specify the bucket name so far in the backup-auth call above. Instead, you only specify the bucket name when actually doing the backup or when scheduling it (see further below). Here, we run a one-time backup of the mypg service to the S3 bucket my-hetzner-bucket-name.

dokku postgres:backup mypg my-hetzner-bucket-name

Schedule backups

Here, we’re scheduling backups to happen daily at 03:00 am to the bucket my-hetzner-bucket-name

dokku postgres:backup-schedule mypg "0 3 * * *" my-hetzner-bucket-name

Longer Explanation

There aren’t many articles out there on how to set up postgres backups in dokku, and when I asked ChatGPT, it got it surprisingly wrong. So here’s how it works.

First, you have to call postgres:backup-auth (see command above). The idea here is that you link one set of S3 credentials to one dokku postgres service. In other words, you have to configure this for each of your dokku postgres instances. Generally speaking, I would assume that the best practice here is to create a separate bucket for each of your dokku postgres instances, because otherwise you’d have some pretty interesting risks if you throw all your backups in one bucket (if it goes down, all your backups are gone; if you misconfigure something, all your backups are gone, too, etc.).

postgres:backup-auth is called with the following parameters:

  • The name of your dokku postgres instance / service (you can call dokku postgres:list to view all)
  • Your Hetzner S3 access key (the clear-text “login” key you get when creating S3 credentials in the Hetzner dashboard)
  • Your Hetzner S3 secret key (the “password” key you get when creating S3 credentials in the Hetzner dashboard)
  • Your Hetzner S3 region – the region you selected when creating your Hetzner S3 bucket. Current regions available are Falkenstein (fsn1), Nuremberg (nbg1) and Helsinki (hel1).
  • The signature version to use when making S3 requests. Use s3v4 as a value here. Hetzner specifies they support “version 4”, but it was a bit tricky to find out that this translates to the value s3v4 for dokku (or rather, the AWS CLI).
  • The endpoint of your bucket. This is https://<hetzner_s3_region>.your-objectstorage.com, e.g. https://fsn1.your-objectstorage.com.

Next, you run a one-time backup with dokku postgres:backup mypg my-hetzner-bucket-name while observing the Hetzner S3 bucket content (files) in the Hetzner dashboard. You should see a backup file appear there shortly (refresh).

Finally, you should schedule recurring backups by calling dokku postgres:schedule (full command above). This should be pretty self-explanatory, the format for scheduling is the typical cron-style string. Ask ChatGPT to explain it to you 🙂

The somewhat important point here is that it’s a bit counter-intuitive that you only specify your S3 bucket name when either 1) running a one-time backup or 2) scheduling recurring backups. I would have expected to specify the bucket name when already calling backup-auth, but maybe that’s just me.

Hope this helps, and good luck setting up your backups!

If you haven’t yet, check out Hetzner S3 and dokku, both are awesome in different ways. And consider donating to dokku, the project is mostly being run by one very nice dude.

You might also be interested in my post on using Hetzner S3 with Rails.

Leave a Reply

Your email address will not be published. Required fields are marked *