Skip to content

Choosing storage

SyncBins stores metadata in SQLite and large ciphertext blobs (screenshots, files, audio) in a pluggable backend. The server never sees plaintext — blobs are encrypted on your device before upload.

Default for self-hosters: local disk. No cloud account, no extra env vars beyond the quick start. Switch to S3, R2, or Azure only if you want blobs off the VPS or need more durability than a single disk.

BackendWhen to useExtra env vars
Local diskHomelab, VPS, “just run it”None (STORAGE_KIND=local is the default)
AWS S3Standard cloud object storageSTORAGE_KIND=s3 + S3_* vars
Cloudflare R2Cheap cloud blobs, zero egressSTORAGE_KIND=r2 + four R2_* vars
Azure BlobAlready on AzureSTORAGE_KIND=azure + connection string

There is no Settings UI for this — configure at deploy time in docker/.env. See Configuration reference for every variable.

BackendCost / GB-moEgressSetupBest for
Local disk$0 (your hardware)$01 minMost self-hosters
AWS S3~$0.023 (Standard)Per-GB5 minAWS shops, widest ecosystem
Cloudflare R2~$0.015$05 minCloud without egress surprise
Azure Blob~$0.018 (Hot)Per-GB10 minAzure shops

Items under ~64 KB stay inline in SQLite — only larger payloads hit blob storage.

docker/.env
STORAGE_KIND=local
LOCAL_BLOB_DIR=/data/blobs
BLOB_URL_SECRET=… # required in production — openssl rand -hex 32

Blobs live as {ulid}.bin under LOCAL_BLOB_DIR. In Docker, bind-mount ./data:/data so both SQLite and blobs survive container rebuilds.

You do not need R2, S3, or Azure for a fully working self-hosted SyncBins. This is what the dev compose uses.

Rough guide for ciphertext (already encrypted on device):

  • Screenshots: 50 KB – 500 KB each
  • Voice memos: ~0.5 MB per minute
  • Files: whatever you drop in

A heavy user might add ~50 MB/week. Local disk or a small R2 bucket is plenty for personal use.

  1. Stop the server.
  2. Copy blobs (cp -r, rclone copy, or aws s3 sync depending on source/target).
  3. Update STORAGE_KIND and credentials in .env.
  4. Start the server.

SQLite keeps the same blob_ref names; the new backend must contain the same {ulid}.bin objects.