This guide provides detailed instructions on setting up a static website using AWS S3, Route 53, and CloudFront, including enabling HTTPS. Involving several key steps, including S3 bucket setup, domain configuration, and implementing secure HTTPS connections.
if you're ok with that long long url, stop here.
If you don't want an unattractive domain name:
Purchase a domain, set a CNAME record pointing to your S3 bucket's website endpoint
aws CNAME [your s3 endpoint]
if you're ok with adding CNAME to spec s3 endpoint everytime, stop here.
aws NS ns-464.awsdns-58.com aws NS ns-723.awsdns-26.net aws NS ns-1767.awsdns-28.co.uk aws NS ns-1135.awsdns-13.org
if no HTTPS is ok for you. Skip next.
When adding SSL, there's a step to pause and add a TXT Record in Route53 (Note1)
brew install certbot sudo certbot certonly --manual --preferred-challenges=dns -d aws.domain.com # Some guidelines to review, keep saying y # TXT record Please deploy a DNS TXT record under the name: **_acme-challenge**.domain.com. with the following value: zA7PnMP...bAf9oUUdQT0
Upon success, it tells you files are generated in /etc/letsencrypt/live/aws.domain.com/. You'll need two files from this folder:
fullchain.pem
privkey.pem
$ sudo cat /etc/letsencrypt/live/aws.domain.com/README This directory contains your keys and certificates. `privkey.pem` : the private key for your certificate. `fullchain.pem`: the certificate file used in most server software. `chain.pem` : used for OCSP stapling in Nginx >=1.3.7. `cert.pem` : will break many server configurations, and should not be used without reading further documentation (see link below). $ sudo cat /etc/letsencrypt/live/aws.domain.com/fullchain.pem -----BEGIN CERTIFICATE----- # put into Certificate body -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- # put to Certificate chain *- optional* -----END CERTIFICATE-----
fullchain.pem
-----BEGIN CERTIFICATE----- # put into Certificate body -----END CERTIFICATE-----
privkey.pem
-----BEGIN PRIVATE KEY----- ... -----END PRIVATE KEY-----
fullchain.pem
-----BEGIN CERTIFICATE----- # put to Certificate chain *- optional* -----END CERTIFICATE-----
if you see optional then don't fill, the step 4.2 will failed because it's not a trusted CA.
Change your original domain.com A record from pointing to S3 resource to pointing to CloudFront
Certificates are valid for 90 days, so repeat steps 2 to 4 after expiration
If you don't want your S3 website endpoint to be directly accessible (http://your-bucket.s3-website-us-east-1.amazonaws.com/), even if you've already configured your own domain name with Route 53 and set up CloudFront, and you only want to access S3 through CloudFront while blocking all other access:
In CloudFront > Origin access > Create Control Setting, simply create it. This step is straightforward.
function handler(event) { var request = event.request; if (request.uri === '/') { request.uri = '/index.html'; } else if (request.uri.endsWith('/')) { request.uri += 'index.html'; } return request; }
But from your perspective, you won't be aware that CloudFront has modified the request.uri for you.
{ "Version": "2008-10-17", "Id": "PolicyForCloudFrontPrivateContent", "Statement": [ { "Sid": "AllowCloudFrontServicePrincipal", "Effect": "Allow", "Principal": { "Service": "cloudfront.amazonaws.com" }, "Action": "s3:GetObject", "Resource": "arn:aws:s3:::<your-bucket>/*", "Condition": { "StringEquals": { "AWS:SourceArn": "arn:aws:cloudfront::263386971159:distribution/<distribution id>" } } } ] }
Remember: if you don't set up the Origin Access Control (OAC) for your bucket policy, even if you whitelist your CloudFront distribution, it will be meaningless. So, always remember to do step 1.
This configuration ensures that your S3 content can only be accessed through the specified CloudFront Distribution, providing enhanced security and access control.
What If: Your S3 bucket has been updated, but the changes are not being reflected when accessed through your domain.
To resolve this, you need to create an invalidation in CloudFront and specify that all files should be invalidated so that they are re-fetched.
read: AWS cloudfront not updating on update of files in S3The TXT record in Step 3 should be set in Route53, not your domain provider's
Because your domain is pointing to AWS Name Server, it means this domain's resolution is handled by Route53
Although the domain is specified when adding an SSL certificate, in CloudFront Distribution you still need to explicitly state which domain needs HTTPS protection in Alternate domain name. If not specified in CloudFront Distribution, even with a complete SSL certificate, it won't protect you.
Regarding AWS resource configuration, you're often told to set the bucket name equal to the domain name, same for Route 53. Then you might wonder if one step goes wrong, will the whole setup fail?
Scenario: bucket name is different
subbbb.aws.domain.com # point to subbbb.aws.domain.com.s3-websit…
anothersub.aws.domain.com # point to subbbb.aws.domain.com.s3-websit…
# 404 Not Found - Code: NoSuchBucket - Message: The specified bucket does not exist - BucketName: **anothersub**.domain.com - RequestId: 6MTX7N8Z7KNGPBNP - HostId: JPiP....mofF7c=
While DNS resolves anothersub.aws.jialin00.com to the S3 endpoint of subbbb.aws.domain.com.s3-websit…, the S3 service itself remains unaware of this DNS mapping. In AWS, DNS and S3 storage are decoupled. This means they work separately, even when connected.
What If: Route 53 Hosted Zone is set as domain.com, and inside it has aws.domain.com A record Alias to CloudFront or S3 Resource endpoint. If domain.com is currently hosted elsewhere like Github, will it affect the entire configuration?
Truth is: Your domain.com in the domain provider DNS already has an A record to Github Name Server IP. In this sense, Route53 having domain.com won't take over. The domain provider DNS points to Github, and won't be taken over by AWS Route53's Hosted Zone having the same name for domain.com resolution.
So If your Route53 Hosted Zone is aws.domain.com, it won't care about notaws.domain.com or any other subdomains of domain.com. Route 53 only mind its own business.