Skip to main content
split cuts the final archive into fixed-size parts before upload. snapr applies it after compression and (if configured) encryption, so each part is a slice of the encrypted, compressed bytes — not a self-contained mini-archive. Use it when:
  • a storage backend rejects objects above some size (FTP/SFTP server quotas, email attachment limits, providers without S3 multipart upload),
  • you want backups to fit on removable media of a known capacity,
  • a flaky network makes re-uploading one failed part cheaper than re-uploading the whole archive.

Fields

Example

snapr.yaml

How parts are named

Each part gets the original archive name plus a .part- suffix with three lowercase letters, counting in base 26: aaa, aab, … zzz. That caps an archive at 17,576 parts. With a 1 GiB chunk that is a 17.1 TiB ceiling — raise chunkSize if you ever get close.

On-disk layout

A split snapshot lives in a wrapper directory inside the per-job folder. Parts are plain files inside it:
The wrapper name encodes the part count and the total size in bytes (.parts-3-3221225472 means 3 parts, about 3 GiB). snapr reads both from the directory name alone, so listing a job’s backups never descends into the wrapper or stats individual parts — it stays one storage call regardless of part count. The wrapper is created at upload time and never modified afterward. Retention keeps the whole wrapper or deletes it entirely.
If the archive fits in a single chunk, snapr skips the wrapper and uploads the single part (still named .part-aaa) directly into the job folder. A wrapper with one part is never produced.

Retention treats a set as one backup

One wrapper directory counts as one logical backup. retention.last: 14 keeps the 14 newest snapshots, no matter how many parts each produced. Rotation removes the wrapper and all its parts in one operation.

Downloading a split backup

The web UI and GET /api/v1/jobs/{name}/backups/{filename}/download accept the set ID — the original archive name without the wrapper suffix and without .part-XXX. snapr opens each part on the storage, streams them back-to-back, and serves the result as one continuous download. You get a single file, no manual concatenation. The UI also offers per-part download, useful when one full-archive transfer is impractical.
For bunny.net Storage behind a signed Pull Zone, full-set download is not supported — one HTTP redirect cannot represent N parts. “Download all” returns 501 Not Implemented there. Per-part download still works, since each part gets its own redirect to a signed URL. For full-set streaming, use a non-redirect storage (Local, S3, SFTP, WebDAV) as the download source.

Reassembling parts manually

If you copy a wrapper directory off the storage yourself, concatenate the parts in lexicographic order.
1

Concatenate the parts

The aaa, aab, aac suffixes sort lexicographically in write order, and shell globs expand in the same order, so a plain cat is safe:
2

Decrypt (if the job uses encryption)

See Encryption for details.
3

Extract

Toggling split on or off

Adding or removing the split block between runs is safe. Existing snapshots keep their layout — wrapper directories from past split runs and plain archives from non-split runs coexist in the same job folder. Listing, retention, and download handle both transparently.

Notes

  • chunkSize is validated at config load. An unparseable value fails startup with a validation error.
  • Splitting runs purely in Go — no external split binary required.
  • A part smaller than chunkSize is always the last part. Don’t estimate chunkSize from an arbitrary part’s size.