Skip to content

WORM (write once, read many) means objects can’t be deleted or overwritten until their retention date, not even by you, not even by an attacker holding your keys. It’s the property that makes a backup survive the bad day it exists for.

Before writing anything, gitdr probes the destination’s lock configuration. Then:

  • Lock confirmed. It proceeds and records the observed immutability in the signed manifest, so “was this backup on WORM storage” has a tamper-evident answer later.
  • No lock. It warns loudly and proceeds. Configuring WORM is your job, but you’ll never be quietly unprotected.
  • --require-worm (or worm.require: true). No confirmed lock means the run fails closed. Use this once your bucket is set up.

Independent of all that, gitdr’s storage layer has no delete or overwrite method, uploads are create-only. WORM protects you from stolen credentials; create-only protects you from gitdr itself.

AWS S3, Object Lock. Only settable at bucket creation:

Terminal window
aws s3api create-bucket --bucket my-worm-bucket --region us-east-1 \
--object-lock-enabled-for-bucket
aws s3api put-object-lock-configuration --bucket my-worm-bucket \
--object-lock-configuration \
'{"ObjectLockEnabled":"Enabled","Rule":{"DefaultRetention":{"Mode":"COMPLIANCE","Days":30}}}'

COMPLIANCE mode is real WORM, nobody can shorten it. GOVERNANCE can be lifted with a special permission, which an attacker with admin can also hold. Pick COMPLIANCE.

Google Cloud Storage, locked retention policy. The lock is irreversible:

Terminal window
gcloud storage buckets create gs://my-worm-bucket --location=US \
--uniform-bucket-level-access --public-access-prevention --retention-period=30d
gcloud storage buckets update gs://my-worm-bucket --lock-retention-period

Azure Blob. Storage account with version-level immutability plus blob versioning, then a container with a time-based immutability policy (Azure docs).

“S3-compatible” is a spectrum, and Object Lock is one of the least universally implemented parts. Set destination.s3.endpoint and usually usePathStyle: true.

Provider Object Lock Notes
Wasabi yes 90-day minimum retention
Backblaze B2 yes enable at bucket creation, versioning required
MinIO / IDrive e2 yes create the bucket with object lock
Cloudflare R2 no works as a destination, gitdr warns, no WORM

A provider that doesn’t implement the Object Lock API can’t be confirmed immutable, so gitdr warns and proceeds, or fails closed under --require-worm.

The destination credential needs create/put and read. It never needs delete, so don’t grant it. A compromised runner then can’t purge history even on a non-WORM bucket.