How to replicate Amazon S3 Static website hosting behaviour with R2 and save money

Denis Chaschin
6 min readMay 5, 2023

Migrating from Amazon S3 to Cloudflare R2: A Comprehensive Guide

static website hosting provider, orange color, computer graphics, ultra detailed, cinematic lighting, small people figures moving small boxes between large servers buildings, inspiration, cloudflare, amazon s3, city of computers and microchips, cloud infrastructure, people, eye catchy, attractive, serverless architecture scheme
a city of serverless infrastructure

In this article, we will guide you through the process of migrating your static website hosted on Amazon S3 to Cloudflare R2. If you’re already using Cloudflare for your domain hosting and CDN, this migration will be a breeze. By following the steps below, you can easily replicate the Amazon S3 static website hosting behaviour with R2, save money, and enjoy a seamless experience.

Pricing Comparison

To help you understand the cost savings of migrating from Amazon S3 to Cloudflare R2, let’s compare the pricing using a simple mobile application website as an example.

Assumptions

Let’s say you store 5GB of data which is more than enough for a simple static website, you perform 500K writing operations and 10M reading operations.

The comparison is made by using a calculator on the Cloudflare website: https://r2-calculator.cloudflare.com/

Amazon S3 storage would cost you $6.48/mo while Cloudflare R2 would charge you $0/mo. Not sure about you, but for my purpose this works more than great.

For reference:

R2 pricing: https://developers.cloudflare.com/r2/pricing/

AWS pricing: https://aws.amazon.com/ru/s3/pricing/

S3 to R2 migration process step-by-step

These steps will guide you through the process of creating an R2 bucket and setting up the rules for the website so that it behaves similarly to S3 static websites. Screenshots are here for additional clarity.

Step 1: Creating an R2 Bucket

To begin, navigate to Cloudflare R2 and click the “Create bucket” button to create a new R2 bucket for your website. You can always check bucket information on the bucket settings page — we will need it later.

Cloudflare R2. Create new bucket button screenshot.
Create a new bucket in R2

Step 2: Upload Website Content

To interact with R2 using the command-line interface (CLI), you can use the familiar AWS CLI with some modifications. Follow the steps below to upload your website content:

  1. Create R2 credentials for the CLI. Navigate to R2 > Manage R2 API Tokens > Create API token. Type a new token name and under “Permissions”, select “Read” or “Edit”. More details about the credentials can be found here: https://developers.cloudflare.com/r2/api/s3/tokens/.
  2. Configure a new profile for CLI. Run the following command to create a new profile (using r2 name as an example) that allows you to work with both AWS and R2:
aws configure --profile r2

3. Input the required information. The terminal will prompt you for the following details. Use the values from the credentials you created earlier.

AWS Access Key ID [None]:      <access_key_id>
AWS Secret Access Key [None]: <access_key_secret>
Default region name [None]: auto
Default output format [None]: json

4. Upload your website content. Navigate to the directory containing your static website files using the cd command

cd <path to directory>

Initiate the uploading process with the following aws command:

aws s3 sync ./build s3://<name of your bucket>/ - acl public-read - endpoint-url https://<your Cloudflare endpoint URL for the bucket, found in the bucket settings>.cloudflarestorage.com - profile r2

5. Wait for the upload to complete.

For more details on uploading website content using AWS CLI, refer to the official documentation: https://developers.cloudflare.com/r2/examples/aws/aws-cli/.

Step 3: Connecting the Domain

Since your domain is already on Cloudflare, connecting it to your R2 bucket is straightforward. Navigate to R2 bucket settings > Public access > Custom domains > Connect domain.

Cloudflare R2. Use Connect Domain button to connect custom domain name to R2 bucket
Connect domain to Cloudflare R2

Select your domain, and Cloudflare will suggest a new DNS record that points the domain to the bucket.

Cloudflare suggests DNS records change to connect R2 to the domain

Note: at the moment of writing domain names with Cyrillic letters are not supported by R2. I’ve tried typing a punny code version and tried connecting using CNAME record. Both ways failed for different reasons. S3 doesn’t work with Cyrillic letters in the domain names either, so not a big difference in this.

Cloudflare might show you an error domain already has a CNAME DNS record. In this case, you need to remove the existing CNAME record in the DNS settings for the domain.

Error: DNS record for this domain already exists on zone. (Code: 10056)
If you see this error — you need to remove CNAME record from DNS records in Cloudflare

Once connected, test the website by opening https://<your-website domain>/index.html.

Note that you need to specify the exact HTML page file name for now, as we’ll configure the default behaviour in the next step.

Step 4: Replicating the Index Document S3 Setting

Firstly, let’s teach R2 to load index.html when the website URL contains a path to a directory. This is very common behaviour and S3 does so by default.

Chose Rules from the Cloudflare website settings menu
The rules section of Cloudflare website settings
  1. Navigate to “Transform Rules” in your website settings in Cloudflare
  2. Create a new rewrite rule named “Use index.html files”
  3. For the condition, we will use URI Path that ends with “/”. This produces (ends_with(http.request.uri.path, “/”)) in the expression preview field.
Create new Rewrite URL Rule. Custom filter expression. When incoming requests match. URI Path ends with “/”
Creating a new Rewrite URL Rule in Cloudflare

4. Set Rewrite parameters — Path to dynamic concat(http.request.uri.path, “index.html”)

Setting Rewrite URL Rule to Dynamic Path rewrite

5. Click the “Deploy” button.

Now website should start opening the index.html page by default: https://<your-website domain>. Test that it works correctly, and follow the steps again if it doesn’t.

Another rule that needs to be created is in the Redirect Rules section. This is so that when user types something like https://example.com/main — the browser would be redirected to https://example.com/main/ (notice “/” at the end, it’s important as this refers to a directory) and then Cloudflare would load index.html from the directory according to the previously created rule. Follow these steps:

  1. Go to “Redirect Rules” in Cloudflare.
  2. Create a new rule named “Adding “/” at the end when missing”.
  3. Add condition URI Path contains “.” — this is not to override files and some special folders like .well-known if used
  4. Click “And”, and add the condition URI Path ends with “/” — this is to treat files without extensions as folders, as in the most popular cases is true. You might need to write your custom rules instead if it is not your case.
Creating a dynamic redirect rule in Cloudflare to treat files without extensions as directories

5. These two rules will result in the expression: (not http.request.uri.path contains “.” and not ends_with(http.request.uri.path, “/”)), (just for you to double check)

6. URL redirect part of rule we chose Dynamic expression concat(http.request.uri.path, “/”) with a 301 status code

Setting the URL Redirect part of rule

7. Click the “Deploy” button.

Congratulations! Well done 👍 Check now how your website works on Cloudflare R2. And The S3 bucket can be deleted if everything is alright.

A female waiting for website to load after moving from S3 to R2
A web developer checking that their website works after migrating from Amazon S3 to Cloudflare R2

That’s it! You have successfully migrated your static website from Amazon S3 to Cloudflare R2, replicating the desired behaviour, and potentially saving money on your hosting costs.

I hope this guide has been helpful in walking you through the process. If you found this article beneficial, please consider following my Medium blog. It costs nothing for you but is immensely rewarding for me, as it helps me continue to share valuable content with readers like you. Thank you for your support, and happy hosting!

--

--

Denis Chaschin

Creating iOS apps. Living in Sydney, originally from Saint-Petersburg