Sthora
Managed services

Backups

Scheduled and on-demand backups of a managed service, to local disk or any S3-compatible bucket — and how to restore one.

Backups run the service's own client inside its own container. There is no separate backup image holding credentials, and no version-skew between a dump tool and the database it dumps.

Scheduling

Set a five-field cron expression on the service — 0 3 * * * for 03:00 daily. The maintenance job asks which services are due and runs those.

The expression is validated for shape, not for range. Checking each field would duplicate the scheduler's own parser and drift from it. What the check does catch is what operators actually get wrong here: a six-field expression copied from a different scheduler, and free text.

BACKUP_TIMEOUT_SECONDS (default 3600) is the ceiling on one backup step. A dump of a large database is slow, and killing it halfway produces a file that looks like a backup and is not one.

Where they go

TargetDestination
LOCAL/var/lib/sthora/backups/<slug>/
S3Any S3-compatible endpoint — bucket, region, endpoint, access key, secret key

The S3 destination is write-only, exactly like an environment variable: it is stored encrypted and returned by no endpoint. The upload runs through a pinned AWS CLI image.

A service set to S3 with no destination configured fails its backup with a message saying so. Set the destination before you set the target.

backupRetentionCount (1–365) prunes what falls out of retention after each successful backup. Only LOCAL artefacts are pruned by the platform — an S3 bucket's lifecycle is the bucket's own business.

What each kind produces

KindCommandFile
PostgreSQLpg_dump --format custom.dump
Redisredis-cli SAVE, then copy dump.rdb.rdb
MinIOmc alias set, then tar -czf of the data directory.tar.gz

A failed backup opens an alert

BACKUP_FAILED is a CRITICAL alert. A backup that quietly stopped running is worse than no backup, because you find out at the moment you need it.

Restoring

Restores are a deliberate operator action, run from the box.

# PostgreSQL
docker cp <backup>.dump sthora-svc-<slug>:/tmp/restore.dump
docker exec sthora-svc-<slug> \
  pg_restore --username sthora --dbname app --clean --if-exists /tmp/restore.dump

# Redis — it loads its dump only at startup, so the restart is required
docker cp <backup>.rdb sthora-svc-<slug>:/data/dump.rdb
docker restart sthora-svc-<slug>

# MinIO
docker cp <backup>.tar.gz sthora-svc-<slug>:/tmp/restore.tar.gz
docker exec sthora-svc-<slug> tar -xzf /tmp/restore.tar.gz -C /data

The platform's own database

Separate from all of this. It is dumped nightly to /var/lib/sthora/backups/platform/, and again by install.sh --upgrade before it touches anything. See backup and restore.

What is not backed up

An application's volumes. Back those up from inside the application, or keep anything you would regret losing in a managed service.

On this page