Deploy static websites Cloudflare+S3

Guide to deploy a static website with s3 bucket, backed by cloudflare.

Screenshot-2021-09-10-at-1.10.53-PM

  • Create S3 bucket with the name as intended domain. In this blogpost, I'm using https://travelsanta.com

  • Enable static website hosting:
    Screenshot-2021-09-10-at-12.33.40-PM

  • Allow Public Access:
    Screenshot-2021-09-10-at-1.21.28-PM

  • Use the bucket policy on S3:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "PublicReadGetObject",
            "Effect": "Allow",
            "Principal": "*",
            "Action": "s3:GetObject",
            "Resource": "arn:aws:s3:::travelsanta.com/*",
            "Condition": {
                "IpAddress": {
                    "aws:SourceIp": [
                        "173.245.48.0/20",
                        "103.21.244.0/22",
                        "103.22.200.0/22",
                        "103.31.4.0/22",
                        "141.101.64.0/18",
                        "108.162.192.0/18",
                        "190.93.240.0/20",
                        "188.114.96.0/20",
                        "197.234.240.0/22",
                        "198.41.128.0/17",
                        "162.158.0.0/15",
                        "104.16.0.0/13",
                        "104.24.0.0/14",
                        "172.64.0.0/13",
                        "131.0.72.0/22",
                        "2400:cb00::/32",
                        "2606:4700::/32",
                        "2803:f800::/32",
                        "2405:b500::/32",
                        "2405:8100::/32",
                        "2a06:98c0::/29",
                        "2c0f:f248::/32"
                    ]
                }
            }
        }
    ]
}

For latest list of ipv4 and ipv6 address of Cloudflare, refer https://www.cloudflare.com/ips-v4 and https://www.cloudflare.com/ips-v6

  • Login to cloudflare and add a dns entry for the intended domain name, with CNAME entry with value as s3 bucket. The format value is travelsanta.com.s3-website.AWS_REGION.amazonaws.comScreenshot-2021-09-10-at-1.26.20-PM

Access the website with https://travelsanta.com and you'll have https, CDN, DDOS protection, etc.
The whole setup would be free of cost if the traffic is low.

Hope you've a secure static website and keep making internet awesome!

Terraform script for the same, using resources alone:

 provider "aws" {
   region = var.region
 }

 terraform {
  required_providers {
    cloudflare = {
      source = "cloudflare/cloudflare"
      version = "~> 3.0"
    }
  }
 }

 provider "cloudflare" {
   email   = var.cloudflare_email #email you use for logging into cloudflare
   api_key = var.cloudflare_api_key #generate api key from cloudflare dashboard
 }

 resource "aws_s3_bucket" "bucket" {
   bucket = "travelsanta.com"
   acl    = "public-read"
   policy = <<POLICY
 {
     "Version": "2012-10-17",
     "Statement": [
         {
             "Sid": "PublicReadGetObject",
             "Effect": "Allow",
             "Principal": "*",
             "Action": "s3:GetObject",
             "Resource": "arn:aws:s3:::travelsanta.com/*",
             "Condition": {
                 "IpAddress": {
                     "aws:SourceIp": [
                         "173.245.48.0/20",
                         "103.21.244.0/22",
                         "103.22.200.0/22",
                         "103.31.4.0/22",
                         "141.101.64.0/18",
                         "108.162.192.0/18",
                         "190.93.240.0/20",
                         "188.114.96.0/20",
                         "197.234.240.0/22",
                         "198.41.128.0/17",
                         "162.158.0.0/15",
                         "104.16.0.0/13",
                         "104.24.0.0/14",
                         "172.64.0.0/13",
                         "131.0.72.0/22",
                         "2400:cb00::/32",
                         "2606:4700::/32",
                         "2803:f800::/32",
                         "2405:b500::/32",
                         "2405:8100::/32",
                         "2a06:98c0::/29",
                         "2c0f:f248::/32"
                     ]
                 }
             }
         }
     ]
 }
 POLICY
   website {
     index_document = "index.html"
     error_document = "404.html"
   }
 }

 resource "cloudflare_record" "root_domain" {
   zone_id = "SECRET_VALUE" #Get this from cloudflare via API call
   name    = "travelsanta.com"
   value   = "travelsanta.s3-website.ap-south-1.amazonaws.com"
   type    = "CNAME"
   proxied = true
 }