How to access a private S3 bucket via Cloudflare
Tags: cloudflare, aws, s3
Published: 2023-08-01 20:09:39

![Hero Image Cloudflare + S3](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/arozmwdfodr92apayawz.png)
In this blog post, we'll explore how to access a private S3 bucket via Cloudflare. Most of the tutorials on the internet suggest that you need to enable static hosting on your S3 bucket and use the same name for your bucket and your domain. For example, if your domain is `example.com`, your bucket name should be `example.com` too.

However, this approach has some drawbacks. Amazon S3 website endpoints do not support HTTPS. Using the same name for your bucket and your domain is not always possible or desirable. Bucket names have to be unique across all of AWS, so you might not get the name you want. Also, you might want to map multiple domains to the same bucket, or use an existing bucket with a different domain name.

## The solution

In this demo, I will show you how to access a private S3 bucket with a different name than your domain via Cloudflare. Let’s assume that we have a bucket named `test-bucket` in the `eu-central-1` region, and we want to map it to our domain `test.ashish.link`.

![Cloudflare dashboard to add CNAME records](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/h4lip2mbzclk7f2x97hv.png)


### Step 1: Add a CNAME record on Cloudflare

The first step is to add a CNAME record on Cloudflare that points to the S3 endpoint of our bucket. The S3 endpoint has the format `<bucket-name>.s3.<region>.amazonaws.com`. In our case, it is `test-bucket.s3.eu-central-1.amazonaws.com`.


###Step 2: Add a bucket policy for Cloudflare IPs

The second step is to add a bucket policy on our S3 bucket that allows Cloudflare IPs to access our objects. You can find the list of Cloudflare IPs on their website. The bucket policy should look something like this:
```
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "AllowCloudFlareIP",
            "Effect": "Allow",
            "Principal": "*",
            "Action": "s3:GetObject",
            "Resource": [
                "arn:aws:s3:::test-bucket",
                "arn:aws:s3:::test-bucket/*"
            ],
            "Condition": {
                "IpAddress": {
                    "aws:SourceIp": [
                        <list of ips>
                    ]
                }
            }
        }
    ]
}
```
This policy grants read access to our bucket and its objects only to the requests that come from Cloudflare IPs. You can find the list of cloudflare IPs from [here](https://www.cloudflare.com/ips/).


###Step 3: Set a Host header override on Cloudflare

The final step is to set a Host header override on Cloudflare that tells S3 which bucket we want to access. By default, S3 uses the Host header of the request to determine the bucket name. For example, if we request `example.com/image`.jpg, S3 will look for a bucket named `example.com`. However, since our bucket has a different name, we need to override this behavior and tell S3 to use `test-bucket.s3.eu-central-1.amazonaws.com `as the Host header instead.
To do this, we need to create a _Origin rule_ on Cloudflare that sets the Host header override as follows:
This origin rule tells Cloudflare to forward all requests for `test.ashish.link/*` to our S3 endpoint with the correct Host header.

![Cloudflare dashboard to add origin rules](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/a28qaxl6s6ay8dlwbjn0.png)


###Conclusion:

By following these steps, you can successfully access a private S3 bucket via Cloudflare, regardless of whether your bucket name matches your domain name or not. This setup allows you to securely and efficiently serve your assets while maximizing control over access.

I hope you found this post helpful. If you have any questions or feedback, please leave a comment below.