Cloudflare R2

Verified against the provider's documentation, not against a live account.

A provider snapshot disappears with the account that holds it; a dump in a bucket you control is the copy that survives, and Verestore proves it restores.

1. Write dumps to R2

R2 speaks the S3 API at https://<account-id>.r2.cloudflarestorage.com (or https://<account-id>.eu.r2.cloudflarestorage.com for a bucket in the EU jurisdiction). The signing region is always auto. With a separate read-write token for your backup job:

pg_dump --format=custom --no-owner "$DATABASE_URL" \
  | aws --endpoint-url "https://$R2_ACCOUNT_ID.r2.cloudflarestorage.com" --region auto \
      s3 cp - "s3://acme-backups/orders/orders-$(date -u +%Y-%m-%dT%H-%M).dump"

Verestore accepts pg_dump custom format (-Fc) or plain SQL, optionally gzipped. The format is detected from the content, not the file extension.

2. Create a read-only R2 API token

R2 API tokens are scoped to buckets, not to prefixes. Use a dedicated bucket per database so the token can read nothing else.

  1. In the Cloudflare dashboard, open R2 and create an API token (check the provider's current documentation for the exact menu).
  2. Name it verestore-reader.
  3. Permission: Object Read only.
  4. Scope: apply it to the specific bucket acme-backups only.
  5. Create the token and copy the Access Key ID and Secret Access Key shown for S3 clients. The secret is shown once.

Verestore only lists objects under the prefix (ListObjectsV2) and reads orders/*, pinned to the listed ETag. It never writes or deletes.

3. Add the target in Verestore

  • S3 endpoint: https://<account-id>.r2.cloudflarestorage.com (or the .eu. form)
  • Region: auto (or leave it empty: it is filled from the endpoint)
  • Bucket: acme-backups
  • Prefix: orders/
  • Access key ID and secret access key: from the token