Cloudflare R2 exposes an S3-compatible API and can be connected to Storage UI with an Account ID, Access Key ID, and Secret Access Key.
1. Create a bucket
- Open R2 Object Storage in the Cloudflare dashboard.
- Select Create bucket.
- Enter a unique bucket name.
- Create the bucket and keep its name for the Storage UI configuration.
2. Create API credentials
Open R2 Object Storage -> Manage API tokens, then create an Account API token.
Choose the minimum permission required:
- Object Read & Write for full file management.
- Object Read when the connection will only be used in read-only mode.
Limit the token to the required bucket when possible. After creating it, save these values:
- Access Key ID
- Secret Access Key
- Account ID
The Secret Access Key is only displayed once. Store it securely and never expose it through a NEXT_PUBLIC_* variable.
See the Cloudflare R2 API token documentation for the current dashboard flow and permission options.
3. Configure Storage UI
Add the connection to .env.local for local development, or to the environment variable settings on your deployment platform:
STORAGE_1_PROVIDER=r2
STORAGE_1_NAME=Cloudflare R2
STORAGE_1_BUCKET=my-bucket
STORAGE_1_ACCOUNT_ID=your-cloudflare-account-id
STORAGE_1_ACCESS_KEY_ID=your-access-key-id
STORAGE_1_SECRET_ACCESS_KEY=your-secret-access-key
Replace my-bucket with the exact bucket name created in Cloudflare.
Storage UI always builds the R2 endpoint from STORAGE_1_ACCOUNT_ID (https://<account-id>.r2.cloudflarestorage.com) - R2 has no custom-endpoint option, so a STORAGE_1_ENDPOINT value would simply be ignored. Double-check the Account ID: a missing or incorrect value isn't caught up front, and instead surfaces later as a connection or DNS error.
4. Optional settings
Enable read-only mode when the API token only has read access, or when users should not modify objects:
STORAGE_1_READ_ONLY=true
If the bucket is available through a public domain or CDN, configure its public base URL:
STORAGE_1_PUBLIC_BASE_URL=https://files.example.com
5. Restart Storage UI
Restart the development server after changing .env.local:
bun run dev
For a hosted deployment, save the environment variables and redeploy the application. The Cloudflare R2 connection will then appear in the sidebar.
Troubleshooting
The bucket does not appear
Confirm that the bucket name, Account ID, Access Key ID, and Secret Access Key are all configured under the same STORAGE_n_* number. A connection with a missing Account ID still loads - it just fails at request time, so a bucket that appears in the sidebar but stays empty or errors on open is usually a wrong or missing STORAGE_n_ACCOUNT_ID.
Access is denied
Check that the API token has access to the selected bucket. Full file management requires Object Read & Write permission.
Reading works but uploads fail
Confirm that STORAGE_n_READ_ONLY is not set to true and that the API token includes write permission.
Requests fail with a connection or DNS error
The endpoint is derived from STORAGE_n_ACCOUNT_ID as https://<account-id>.r2.cloudflarestorage.com. Since this value isn't validated when the connection loads, a typo or missing Account ID only shows up once a request is made.