VPS Snaps

How to use Cloudflare R2 for server backups

Cloudflare R2 is S3-compatible object storage with no egress fees, so pulling a backup back down costs nothing in bandwidth. Create a private bucket, create an API token with Object Read & Write scoped to that bucket, and point the AWS CLI at https://<ACCOUNT_ID>.r2.cloudflarestorage.com with the region set to auto. R2 has no versioning, so use a lifecycle rule for retention and a bucket lock rule if the server's token must not be able to delete backups.

8 min readUpdated Checked against official documentation

Create the bucket

  1. In the Cloudflare dashboard, go to the R2 object storage page and select Create bucket.
  2. Enter a name: 3 to 63 characters, lowercase letters, numbers and hyphens, not starting or ending with a hyphen.
  3. Under Location, leave None for automatic placement, pick a location hint, or select Specify jurisdiction (see the table below).
  4. Select Create bucket.

Buckets are private by default. Leave public access and the r2.dev URL off for a backup bucket. With Wrangler, Cloudflare's CLI:

Terminal
npx wrangler r2 bucket create acme-server-backups --location weur
  • --location is an optional location hint. Leave it out for automatic placement.
  • --jurisdiction eu creates the bucket in a jurisdiction instead.

Location hints vs jurisdictions

Location hintJurisdiction
What it doesBest-effort placement near where you expect accessObjects are stored within that jurisdiction
Valueswnam, enam, weur, eeur, apac, oceu, fedramp (Enterprise, via Cloudflare), us
S3 endpointhttps://<ACCOUNT_ID>.r2.cloudflarestorage.comhttps://<ACCOUNT_ID>.<JURISDICTION>.r2.cloudflarestorage.com
Changing itOnly honored the first time a bucket name is createdCan't be changed after creation

Automatic placement picks the region closest to whoever sends the create request, which is your laptop if you run Wrangler there. Set a hint if your servers are elsewhere. Use a jurisdiction only when data residency is a requirement; such buckets only answer on their own endpoint.

Create a bucket-scoped API token

R2 has to be purchased on the account before you can create API tokens. Then:

  1. On the R2 object storage page, under Account Details, select Manage next to API Tokens.
  2. Choose Create Account API token. It belongs to the account, so it keeps working if the person who made it leaves. A User API token stops working when that user is removed.
  3. Under Permissions, choose Object Read & Write.
  4. Scope the token to the backup bucket only.
  5. Create the token and copy the Access Key ID and Secret Access Key. The secret is shown once.
PermissionWhat it allows
Admin Read & WriteCreate, list and delete buckets, edit bucket configuration, read, write and list objects
Admin Read onlyList buckets, view configuration, read and list objects
Object Read & WriteRead, write and list objects in specific buckets
Object Read onlyRead and list objects in specific buckets

Object Read & Write can't touch bucket settings, so a server holding it can't change lifecycle or lock rules. It can overwrite and delete objects in its bucket, and R2 has no write-only option. Bucket locks, below, close that gap. You also need your account ID, shown in the dashboard, for the endpoint.

Configure the AWS CLI

Terminal
aws configure --profile r2

Enter the Access Key ID and Secret Access Key, and auto for the region. The SDK requires a region; R2 ignores it, and also treats an empty value or us-east-1 as auto. To skip --endpoint-url on every command, add the endpoint to the profile:

~/.aws/config
[profile r2]
region = auto
endpoint_url = https://<ACCOUNT_ID>.r2.cloudflarestorage.com

The examples below still pass --endpoint-url, which overrides the profile. Test by listing the bucket itself. A bucket-scoped token isn't meant for listing every bucket in the account, and rclone needs no_check_bucket = true with such a token; see rclone backups.

Terminal
aws s3 ls s3://acme-server-backups/ --profile r2 --endpoint-url https://<ACCOUNT_ID>.r2.cloudflarestorage.com

Upload backups

Terminal
aws s3 cp /var/backups/web-01-2026-10-03.tar.gz s3://acme-server-backups/web-01/2026-10-03.tar.gz --profile r2 --endpoint-url https://<ACCOUNT_ID>.r2.cloudflarestorage.com --only-show-errors
Terminal
aws s3 sync /var/backups/web-01/ s3://acme-server-backups/web-01/ --profile r2 --endpoint-url https://<ACCOUNT_ID>.r2.cloudflarestorage.com --only-show-errors
  • Use unique, dated keys. Without versioning, an overwrite or delete on R2 is final.
  • Don't add --delete to sync. A wiped local directory would delete the backups.
  • Don't pass --sse. R2 doesn't implement the x-amz-server-side-encryption header; it encrypts every object and its metadata at rest with AES-256 automatically.
  • --storage-class STANDARD_IA stores an object in Infrequent Access. STANDARD is the default.

Expire old backups with lifecycle rules

In the dashboard, open the bucket, select Settings, then under Object Lifecycle Rules select Add rule, fill in the prefix and actions, and select Save changes. With Wrangler, logged in with npx wrangler login:

Terminal
npx wrangler r2 bucket lifecycle add acme-server-backups expire-30d web-01/ --expire-days 30
  • expire-30d is the rule's name and web-01/ its prefix. Leave the prefix empty to cover the whole bucket.
  • --expire-days 30 deletes objects 30 days after upload.
  • --ia-transition-days moves objects to Infrequent Access after that many days. Objects can't be moved back to Standard by a lifecycle rule.
  • --abort-multipart-days cancels unfinished multipart uploads. Every bucket already has a default rule that does this after seven days.

Objects are typically removed within 24 hours of their expiration time; existing objects can take longer after a rule changes. If an expire and a transition fall within the same 24 hours, the expire wins. A bucket can have up to 1,000 rules. Managing them needs an admin-level token, which the server never holds.

Protect backups with bucket locks

R2 doesn't implement versioning or the S3 Object Lock API. Instead, bucket lock rules stop objects under a prefix from being deleted or overwritten for a number of days, until a date, or indefinitely. They cover existing objects as well as new ones, the strictest matching rule wins, and they override lifecycle rules.

Terminal
npx wrangler r2 bucket lock add acme-server-backups lock-14d web-01/ --retention-days 14

In the dashboard, the same rule is under the bucket's Settings tab, in the Bucket lock rules card. Keep the lock shorter than your lifecycle expiry: a lifecycle rule that tries to delete a locked object waits until the lock ends.

Anyone who can edit the bucket's configuration can remove a lock rule, with wrangler r2 bucket lock remove or in the dashboard. A lock stops a leaked object token, not a compromised Cloudflare admin login. Also, a bucket with lock rules can't be emptied until they are removed.

Verify a backup

Terminal
aws s3 ls s3://acme-server-backups/web-01/ --recursive --human-readable --summarize --profile r2 --endpoint-url https://<ACCOUNT_ID>.r2.cloudflarestorage.com
Terminal
aws s3 cp s3://acme-server-backups/web-01/2026-10-03.tar.gz /tmp/restore-test.tar.gz --profile r2 --endpoint-url https://<ACCOUNT_ID>.r2.cloudflarestorage.com && sha256sum /tmp/restore-test.tar.gz && tar -tzf /tmp/restore-test.tar.gz > /dev/null && echo OK

Compare the hash with the one you recorded before upload. Because egress is free, a full test download of a Standard object costs one Class B operation per request; Infrequent Access adds a retrieval fee. See testing a restore.

What it costs

As of October 2026, Cloudflare lists:

StandardInfrequent Access
Storage$0.015 / GB-month$0.01 / GB-month
Class A operations (writes, lists)$4.50 / million$9.00 / million
Class B operations (reads, heads)$0.36 / million$0.90 / million
Data retrievalNone$0.01 / GB
Egress to the internetFreeFree
Minimum storage durationNone30 days
  • Free every month, Standard only: 10 GB-month of storage, 1 million Class A and 10 million Class B operations.
  • DeleteObject, DeleteBucket and AbortMultipartUpload are free. So are requests rejected as unauthorized.
  • Usage is rounded up to the next billing unit: 1.1 GB-month is billed as 2.
  • ListObjects, PutObject and each multipart UploadPart are Class A operations, so aws s3 sync listings count.

Example: 100 GB of Standard backups is billed as 90 GB-month after the free tier, or $1.35 a month, and a daily upload stays well inside the free operations. Infrequent Access only pays off for copies kept 30 days or more and rarely read, because it has retrieval fees and no free tier.

Limits and S3 differences that matter for backups

  • No versioning: deletes and overwrites are permanent.
  • No S3 Object Lock headers; use bucket lock rules.
  • No bucket policies or ACLs: the API token is the only access control.
  • No object tagging, so no tag-based rules.
  • Objects up to 4.995 TiB; a single upload or part up to 4.995 GiB; at most 10,000 parts.
  • One write per second to the same key; faster writes get HTTP 429.
  • Jurisdiction buckets only answer on their jurisdiction endpoint, so most tools need one profile per jurisdiction.
  • The region is always auto.

A key that can upload can usually delete too. For backups an attacker cannot remove, see protecting backups from ransomware; to keep what is stored readable only by you, encrypt it before upload.

Frequently asked questions

Is Cloudflare R2 egress really free?
Yes. Cloudflare charges no egress for any storage class through the S3 API, Workers API or r2.dev. Infrequent Access objects still have a $0.01 per GB retrieval fee as of October 2026.
What region do I use for R2 in the AWS CLI?
auto. The CLI needs a value but R2 doesn't use it. An empty value or us-east-1 also maps to auto.
Does R2 support versioning or Object Lock?
No versioning and no S3 Object Lock API. Use bucket lock rules to stop objects under a prefix from being deleted or overwritten for a period.
Can an R2 API token be limited to one bucket?
Yes. Tokens with Object Read & Write or Object Read only permission can be scoped to specific buckets.
How much R2 storage is free?
As of October 2026, 10 GB-month of Standard storage, 1 million Class A and 10 million Class B operations each month. The free tier doesn't cover Infrequent Access.

How this was checked

Commands, limits and prices were checked against these official pages, on October 3, 2026: