How to deploy a static website with CloudFront and a private S3 bucket
In this article we shown how to deploy a static website with CloudFront by keeping the S3 bucket public and making use of S3 website endpoint. Here we will show how to do it with a private bucket.
1. Create S3 bucket
- Go to S3
- Click on Create bucket
- Select Block all public access
- Save
2. Create a CloudFront distribution
- Go to CloudFront and create a new distribution
- Select the origin domain to be the S3 bucket containing your static website and DO NOT click on Use website endpoint
- Set origin access to Origin access control settings (OAC) and select your bucket
- Leave all the other options as default and save
3. Update S3 policy
- After saving, you will be shown a banner where you can copy the policy that you have to save in S3
- Go to your S3 bucket, click on the Permissions tab, here you can find the bucket policy to edit
- Paste the policy copied from Cloudfront, it should look like this:
{ "Version": "2008-10-17", "Id": "PolicyForCloudFrontPrivateContent", "Statement": [ { "Sid": "AllowCloudFrontServicePrincipal", "Effect": "Allow", "Principal": { "Service": "cloudfront.amazonaws.com" }, "Action": "s3:GetObject", "Resource": "arn:aws:s3:::<bucket-name>/*", "Condition": { "StringEquals": { "AWS:SourceArn": "arn:aws:cloudfront::<account-id>:distribution/<distribution-id>" } } } ] }
- After saving, your website won’t be accessible from S3 directly, you will get a
403 Forbidden
orAccess Denied
error since you’re enforcing the bucket to be accessible only by CloudFront - At this point you should be able to access the website through the CloudFront endpoint. You can find it in the distribution under General > Details > Distribution domain name. If you have an
Access Denied
error, double check in the Origins setting that the Origin is configured to use the S3 website endpoint, and not the S3 bucket - If you do any change to CloudFront config, notice that the content is cached, so you will probably not see any changes until the TTL expired. To speed up this process, you can create an Invalidation
4. Redirect routes to index.html
Since you’re not using the S3 static website feature, CloudFront will not redirect the routes to index.html
automatically. For example, you might want to access the page contained in about/index.html
by going on the URL www.your-site.com/about
instead of www.your-site.com/about/index.html
. In order to allow this, you will need to create a custom function
- Go to CloudFront
- On the left menu, click on Functions
- Click on Create function
- Choose a name for the function and click on Next
- Copy the following code in the
Build
tabfunction handler(event) { var request = event.request; var uri = request.uri; if (uri.endsWith('/')) { request.uri += 'index.html'; } else if (!uri.includes('.')) { request.uri += '/index.html'; } return request; }
- Go on the Publish tab and click on Publish Function
- Click on Add association
- Select your distribution and the cache behaviour, and set Event type to Viewer Request
After adding the association, create a Cache Invalidation and you will be able to access your website correctly after it’s completed
5. Use a custom domain
- Go to Route53, click on Hosted zone and then click on the hosted zone of your domain
- Click on Create record and apply the following configuration
- Record type: A
- Alias: On
- Route traffic to: Alias to CloudFront distribution
- Select your CloudFront distribution
Now create another record to redirect www
to the same domain, with the following config:
- Record type: A
- Alias: On
- Route traffic to: Alias to another record in this hosted zone
- Select the record that you created in the previous step
6. Configure SSL
First thing, you need to create a SSL certificate:
- Go to AWS Certificate Manager (ACM)
- Click on Request certificate and configure it with the following:
- Certificate type: Request a public certificate
- Fully qualified domain name: your-website-domain.com
- Click on Add another name to this certificate and set the other name as
www.your-website-domain.com
- Validation method: DNS Validation
- Click on Request
Now you have to attach your certificate to CloudFront:
- Go to your CloudFront distribution, click on General and then under the Settings section click on Edit
- Apply the following config:
- Alternate domain name (CNAME): add the domains specified in your ACM certificate
- Custom SSL certificate: select your ACM certificate
- Click on Save
To redirect traffic from HTTP to HTTPS:
- Go to Behaviours. There should be only one behaviour here, select it and then click on Edit
- Set Viewer protocol policy to Redirect HTTP to HTTPS
- Click on Save
Conclusion
Congratulations, you have successfully created a website with a private S3 bucket and CloudFront! Thanks to CloudFront your user will experience much less latency, due to to the AWS edge locations, where the content will be cached.