Create a CloudFront distribution
With CloudFront, Amazon created a CDN (Content Delivery Network), which can be used for serving static files in a fast manner. The actual files are being managed at one single place, but are provided by different servers. The particular server for a request is chosen based on the requester’s location. If a US-based client is requesting a static file from the CDN, the file is being provided by a server based somewhere in the USA. However, if the client’s location is Germany, the file won’t be served from a US-based, but a German server. This is done in order to save loading-time.
The servers, which hold a cached version of the static files are called Edge Locations. In the image below, each blue dot stands for at least one Edge Location. Some dots stand for up to 3 of them. More details about the AWS-Regions and Edge Locations can be found here.
|NORAM||US||New York, NY||3|
|NORAM||US||Palo Alto, CA||1|
|NORAM||US||San Jose, CA||1|
|NORAM||US||South Bend, IN||1|
|NORAM||US||St. Louis, MO||1|
|LATAM||BR||Rio de Janeiro||1|
The static files for the distribution need to be stored at some place. There are also other concepts like e.g. origin pull, but here I will focus on a S3-bucket. Therefore, you first need to create a S3-bucket. It’s a best practice to give the S3-bucket the same name as the domain-name we use later on.
With the command above you can create a S3-bucket with the name aws-blog.io. Keep in mind, that a S3-bucket-name needs to be unique for the whole service and not only your account. The command below is used to delete the bucket, in case it’s not needed anymore. That statement contains a –force at the end, which means that S3 will delete the bucket, even it has content within it. I normally do include the force-option, because I already have decided to delete a bucket, even if it contains data.
For the CloudFront-distribution to work properly, there needs to be some access-rights adjustments. With the following bucket-policy, a download of any file within that bucket is allowed for any user. For a more professional setup, this should get reducded to CloudFront-sources / Principals only.
Just edit the following JSON-statement accordingly and save it as bucket-policy.json. It actually can be named anything, but within this post I will reference it.
Now that you have an adjusted bucket-policy, it needs to be applied on the bucket itself. This is done by using aws s3api, as stated in the command below.
Everything is now setup from a S3-environment point-of-view. The only thing that’s missing is the actual data respectively the static files which later on should get served by CloudFront. With the next command, a local folder and a S3-bucket are getting synchronized. Here, the source is the local folder /home/flo/aws-blog.io/_site and the target is the s3-bucket aws-blog.io. Sources and targets can both be either local folders or S3-buckets. The –delete amendment will delete every file in the target, if it’s not existent within the source.
Create a web-distribution
During both creation-modes (Method 1 and Method 2), the following values in the JSON-statement need to get adjusted to your individual account:
- DistributionConfig.CallerReference (I normally set here the current timestamp, however it needs to be unique within all your previous AWS-API-calls)
If you chose Method 1, you need to specify more parameters, as we here generate a default-distribution-config with the command amendment –generate-cli-skeleton, whereas for Method 2 we use a pre-configured config-file.
For this alternative of setting up a CloudFront-distribution, we need a software called jq, which helps editing json-files. It does make sense to install that software now, as we also need it later on.
Creating a DNS-record for distribution
This setup is intended for domains hosted within Route53. It’s also possible with other hosters. There you just need to create a CNAME for your distributions DNS-name. If you don’t have a domain within Route53 yet, there’s already a blog-post on who to set that up. You can find that post here. For the creation of the CNAME-DNS entries, it’s advised to wait until the status of the distribution has changed from In Progress to Deployed. The state of all distributions can be checked with aws cloudfront list-distributions, as described below.
You then can create a file called aws-blog.io-cloudfront-alias.json (you actually can name it anything, but I’ll reference it later on), copy & paste the following JSON-statement and edit accordingly. The mentioned DNSName of the distribution is also in the command above, which you just used to check the distribution’s state.
NOTE: The HostedZoneId in AliasTarget is AWS’s HostedZoneId of CloudFront, so you need so set that specific one with the ID Z2FDTNDATAQYW2 and not your own one.
The previously created JSON-statement gets used as a parameter for the next command. The only other unique parameter is the hosted-zone-id.
In order to delete a distribution, it first needs to get in a disabled-state. After this step had been done, it can get deleted.
After the installation of the mentioned tools, you can download the current distribution-config and set enabled: false in it. This is all done with the next command-block. The only parameter that needs to get adjusted is the –id, which you can get with a listing of all domains as previously done. For the update-process you need the value of ETag, which will be listed with the very first command.
The status of the distribution needs to be Deployed, in order to proceed. You can always check the status of all of your distributions with the following command, which just lists all distributions and their states.
When the state of the distribution has changed to Deployed, you can trigger the actual deletion with the following command.
An invalidations is always needed, when a file has been adjusted before it’s specified expiration-date. When an invalidation is triggered in CloudFront, all cached versions of the files on all Edge Locations are getting renewed. Big websites with many deployments should rather look into an asset-pipeline concept with hashes as filenames, because after 1.000 invalidations per month, you will get charged for it.
NOTE: An invalidation call like the one below needs an unique CallerReference. That one needs to be specific for all calls to the AWS-API. As I actually don’t use the CallerReference, I just set a current timestamp for it.