Holds nothing
No database, no cache, no disk. Keys and credentials live for one request, then they're wiped. Scale out and restart freely.
Coming soon · a SafeHelm product
Backups go in. Only ciphertext comes out the other end.
A stateless, encrypting backup gateway written in Rust. Stream in database dumps, containers and files; vBackup compresses, encrypts and stores them in any S3-compatible object storage.
Pipe in pg_dump, docker or
tar. If the dump fails, nothing is stored.
zstd first, because encrypted data can't be compressed later.
A fresh 256-bit key for every object. XChaCha20-Poly1305, authenticated end to end.
Into your S3-compatible bucket, with optional Object Lock against deletion.
No database, no cache, no disk. Keys and credentials live for one request, then they're wiped. Scale out and restart freely.
One data key per object, wrapped by your key. Tampered, truncated, reordered or swapped objects fail the restore.
Encrypt on your side and vBackup never sees a key. One switch makes it refuse any request that carries one.
A hash-chained record of every backup, kept by you. Hidden, rolled-back or swapped backups get caught.
S3 Object Lock per backup. In COMPLIANCE mode not even the holder of the storage credentials can delete it early.
A self-describing format: any S3 client plus the offline CLI decrypts a backup. No running service needed.
Move to a new key by re-wrapping only the data key. No decrypting, no re-uploading.
One static Rust binary in a distroless image. Storage endpoints come from an allowlist, so it can't be turned into an SSRF proxy.
The CLI runs next to your database or containers and reads its secrets
from the environment, so they never show up in ps. Prefer
to build it in? Every command is a call to a versioned REST API with
an OpenAPI spec.
$ export VBACKUP_URL=http://vbackup.internal:8080 \
VBACKUP_TOKEN=… VBACKUP_BUCKET=acme-backups \
VBACKUP_S3_ACCESS_KEY=… VBACKUP_S3_SECRET_KEY=… \
VBACKUP_KEY=… VBACKUP_KEY_ID=acme/2026-11
$ H=(-H "Authorization: Bearer $VBACKUP_TOKEN"
-H "X-Storage-Access-Key: $AK"
-H "X-Storage-Secret-Key: $SK"
-H "X-Backup-Key: $KEK" -H "X-Backup-Key-Id: acme/2026-11")
$ API=$VBACKUP_URL/v1/backups/acme-backups/acme
$ vbackup-client backup -t acme -s pg-main \
-k postgres --retain-days 30 \
-- pg_dump -Fc -Z0 "$DATABASE_URL"
$ pg_dump -Fc -Z0 "$DATABASE_URL" | curl -sf -T - \
-X POST "${H[@]}" -H "X-Backup-Kind: postgres" \
-H "X-Backup-Retain-Days: 30" "$API/pg-main"
# → 201 {"backup_id": …, "plaintext_sha256": …}
$ vbackup-client backup -t acme -s pg-main \
-k postgres -n pre-migration-v42 \
-- pg_dump -Fc -Z0 "$DATABASE_URL"
$ pg_dump -Fc -Z0 "$DATABASE_URL" | curl -sf -T - \
-X POST "${H[@]}" -H "X-Backup-Kind: postgres" \
-H "X-Backup-Name: pre-migration-v42" "$API/pg-main"
$ vbackup-client restore -t acme -s pg-main \
-n pre-migration-v42 -o pre-v42.dump
$ curl -sf "${H[@]}" -o pre-v42.dump \
"$API/pg-main/latest?name=pre-migration-v42"
$ vbackup-client list -t acme -s pg-main
$ curl -sf "${H[@]}" "$API/pg-main"
$ vbackup-client prune -t acme -s pg-main \
--keep-daily 7 --keep-weekly 4 # dry run
$ curl -sf -X POST "${H[@]}" \
"$API/pg-main/prune?keep_daily=7&keep_weekly=4"
# dry run unless dry_run=false
Piping into curl stores whatever arrives; the CLI also
aborts the upload when the dump command fails, so a broken dump can
never pass for a good backup.
vBackup is in active development and testing. Tell us what you need to back up.
[email protected]