Storage / Cloudflare R2Menu

Cloudflare R2Cloudflare R2

Store your SFTP server's files in your own Cloudflare R2 bucket, with no egress fees.

Updated · Markdown

R2 doesn’t charge for egress, so it suits servers where partners download a lot. You can also pin a bucket to the EU jurisdiction.

Before you start

  • A Cloudflare account with R2 enabled.
  • Your Account ID: a 32-character hex string, shown on the R2 Overview page under Account Details. It’s also the first part of the bucket’s S3 API address.

1. Create the bucket

  1. In the Cloudflare dashboard, go to R2 object storage → Overview and select Create bucket.
  2. Pick the Location:
    • Automatic or a location hint (for example Eastern Europe (EEUR)) only suggests where the data should live. It is not a guarantee, and the bucket uses the default endpoint.
    • A jurisdiction (for example European Union) guarantees the data stays there, and the bucket gets its own endpoint (see step 3). Choose this if your contracts require data to stay in the EU. It can’t be changed after the bucket is created.
  3. Create the bucket.

Keep the bucket private

In the bucket’s Settings, leave Public Development URL disabled and don’t connect a Custom Domain. Either one makes every file readable by anyone who guesses its path. CloudFile doesn’t need them: download links in webhooks are signed and expire after an hour.

You can leave the other settings as they are. The default lifecycle rule that aborts unfinished multipart uploads after 7 days is fine. To upload files over 100 MB from the web file manager or through file requests, add a CORS policy that allows PUT from https://cloudfile.dev under Settings → CORS Policy (see Uploads from the browser). SFTP and FTP don’t need it.

2. Create an API token

R2 access keys come from an R2 API token scoped to your bucket.

  1. On the R2 Overview page, under Account Details, select Manage next to API Tokens.

  2. Choose Create Account API token. (A user token works too, but stops working if your user leaves the account.)

  3. Under Permissions, choose Object Read & Write.

  4. Under Specify bucket(s), choose Apply to specific buckets only and pick your bucket.

  5. Create the token. Cloudflare shows a summary with three values, once:

    • Token value (starts with cfat_): not needed by CloudFile.
    • Access Key ID (32 characters): goes into CloudFile.
    • Secret Access Key (64 characters): goes into CloudFile.

    The summary also lists the endpoint to use under Use jurisdiction-specific endpoints for S3 clients.

Copy the Access Key ID and Secret Access Key somewhere safe. Cloudflare won’t show the secret again. If they leak, open the token and select Roll to get new keys, then update them in CloudFile.

3. Connect it

In CloudFile, go to Storage → Add bucket and choose Cloudflare R2:

Field Value
Bucket Your bucket name, e.g. my-files
Account ID From Account Details, e.g. 9276e14e21f297b9b1b0779e028b6814
Endpoint Filled in from the Account ID: https://<account-id>.r2.cloudflarestorage.com
Access key ID The Access Key ID from step 2
Secret access key The Secret Access Key from step 2
Name Optional, e.g. Production
Path-style URLs On

The endpoint never includes the bucket name. The bucket’s settings page shows its S3 API address as https://<account-id>.r2.cloudflarestorage.com/my-files. If you paste that, CloudFile drops the /my-files part for you.

For a bucket in a jurisdiction, add the jurisdiction to the endpoint, for example https://<account-id>.eu.r2.cloudflarestorage.com for the EU. A location hint such as EEUR doesn’t change the endpoint. The region is always auto, so CloudFile sets it for you.

Click Test connection. CloudFile writes, reads and deletes a small test file. Then click Save.

4. Use it on a server

Open a server and pick the bucket under Settings → Storage. New files go to the bucket from then on. Files already on the server aren’t moved.

In the bucket, each SFTP user gets a folder, <prefix>/<username>/, and shared folders live in <prefix>/_shared/<name>/. Leave the prefix empty to put them at the bucket root.

Troubleshooting

  • Writing a test file failed: The specified bucket does not exist. Either the bucket name is wrong, or the bucket is in a jurisdiction (for example the EU) and the endpoint is missing it. Use https://<account-id>.eu.r2.cloudflarestorage.com.
  • Writing a test file failed with a DNS or connection error. The Account ID is wrong. Copy it again from Account Details. It’s a 32-character hex string.
  • Writing a test file failed: Access Denied. The token is scoped to a different bucket, or it has only Object Read permission. Create a new token with Object Read & Write for this bucket.
  • Writing a test file failed with an invalid access key or signature error. You pasted the cfat_… token value instead of the Access Key ID and Secret Access Key shown with it, or the token was rolled since.

See Your own bucket for how files are laid out in the bucket.