Local backups
A worker on your hardware connects to the source. The credential never leaves.
View as MarkdownA local backup runs on a machine you own. Your worker connects to the source, produces the dump, encrypts it, and uploads ciphertext. We schedule the run and record what happened.
This is the stronger of the two connected kinds, and the one to prefer whenever you can run a process.
The data path
your worker: dump → encrypt → checksum → upload
us: ↳ inspect → compress → deliver → finalize| Stage | Runs on | Sees |
|---|---|---|
| Dump | Your host | The source, using credentials in the worker's own config |
| Encrypt | Your host | Plaintext, briefly |
| Upload | Your host to object storage | Ciphertext |
| Everything after | Ours | Ciphertext, a checksum, a size and a filename |
The crucial line is the second one. A local backup is encrypted before it leaves your network, by the worker, with a public key you put in its config. Our side of the pipeline never holds a key that could open it.
What we send the worker
Three identifiers: the workspace, the backup, and the run. That is the whole payload.
No credentials, no source configuration and no data travel to the worker, because they never
came from us. It resolves the backup ID against its own config.yaml and works from there.
A backup with no matching entry fails with ConfigDrift rather than guessing.
Configuring one
A local backup is configured in two places, and both are required.
On our side, the definition says which worker runs it and how often:
workers:
- name: prod-worker-1
backups:
- name: prod-db
kind: local
source_type: postgres
worker: prod-worker-1
schedule: "0 2 * * *"
retention:
keep_last: 10
expire_after: 90dOn the worker, keyed by the backup ID, the source itself:
backups:
"<backup-uuid>":
source_type: postgres
source:
database: app
host: db.internal
password: "<password>"A local backup takes no source or credentials block in saved.yaml. Sending one is
refused, naming the kind: a local backup's credentials never reach us, so accepting them
would be accepting a secret we promised not to hold.
See worker configuration for every field each source type accepts.
Source types
All eight local types, including the three that exist nowhere else:
| Type | Also available as cloud |
|---|---|
postgres, mysql, redis, s3, web | Yes |
script, file, folder | Never |
script, file and folder are local-only permanently. script runs a command you wrote,
and we are not taking on the sandboxing and abuse problem of executing customer commands in
our cloud. file and folder read your filesystem, which does not exist in our cloud at
all.
That makes script the most useful type in the list: it lets you back up anything we have no
connector for, on your own hardware, with no work from us.
Routing
A local backup must name a worker, and its runs go only to that worker's queue.
- If the worker is offline, runs queue until it returns. They are not redistributed, because no other machine has the credentials.
- Changing the worker recreates the schedule, so the change takes effect from the next fire.
- One backup, one worker. To spread load, provision a second worker and split the backups between them.
What it costs you
The honest trade, stated in both directions.
| You gain | You pay |
|---|---|
| Source credentials never leave your network | A process to install, run and keep upgraded |
| Plaintext never exists on our infrastructure | Disk on the worker, roughly twice the dump size |
| The encryption key is yours alone | A backup does not run while the worker is down |
Access to script, file and folder | Your own monitoring of whether it is up |
The second row of the right-hand column is the one people underestimate. A worker with a full disk fails every run, and it fails at the dump step, which is the most expensive place to fail.