Summary: We present the most secure way to create an S3 bucket with the required permissions to function as a static content store, how to create and configure an SSL certificate to ensure content delivery is done securely, and finally how to configure Amazon CloudFront to that functions as the CDN of your website and loads the content from the S3 bucket created in the first part.
Create an S3 bucket for the storage of the static content of a website
Go to the AWS console, select the S3 service, and select the Create new bucket option.
Give the bucket a name (I recommend using the same name that your CDN subdomain will have to make it easier for you to identify. Eg: if the site is example.com and you want to name your CDN cdn.example.com use this same name for the bucket.
Initial bucket configuration:
- Select the area where you will be staying. Important: If your site is hosted on Amazon Lightsail, the bucket and the lightsail instance must be in the same zone
- In the Bucket Configuration section, make sure to select the ACLs disabled (recommended) option
- Then in Block Public Access settings for this bucket select the option Block all public access
- Keep the rest of the options as default and click create bucket, (the last options should look like this)
Create and configure an SSL certificate to ensure content delivery is done securely to your users
Once in the AWS console, look for the Amazon Certificate Manager (ACM) service. This service is used to create public SSL certificates and its configuration is extremely easy.
AWS Certificate Manager CloudFront
Once in ACM select the "Request" option select the "Request a public certificate" option and then click Next
CloudFront subdomain
- Write the name of the subdomain that you will use as CDN (cdn.example.com in this example)
- In Validation method select the DNS option
- and as algorithm selects RSA 2048
CloudFront certificate
- Click on request and look for the new certificate in the list that appears (if it does not appear, just refresh the page)
- Select the certificate and you will see the details
- You must create a new CNAME record in your DNS. The name and value of this registry appear in the “Domains” section
A green mark with the text "verified" will appear when the new record is active, this may take a few minutes. If you registered your domain using the Amazon Route 53 service, all you have to do is click on the “Create records in Route 53” option and AWS will take care of creating the record.
Create Amazon CloudFront Distribution to Serve Content Residing in S3
First, go to the AWS CloudFront service and select "Create New Distribution" on the next screen you must enter the following configuration:
AWS CloudFront control settings
In Origin > Origin domain you only have to select the S3 bucket in which you are going to store the static content
In Origin > Origin access select the option “Origin access control settings” and “Create control settings”. You will see a notice explaining that you must update the bucket permissions, this is done when you finish creating the distribution
AWS CloudFront cache policy
Then in “Default cache behavior” make sure to check “redirect http to https” and Allowed HTTP methods GET, HEAD, OPTIONS, PUT, POST, PATCH, DELETE and select OPTIONS in the next part “Cache HTTP methods”
In the “Cache key and origin requests” section, check the “Cache policy and origin request policy” option, right here select the CachingOptimized option in “Cache Policy” and “CORS-S3Origin” in Origin request Policy
At the end of this same section, in “Response headers policy” select CORS-and-SecurityHeadersPolicy
Then, in the setting section, select the one that best suits your target audience from the 3 options. We recommend “Use all edge locations” to guarantee the best possible performance.
AWS CloudFront alternate domain name (CNAME)
In the “Alternate domain name (CNAME)” section, select Add item and write the name of the subdomain that you will use for your CDN. In this example it would be “cdn.example.com”
Then in the dropdown that appears below select the SSL certificate that you created using ACM
Support for CloudFront http2 and http3
In “Supported HTTP versions” mark the support for http/2 and http/3
Click on “Create distribution”
Almost there… All that remains is to update your DNS and S3 bucket policy.
Update the CloudFront DNS CNAME
In CloudFront, select the distribution you created and copy the value that appears in “Distribution domain name”. Create a new CNAME record in your DNS with the following values
TYPE | YAM | VALUE |
CNAME | cdn.example.com | value you copied from “Distribution domain name”* It must have the structure: lettersandnumbers.cloudfront.net* |
AWS CloudFront S3 bucket policy
Lastly, with the distribution selected, go to the “Origins” tab, mark the origin that appears and click the Edit button. Almost at the beginning, in the "Origin access" section, look at the notice that appears and click on the "Copy policy" option to copy to the clipboard the policy that allows access to this Amazon CloudFront distribution to the S3 bucket and then click on the link below with the text “Go to S3 bucket permissions”.
This will take you to the S3 bucket that you have selected as the origin of your Amazon CloudFront distribution. Scroll down until you find the “Bucket policy” section and click edit. Paste the content of the clipboard (Ctrl + V or Right click > paste), check that the indentation is correct (it usually happens that it does not copy well and this can cause you to not be able to save the changes). The first character must be "{" so you must delete any white space that appears before this symbol.
Checking the operation of the AWS CloudFront service
This is it, your CDN with Amazon CloudFront is now created. To test that all the configuration is correct in your S3 bucket, select the Objects tab, drag any image from your computer to that tab. Open a new tab in your browser and type the URL of the image you uploaded to your CDN which would have the following path:
https://[subdomain]/[upload_image]
Suppose that the image is called img-1.png, then following the same example with which we have been working, the route would be: https://cdn.example.com/img-1.png