1. Set Up S3 Bucket
Create Bucket
- Select “Create bucket”
- For bucket name, it has to match your domain name including the www. So it has to be www.<your website name>.com. If it doesn’t match your domain name, pretty sure none of this is going to work.
- Optional (this is only for testing purposes if you wanted it, change this back once you have everything working, which I instruct you through down in the Extra Steps section way down below): Uncheck Block all public access, and select “I acknowledge that the current settings might result in this bucket and the objects within becoming public”. You should definitely change this back to block once everything is connected to your domain, but for now, this will allow you to make sure that at least your S3 bucket is working.
- You don’t have to add a tag, but for naming purposes and making it easier on yourself, make a tag. For key, call it “Name” and for Value call it <your website>-Bucket. No need to have the "www" in the Tag value, again just a name to help you.
- Leave all other values default.
- Select "Create Bucket"
Add Files
- Click into your new bucket from the home page to go into the details.
- And now upload your index.html and error.html file, along with any other additional files.
- Select all. Make them all public by selecting "Actions" and selecting "Make public". As of Nov 2021, AWS has now changed this, and you should do this in a policy rather than here, but you now have to choose "Make public using ACL" which requires going into your bucket's Permissions -> Object Ownership and selecting "ACLS enabled".
Properties
- In Properties down at the bottom, under "Static website hosting" select "Edit".
- Enable static website hosting. And put in "index.html" and "error.html" for index and error document respectively.
Optional but required to complete the previous optional task (so for testing your S3 bucket out): Permissions
You will eventually only allow permission for an OAI, as mentioned earlier with blocking that you do not want people to be able to reach your S3 bucket directly, and only reach your website through your domain name that will have https when S3 buckets are http, but for testing purposes if you want to, go ahead and do the following.
In Permissions, in Bucket policy, select edit and put this, again we will change this once we have an OAI:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "PublicReadGetObject",
"Effect": "Allow",
"Principal": "*",
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::www.<your website name>.com/*"
}
]
}
Final Notes for S3 Bucket
If you forget to enable static website hosting before connecting to your CloudFront distribution, it will result in this error when trying to view your website:
If this happens, you can try reconnecting your CloudFront distribution to your S3 bucket to re-register things so to speak. Don't know why this is.
2. Certificate Manager
Head over to certificate manager
VERY IMPORTANT: Change from your current location to US East (N. Virginia) us-east-1. The certificate must be requested from this region, no matter what. If you don’t, and instead have Northern California for example, when you move onto the next step which is Cloudfront, your ssl certificate will not show up and you will not be able to complete your HTTPS setup. Not entirely sure why this is, but to use CloudFront, the region for your certificate must be US East (N. Virginia) us-east-1.
Make a request
- Select "Request".
- For "Certificate Type" leave it on "Request a public certificate".
- For "Fully qualified domain name" put both your <your website name>.com and add a second one being www.<your website name>.com.
- Select DNS validation instead of email. As long as you have the CNAME records in your Google Domain records that will be provided after making this request, you'll never have to worry about updating the certificate again. If you go the email route, you'll have to do a yearly update and I'm not going to worry about that. Select DNS validation, and it'll be good.
- Select make request and go to status page.
Add CNAME Records to Google Domains
- Now on the Certificates page in AWS Certificate Manager it will show that your status is pending.
- Click into the certificate request you just made. You should see a CNAME name and CNAME value for your www.<your website name>.com and your <your website name>.com. If the values are blank, this is a glitch that can happen, just refresh the page until they show up, they should show up right away.
- Copy these CNAME names and CNAME values. You will put these into your Google Domains.
- In Google Domains, go to DNS.
- Create two CNAME records, one for your naked domain, and one for the other. So for www.<your website name>.com host name will be something like:
_123a456789012b3456c7d8ef901a234b.www, Type: CNAME, DATA something like: _fe098765432dc10b987a65f43e21098d.abcdefghij.acm-validations.aws.
- For the other record (naked domain) take the CNAME name and value associated with your name domain and do the same as in the previous record you made. Just to be clear the naked domain should have different CNAME name and value than the www.<your website name>.com.
- Make sure you leave your domain name out since Google Domains automatically attaches this on for you, otherwise your domain name will be in the host name twice such as _123a456789012b3456c7d8ef901a234b.<your website name>.com.<your website name>.com. And this would result in error.
- Select Save and head back over to AWS.
Waiting for Success Status
For me it took 4 minutes after routing things up in Google Domains to get my certificate issued. So sip that coffee and take a breather while you wait! It shouldn't be long.
The certificate status will change to "Issued".
3. CloudFront
Head over to CloudFront in AWS.
- Select Create distribution.
- Origin domain: www.<your website name>.com.s3.amazonaws.com
- Still learning, but For Origin Path, try leaving blank, putting "index.html" or "/index.html" here broke for me. You might run into this error shown in the screenshot below as soon as you block all public access and only allow your OAI (more on the OAI later), just let me know in comments what works, and I can fix this step:
![enter image description here]()
- Viewer protocol policy: Redirect HTTP to HTTPS
Allowed HTTP methods: GET, HEAD, OPTIONS, PUT, POST, PATCH, DELETE
- And towards the bottom, under Settings, select “Add item” for “Alternate domain name”, and put www.<your website name>.com as this should match the bucket that you are pointing to.
- For custom SSL certificate select your new certificate. If you don’t see it, then chances are you didn’t select N. Virginia as the region when making the certificate within certificate manager.
- Keep all else to default and select "Create distribution" to finish.
4. Route 53
Create a hosted zone
- Select Create hosted zone.
- Do the following: Domain name: www.<your website name>.com.
- Leave type to "Public hosted zone"
- Add a description and tag if you want.
- And create.
Add a record to your Route 53 hosted zone for CloudFront
Now go to the hosted zone details if you have not already been taken there. You will now create a record to connect to our CloudFront distribution to add to the list of two records that you should already have there in your hosted zone.
- Select Create Record
- Turn alias on.
- And for “Route traffic to” select “Alias to CloudFront distribution”
- You should see your CloudFront distribution show up, something like: dd56opwkqiwae.coudfront.net. Select this.
- Now finalize by selecting Create Record down at the bottom.
You are now done with the AWS side.
5. Google Domains
You need to create a CNAME record for www.<your website name>.com for connecting to your Cloudfront distribution, and a redirect from <your website name>.com to www.<your website name>.com so that your users can put in your naked domain name and still get to your site. If google domains supported ANAME/ALIAS records, you could do things differently, where you could also create a Cloudfront distribution for your naked domain of <your website name>.com and route <your website name>.com to it's own CloudFront distribution within Google Domains. But since Google doesn’t support ANAME/ALIAS records, you have to redirect your naked domain to your domain, and then your domain to your CloudFront. Also you would have to create an s3 bucket for your naked domain, in which you could point it to the other s3 bucket. But you don’t have to worry about that, since Google Domains doesn’t support ANAME/ALIAS records in the first place. And if it makes you feel any better, amazon.com redirects to www.amazon.com, so having a naked domain redirect to a www url is not only common but used by the big guys.
Now this is fun, the AWS docs at the time of writing this say create a Synthetic Record within Google Domains, but Google Domains recently changed their interface. It no longer calls them "Synthetic records" which was within their "DNS" page, instead you you have to:
- Go to Google Domain's "Website" page and click "Forward Domain"
![enter image description here]()
![enter image description here]()
- In here, forward your naked domain of <your website name>.com to https://www.<your website name>.com.
![enter image description here]()
- Select "Advanced Options" and select "Forward Path" and "SSL On".
![enter image description here]()
- Then go to your DNS page and there make a CNAME record pointing your www.<your website name>.com to your CloudFront distribution.
I blocked out my info, and also put in fake sample data for you to get an idea of what your AWS records are supposed to look like in Google Domains.
![enter image description here]()
Congratulations You Successfully Have an HTTPS Website!
So when someone goes to <your website name>.com, Google Domains redirects it to www.<your website name>.com which then does a CNAME lookup and finds your CloudFront distribution url. From CloudFront which has your SSL certificate, Route 53 sees that the CloudFront distribution was reached and serves your S3 bucket static site.
Extra Steps
Now that you have it so that your users can access the S3 bucket through your domain name using https, you want to turn off the bucket from being accessed directly (which is http and not https among other reasons). So, first go to CloudFront.
1. CloudFront
- In CloudFront, under Security, click Origin Access Identities.
- Select "Create new origin access identity"
- Call it whatever you'd like, but to be constant go ahead and call it <your website name>-OAI.
- Go to CloudFront distributions.
- Click your distribution.
- Select "Origins"
- Select your origin displayed in the list there.
- Select "Edit"
- Under S3 bucket access, select Yes use OAI (bucket can restrict access to only CloudFront)
- From the Origin Access Identity drop down menu that appears, select your new OAI you just made.
- Select "Yes, update the bucket policy". You will still have to go to S3 and delete the previous allow policy that we put in way back in the beginning of this tutorial, which was only optional since it was for testing purposes.
- Select "Save Changes" down in the bottom, and you now have your OAI connected up.
2. S3
- Now head over to S3.
- Select your bucket.
- Only your OAI needs access, so you should block all public access now. So in Permissions, under Block public access (bucket settings), go ahead and block all access now. And under Bucket policy you should have the following:
JSON for OAI, which should have been set if you selected "Yes, update the bucket policy" in the previous step. I added "s3:PutObject" in list of actions as shown below
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "2",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::cloudfront:user/CloudFront Origin Access Identity <your OAI ID>"
},
"Action": [
"s3:GetObject",
"s3:PutObject"
],
"Resource": "[resource_name]"
}
]
}
And now users should only be able to enter your static website via CloudFront and not directly through your S3 bucket.