Writing a backup target
A “target” knows how to read, write, list, and delete blobs in a storage backend (S3, local disk, GCS, Azure Blob, …). To add one, implement the Target interface in internal/backup/ and register it.
Interface
Section titled “Interface”type Target interface { Name() string // unique key, e.g. "s3" Put(ctx context.Context, key string, body io.Reader) (size int64, err error) Get(ctx context.Context, key string) (io.ReadCloser, error) List(ctx context.Context, prefix string) ([]Object, error) Delete(ctx context.Context, key string) error TestConnection(ctx context.Context) error // used by the UI test button}Object is {Key, Size, ModTime}. Keys are forward-slash paths; targets must accept any printable ASCII.
Reference targets
Section titled “Reference targets”- Local (
internal/backup/target_local.go): writes to{data_dir}/backups/local/. Useful for development and one-host setups. - S3 (
internal/backup/target_s3.go): uses the AWS SDK. Supports custom endpoints (R2, Wasabi, MinIO) viaendpoint. Credentials are stored encrypted inregistries-style rows.
Steps to add a target
Section titled “Steps to add a target”- Create
internal/backup/target_<name>.goimplementingTarget. - Add credential storage if needed. Reuse the encrypted-credential pattern from S3 (encrypt with
master_secret). - Register the target in the factory.
- Add unit tests with a fake remote (testcontainers, MinIO, or custom interface mock).
- Add a guide page under
docs/guides/backups/<name>-target.md. - Update
docs/architecture/backup.mdto mention the new target.
Constraints
Section titled “Constraints”- Streaming: never buffer a backup body in memory.
Putshould acceptio.Readerand stream. - Idempotency:
Putwith the same key must overwrite cleanly;Deletemust be a no-op when the key is gone. - Cancellation: honor
ctxfor all network operations. - Credentials: encrypt at rest with
auth.Encrypt. Decrypt only at use time. - Errors: classify retryable vs permanent; the scheduler retries only retryable ones.
Submit
Section titled “Submit”Open a PR with the target, tests, and docs. Tag it feat(backup): <name> target.