Skip to content

Database Backups

You can back up your databases managed by Appliku through the dashboard. Backups can be stored on the server or uploaded to S3-compatible storage.

Cluster vs. Standalone Backups

Backups for standalone datastores run a one-shot container on the chosen backup server, attached to the local applications Docker network. The backup server must be the same server that hosts the datastore when the connection mode is private_connection_url.

Backups for cluster-deployed datastores run a one-shot container attached to the cluster's proxy overlay network, so they can run on any active, set-up server in the same cluster — not necessarily the DB-pinned node. The backup server selector is validated to enforce this. Local backup artifacts and S3 uploads still happen on whichever server runs the cron job, so changing the backup server reschedules the cron on the new server and removes the stale cron entry from the previous one.

How to Back Up a PostgreSQL Database

  1. Open the Appliku dashboard
  2. Go to your application that has a database
  3. Click on the "Manage" link in the "Databases" card:

Manage databases link

  1. Pick your database
  2. Click on the "Add backup" link:

Add backup link

  1. Specify parameters for the backup:

Backup form - schedule

Backup form - S3 settings

Available schedule intervals range from every 30 minutes to daily. For object storage, pick one of the supported providers and supply the credentials for it: most settings (including the endpoint URL) are filled in for you.

Object Storage Providers

When you choose Object Storage (S3-compatible) as the backup target, pick one of the providers below and follow the matching setup section. The form fills in as much as it can automatically: the endpoint URL is derived from the region or the account ID for every preset, so you only need to supply the bucket and the credentials.

The sections that follow walk through creating the bucket and the credentials with each provider, then map the values onto the fields shown in the Appliku backup form.

Amazon S3

  1. Create an AWS account at aws.amazon.com if you don't have one.
  2. In the AWS Console, open S3 and click Create bucket. Pick a unique bucket name and a region. Block all public access unless you have a specific reason not to. Keep the region handy.
  3. Open IAM, go to Users, click Create user, and give it programmatic access.
  4. Attach an inline policy that allows s3:PutObject, s3:GetObject, s3:DeleteObject, and s3:ListBucket on arn:aws:s3:::your-bucket and arn:aws:s3:::your-bucket/*. Avoid using a full-access policy.
  5. After creating the user, open it and create an Access key. Copy the access key ID and secret access key once; AWS does not show the secret again.

Then fill in the backup form:

Field Value
Storage Provider Amazon S3
Bucket The S3 bucket name
Region The AWS region you created the bucket in (e.g. us-east-1)
Access Key ID The IAM user's access key ID
Secret Access Key The IAM user's secret access key
Path Prefix Optional folder inside the bucket (e.g. appliku-backups)

The endpoint is selected automatically from the region.

DigitalOcean Spaces

  1. Sign in to DigitalOcean and open Spaces Object Storage.
  2. Click Create a Spaces Bucket, pick a datacenter region (e.g. nyc3, fra1, sfo3), choose a unique Space name, and enable Restrict File Listing.
  3. Open API in the left sidebar and scroll to Spaces Keys. Click Generate New Key, give it a name, and copy the access key and secret. The secret is shown only once.

Then fill in the backup form:

Field Value
Storage Provider DigitalOcean Spaces
Space Name The Space name you created
Region The datacenter slug (e.g. nyc3, fra1, sfo3)
Spaces Access Key The Spaces access key
Spaces Secret Key The Spaces secret key
Path Prefix Optional folder inside the Space

The endpoint resolves to https://{region}.digitaloceanspaces.com automatically.

Cloudflare R2

  1. In the Cloudflare dashboard, open R2 Object Storage. If R2 is not yet enabled on the account, accept the terms; R2 has a generous free tier and you can use it without entering payment details until you exceed it.
  2. Click Create bucket, pick a unique name and a location hint, and create the bucket.
  3. Open Manage R2 API Tokens (top right on the R2 overview page). Click Create API Token, choose Object Read & Write, scope it to the bucket you just created, and create the token.
  4. On the token page, copy the Access Key ID and Secret Access Key. Cloudflare also shows your Account ID in the right sidebar of the R2 page; copy that too.

Then fill in the backup form:

Field Value
Storage Provider Cloudflare R2
Bucket The R2 bucket name
Cloudflare Account ID The account ID from the R2 overview page
R2 Access Key ID From the R2 API Token
R2 Secret Access Key From the R2 API Token
Path Prefix Optional folder inside the bucket

The endpoint resolves to https://{account_id}.r2.cloudflarestorage.com automatically. R2 does not use regions; Appliku signs requests with auto for you.

Wasabi

  1. Sign up at wasabi.com and confirm the account.
  2. In the Wasabi console, open Buckets and click Create Bucket. Pick a unique name and a region from the dropdown. Wasabi region codes match Appliku's options (e.g. us-east-1, eu-central-1, ap-northeast-1).
  3. Open Access Keys, click Create New Access Key, choose Root User (or a user you created under Users & Groups with bucket permissions), and download the keys. The secret is shown only at creation.

Then fill in the backup form:

Field Value
Storage Provider Wasabi
Bucket The Wasabi bucket name
Region The Wasabi region of the bucket
Access Key ID The Wasabi access key
Secret Access Key The Wasabi secret key
Path Prefix Optional folder inside the bucket

The endpoint is selected from Wasabi's per-region service URLs automatically. Some Wasabi regions have non-standard endpoints (notably us-east-1 uses s3.wasabisys.com with no region in the hostname), so always use the dropdown rather than typing a region by hand.

Custom S3-compatible

The Custom S3-compatible option works with any service that exposes the AWS S3 API, including self-hosted MinIO, SeaweedFS, Garage, Backblaze B2 (S3 API), Hetzner Object Storage, OVH Cloud Object Storage, Scaleway Object Storage, and any other compatible provider.

Each service has its own console, but the steps are always the same:

  1. Create a bucket in the provider's console.
  2. Generate an S3-compatible access key and secret key with read/write/list/delete permissions on that bucket.
  3. Look up the endpoint URL the provider exposes for the S3 API; this is the value the AWS CLI would pass as --endpoint-url. Examples: https://s3.eu-central-1.example.com, https://gateway.storjshare.io, or for a self-hosted MinIO on a private network something like http://minio.internal:9000.

Then fill in the backup form:

Field Value Notes
Storage Provider Custom S3-compatible
Bucket The bucket name
Region Optional region label Set this if your provider requires a region in the signature (e.g. us-east-1). Leave empty otherwise.
Endpoint URL The provider's S3 endpoint Must include the scheme. Both http:// and https:// are accepted; use http:// only for private networks. A trailing slash is stripped automatically, so https://endpoint.example.com/ and https://endpoint.example.com are equivalent.
Access Key ID The S3-compatible access key
Secret Access Key The S3-compatible secret key
Path Prefix Optional folder inside the bucket Leading and trailing slashes are added automatically; backups, /backups, backups/, and /backups/ all save as /backups/.
Addressing Style Auto, Virtual-hosted, or Path Most managed services accept Auto. Pick Path if your provider requires path-style URLs (https://endpoint/bucket/key rather than https://bucket.endpoint/key); self-hosted MinIO and SeaweedFS typically need this.

If you are unsure whether Auto, Virtual-hosted, or Path is right, run Test Storage with Auto first; if it fails with a DNS or NoSuchBucket error, switch to Path and try again.

Test Storage Before Saving

Each remote backup form has a Test Storage button that uploads a tiny test file from the selected server and deletes it on success. The button uses the same Docker image and credentials as the scheduled backup, so a passing test confirms the backup will be able to write to the destination. The test must pass before you can create a new remote backup, and the form will ask for a fresh test if you change storage settings on an existing backup.

Local Storage Retention

When using Local Filesystem as the backup target, you can set Keep Last N Backups to automatically delete old backup files and keep only the most recent N copies. For example, setting it to 7 keeps the last 7 backup files and removes older ones.

Edit backup form with Keep Last N Backups field

Leave the field empty to keep all backups with no automatic deletion.

Retention is applied automatically every 6 hours by Appliku. Backup files for S3 targets are not affected — those are removed from the server immediately after upload.

  1. After submitting the form you will be taken back to the database page with your new backup task:

Backup task added

View Backup Logs and Files

Open a backup task from the backups table to inspect its latest runtime information.

The backup detail page shows the last 200 lines from the backup job log on the server:

/home/app/_cron_logs/backup_job_{backup_id}.log

For Local Filesystem backups, the page also lists the latest compressed backup files from:

/home/app/_backups/{backup_id}/

The file list shows server paths, file sizes, and modification times. S3 backups show the configured bucket and path instead of local server files.

Backup Command Details

The pg_dump command used to perform backups looks like this:

pg_dump --no-privileges --no-owner --no-acl <postgresql_url>

What these arguments do:

  • --no-privileges — Excludes permissions/privileges from the dump file
  • --no-owner — Excludes ownership information from the dump file
  • --no-acl — Excludes access control lists from the dump file

Backup to File

To store a PostgreSQL backup into a compressed file:

pg_dump --no-privileges --no-owner --no-acl <postgresql_url> | gzip > filename.tar.gz

Backup from Docker Container

Since PostgreSQL runs in a Docker container, the full command looks like this:

docker run --rm --network applications -e DATABASE_URL=<postgres_url> \
  -v /home/app/_backups/{backup_id}:/backup postgres:15 sh -c \
  "pg_dump --no-privileges --no-owner --no-acl \"$DATABASE_URL\" | gzip > /backup/<export_filename>"

What each part does:

  • docker run --rm — Starts a temporary container that is removed after it exits
  • --network applications — Connects the backup container to the same Docker network as the database
  • -e DATABASE_URL=... — Passes the selected database connection URL into the backup container
  • -v /home/app/_backups/{backup_id}:/backup — Mounts the backup directory from the host into the container
  • postgres:15 — Uses the official PostgreSQL 15 Docker image
  • The shell command runs pg_dump, pipes through gzip, and saves to the mounted backup directory

Backup Connection Modes

Backups can connect to PostgreSQL in three modes:

  • Connection URL uses the public database URL. This mode is available only when external connections are enabled for the database.
  • Private Connection URL uses the internal Docker network URL. The backup task must run on the same server as the database.
  • Custom lets you provide a PostgreSQL URL manually. If external connections are disabled for the database, the backup task still must run on the database server.

For databases with external connections disabled, new backup tasks default to Private Connection URL and run on the database server.

Restore from Backup

To restore a PostgreSQL database from a backup file:

  1. Download the backup file
  2. Uncompress it:
gunzip 23-database-starttest1-2023-04-18_21-51-01.gz
  1. Import to the database using psql:
psql <new_postgresql_url> < 23-database-starttest1-2023-04-18_21-51-01