R2 (beta) get started guide
Cloudflare R2 Storage allows developers to store large amounts of unstructured data without the costly egress bandwidth fees associated with typical cloud storage services.
This guide will instruct you through setting up Wrangler to deploying your first R2 bucket.
1. Install Wrangler
To create your R2 bucket, install Wrangler , the Workers CLI.
To install
wrangler
, ensure you have
npm
installed. Use a Node version manager like
Volta or
nvm to avoid permission issues or to easily change Node.js versions, then run:
$ npm install -g @cloudflare/wrangler
or install with yarn:
$ yarn global add @cloudflare/wrangler
or install with cargo:
$ cargo install wrangler
Refer to the Wrangler Install/Update page for more information.
2. Authenticate Wrangler
With installation complete, wrangler
will need access to a Cloudflare OAuth token to manage Workers resources on your behalf.
Run the command wrangler login
, which will automate this process.
Wrangler will attempt to automatically open your web browser to complete the login process to your Cloudflare account. If you have issues completing this step or you do not have access to a browser GUI, you can copy and paste the URL generated by wrangler login
in your terminal into a browser and log in.
$ wrangler login
Allow Wrangler to open a page in your browser? [y/n]
y
💁 Opened a link in your default browser: https://dash.cloudflare.com/oauth2/...
Open the browser, log into your account, and select Allow. This will send an OAuth Token to Wrangler so it can deploy your scripts to Cloudflare.
3. Create your bucket
Create your bucket by running:
wrangler r2 bucket create <YOUR_BUCKET_NAME>
To check that your bucket was created, run:
wrangler r2 bucket list
After running the list
command, you will see all bucket names, including the one you have just created.
4. Bind your bucket to a Worker
You will need to bind your bucket to a Worker.
Run the
wrangler generate
command to create a Worker using a
template
. Wrangler templates are git repositories that are designed to be a starting point for building a new Cloudflare Workers project. By default, the
default starter template will be used to generate your new Worker project:
wrangler generate <YOUR_WORKER_NAME>
Next, find your newly generated wrangler.toml
file in your project’s directory and update account_id
with your Cloudflare Account ID.
Find your Account ID by logging in to the Cloudflare dashboard > Overview > move down to API > and select Click to copy to copy your Account ID. Or run the wrangler whoami
command
to copy your Account ID
.
name = "<YOUR_WORKER_NAME>"
type = "javascript"
compatibility_date = "2022-02-10"
account_id = "YOUR_ACCOUNT_ID" # ← Replace with your Account ID.
workers_dev = true
To bind your R2 bucket to your Worker, add the following to your wrangler.toml
file. Update the binding
property to a valid JavaScript variable identifier and bucket_name
to the <YOUR_BUCKET_NAME>
you used to create your bucket in
step 3
:
[[r2_buckets]]
binding = 'MY_BUCKET' # <~ valid JavaScript variable name
bucket_name = '<YOUR_BUCKET_NAME>'
Find more detailed information on configuring your Worker in the Wrangler Configuration documentation .
5. Access your R2 bucket from your Worker
Within your Worker code, your bucket is now available under the MY_BUCKET
variable and you can begin interacting with it.
An R2 bucket is able to READ, LIST, WRITE, and DELETE objects. You can see an example of all operations below using the Service Worker syntax. Add the following snippet into your project’s index.js
file:
addEventListener('fetch', event => {
event.respondWith(handleRequest(event.request));
});
async function handleRequest(request) {
const url = new URL(request.url);
const key = url.pathname.slice(1);
switch (request.method) {
case 'PUT':
await MY_BUCKET.put(key, request.body);
return new Response(`Put ${key} successfully!`);
case 'GET':
const { value } = await MY_BUCKET.get(key);
if (value === null) {
return new Response('Object Not Found', { status: 404 });
}
return new Response(value);
case 'DELETE':
await MY_BUCKET.delete(key);
return new Response('Deleted!', { status: 200 });
default:
return new Response('Route Not Found.', { status: 404 });
}
}
6. Bucket access and privacy
With the above code added to your Worker, every incoming request has the ability to interact with your bucket. This means your bucket is publicly exposed and its contents can be accessed and modified by undesired actors.
You must now define authorization logic to determine who can perform what actions to your bucket. This logic lives within your Worker’s code, as it is your application’s job to determine user privileges. The following is a short list of resources related to access and authorization practices:
- Basic Authentication : Shows how to restrict access using the HTTP Basic schema.
- Using Custom Headers : Allow or deny a request based on a known pre-shared key in a header.
- Authorizing users with Auth0 : Integrate Auth0, an identity management platform, into a Cloudflare Workers application.
Continuing with your newly created bucket and Worker, you will need to protect all bucket operations.
For PUT and DELETE requests, you will make use of a new AUTH_KEY_SECRET
environment variable, which you will define later as a Wrangler secret.
For GET requests, you will ensure that only a specific file can be requested. All of this custom logic occurs inside of an authorizeRequest
function, with the hasValidHeader
function handling the custom header logic. If all validation passes, then the operation is allowed.
const ALLOW_LIST = ['cat-pic.jpg'];
// Check requests for a pre-shared secret
const hasValidHeader = request => {
return request.headers.get('X-Custom-Auth-Key') === AUTH_KEY_SECRET;
};
function authorizeRequest(request, key) {
switch (request.method) {
case 'PUT':
case 'DELETE':
return hasValidHeader(request);
case 'GET':
return ALLOW_LIST.includes(key);
default:
return false;
}
}
async function handleRequest(request) {
const url = new URL(request.url);
const key = url.pathname.slice(1);
if (!authorizeRequest(request, key)) {
return new Response('Forbidden', { status: 403 });
}
// ...
For this to work, you need to create a secret via Wrangler:
wrangler secret put AUTH_KEY_SECRET
This command will prompt you to enter a secret in your terminal:
wrangler secret put AUTH_KEY_SECRET
Enter the secret text you'd like assigned to the variable AUTH_KEY_SECRET on the script named <YOUR_WORKER_NAME>:
*********
🌀 Creating the secret for script name <YOUR_WORKER_NAME>
✨ Success! Uploaded secret AUTH_KEY_SECRET.
This secret is now available as the global variable AUTH_KEY_SECRET
in your Worker.
7. Deploy your bucket
With your Worker and bucket set up, run the wrangler publish
command
to deploy to Cloudflare’s global network:
wrangler publish
You can verify your authorization logic is working through the following commands, using your deployed Worker endpoint:
# Attempt to write an object without providing the "X-Custom-Auth-Key" header
$ curl https://your-worker.dev/cat-pic.jpg -X PUT --header --data 'test'
#=> Forbidden
# Expected because header was missing
# Attempt to write an object with the wrong "X-Custom-Auth-Key" header value
$ curl https://your-worker.dev/cat-pic.jpg -X PUT --header "X-Custom-Auth-Key: hotdog" --data 'test'
#=> Forbidden
# Expected because header value did not match the AUTH_KEY_SECRET value
# Attempt to write an object with the correct "X-Custom-Auth-Key" header value
# Note: Assume that "*********" is the value of your AUTH_KEY_SECRET Wrangler secret
$ curl https://your-worker.dev/cat-pic.jpg -X PUT --header "X-Custom-Auth-Key: *********" --data 'test'
#=> Put cat-pic1.jpg successfully!
# Attempt to read object called "foo"
$ curl https://your-worker.dev/foo
#=> Forbidden
# Expected because "foo" is not in the ALLOW_LIST
# Attempt to read an object called "cat-pic.jpg"
$ curl https://your-worker.dev/cat-pic.jpg
#=> test
# Note: This is the value that was successfully PUT above
By completing this guide, you have successfully installed Wrangler and deployed your R2 bucket to Cloudflare.