Creating a Secure Portfolio Site
Tags: beginners, aws
Published: 2020-04-26 21:35:15

I just deployed my portfolio site, [maxz.dev](maxz.dev), and wanted to share my experience getting it up and running. I've broken down the process into nine steps below!

[1. Code your site from scratch, or find a template that showcases your skills and personality.](#step1)
[2. Purchase a domain name.](#step2)
[3. Create an AWS account for hosting.](#step3)
[4. Create and modify your S3 bucket, and then upload your files.](#step4)
[5. Obtain a TLS certificate from AWS Certificate Manager.](#step5)
[6. Use AWS Cloudfront to deliver your website.](#step6)
[7. Configure DNS settings to point to your AWS Cloudfront url.](#step7)
[8. Readjust privacy settings for your AWS S3 bucket.](#step8)
[9. Share your new portfolio site!](#step9)
<a name="step1"></a>
<br>
**1. Code your site from scratch, or find a template that showcases your skills and personality.**

I struggled with the decision to create my site from scratch or utilize a template. Initially, I felt that it was 'cheating' to use a template and that potential employers would be disappointed if I did not build the site from the ground up. But ultimately I decided that a visually pleasing and user-friendly site is most important. If you're willing to take the time to make your site responsive, mobile friendly and you're confident in your ability to style the site in an impressive manner, no harm in trying to build it from scratch. But I decided that a template was best for me and am very happy with the decision. One important consideration is that a technical recruiter will likely be the first person to see your site for a potential employer. Their frame of reference is different than that of an engineer, and a less modern site may be concerning from their perspective. I utilized [Start Bootstrap](https://startbootstrap.com/) and had a very easy time selecting one of their free templates and modifying it to fit my needs.
<a name="step2"></a>
<br>
**2. Purchase a domain name.**

This step is fairly straight forward. There are many different options here. Google Domains, GoDaddy & Domain.com stand out as major players but feel free to shop around for pricing, and if you have any specific needs (such as email) make sure to consider those too. I went with Google Domains because of their integration with my existing email account. I also chose a '.dev' TLD (top level domain) which was cheaper with Google than it was with GoDaddy. If you want your typed domain name to automatically become a hyperlink in documents and elsewhere, confirm your chosen domain name meets those needs (a '.dev' name does not automatically become a link). Some steps in this walk-though are specific to Google Domains.
<a name="step3"></a>
<br>
**3. Create an AWS account for hosting.**

If you've used AWS for any purpose in the past, feel free to use the same account. If it's your first time with AWS make sure to treat this account with care. You will need to save payment information for your monthly costs and should be cognizant that privacy settings and account settings could be exploited for malicious use. So use a strong password and refer to the help articles I post below for further questions. AWS support is also happy to help with your questions and concerns. 
<a name="step4"></a>
<br>
**4. Create and modify your S3 bucket, and then upload your files.**

After creating your AWS account you will want to navigate to S3 in their 'Services' menu. Next, you will create a bucket with the same name as your domain. For example, my domain is 'maxz.dev' so I named the bucket the same, 'maxz.dev'. Next, you will want to modify your Bucket permissions. Initially your bucket should be set to block all public access. Turn this OFF for now (we will come back to restrict public access at the end). Next, select 'Bucket Policy' and paste the following (replacing 'example.com' with your domain name):

```
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "PublicReadGetObject",
            "Effect": "Allow",
            "Principal": "*",
            "Action": [
                "s3:GetObject"
            ],
            "Resource": [
                "arn:aws:s3:::example.com/*"
            ]
        }
    ]
}
```

After you have modified your bucket settings you will want to upload all of your files & directories to the root directory of the bucket. DO NOT upload a directory containing all of your files to the bucket; upload the contents of your project directory. You must have an index document in the root directory of the bucket. Once your upload has completed, navigate to your bucket 'Properties'. You should see a card named 'Static Website Hosting'. Select this card and select 'Use this bucket to host a website'. Then enter the name of your index document (most likely 'index.html') and, optionally, enter the name of your error document (I did not upload an error document). Save these settings - you should then see a link at the top of this card and clicking it should open your web site. That means you're on the right track.
<a name="step5"></a>
<br>
**5. Obtain a TLS certificate from AWS Certificate Manager.**

Navigate to Certificate Manager under the 'Services' menu in AWS. Then 'Get Started' with a Provision Certificate and select 'Request a public certificate'. Make sure 'us-east-1' is selected as your region for this step; failure to do so may prevent your certificate from showing up in the next step. On the next screen enter your domain name (for example 'maxz.dev' for me) and, separated by a comma, enter your domain name with an '\*' before it to capture any prefix. Click 'Next' to validate your ownership of the provided domain name. I chose to validate using my DNS settings. If DNS validation is selected, AWS will provide a name and value that need to be entered to your Domain Registrar's settings as a CNAME record. For Google Domains, I simply navigated to DNS settings and scrolled to 'Custom resource records'. I then entered the name AWS provided into the 'Name' field, selected 'CNAME' for type, left TTL set to '1H', and entered the value AWS provided into the 'Data' field. Within minutes AWS showed that my certificate request was successful. 
<a name="step6"></a>
<br>
**6. Use AWS Cloudfront to deliver your website.**

Now you should have all of your code saved to S3, and a certificate issued by Certificate Manager. Next you will navigate to 'Cloudfront' in the 'Services' menu. Select 'Create Distribution' then select your bucket name for the 'Origin Domain Name' field. Next, select 'Redirect HTTP to HTTPS'. For the 'Alternate Domain Names', enter your domain name and, separated by a comma, your domain name prepended with an '\*'. Select 'Custom SSL Certificate' for 'SSL Certificate' and choose the certificate that was created in our last step. Next, enter the name of your index document for 'Default Root Object' (most likely 'index.html'). Lastly, name your portfolio site in the 'Comments' field (this will help you down the line when you have other Cloudfront distributions). Cloudfront will take a few minutes to complete its processes. Once it has finished copy the url under the 'Domain Name' column. 
<a name="step7"></a>
<br>
**7. Configure DNS settings to point to your AWS Cloudfront url.**

Using the url that was copied in our last step, return to your domain registrar's settings and create a new CNAME record with the name '\*' and, for Google, the data value of the url that was copied. This points all versions of your domain name with prefixes to the Cloudfront distribution that was created. You cannot use a CNAME to point to the root of your domain; instead, for Google, scroll up to 'Synthetic Records' and enter '@' for the subdomain and 'https://www.example.com' for the value (replacing 'example.com' with your domain name). 
<a name="step8"></a>
<br>
**8. Readjust privacy settings for your AWS S3 bucket.**

We are now going to restrict public access to our bucket and create a new Bucket policy. Return to your Cloudfront distribution and open it to edit settings. Select 'Origins and Origin Groups' then check the row that displays and click 'Edit'. Select 'Yes' for 'Restrict Bucket Access' and either create an identity or use an existing option. Select 'Yes' for 'Grant Read Permissions on Bucket'. Click 'Save' and wait for it to complete. Then navigate to your S3 Bucket. Modify 'Block Public Access' to reflect that public access has been blocked. Then edit the Bucket policy. Remove the first element (an array) from the 'Statement' array so that the policy that was automatically added by Cloudfront remains. The result should look something like this:

```
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "2",
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:iam::cloudfront:user/CloudFront Origin Access Identity xxxxxxxxxxx"
            },
            "Action": "s3:GetObject",
            "Resource": "arn:aws:s3:::example.com/*"
        }
    ]
}
```
<a name="step9"></a>
<br>
**9. Share your new portfolio site!**

Your site should be up and running so feel free to share with the world.






Sources:
[How to host a static website with https using amazon s3, by Ly Channa](https://medium.com/@channaly/how-to-host-static-website-with-https-using-amazon-s3-251434490c59)
[AWS Support - Bucket Permissions](https://docs.aws.amazon.com/AmazonS3/latest/dev/WebsiteAccessPermissionsReqd.html)
[AWS Support - Configuring 3rd Party Domains](https://docs.aws.amazon.com/amplify/latest/userguide/howto-third-party-domains.html)
[Start Bootstrap](https://startbootstrap.com/)
[AWS Console](https://aws.amazon.com/)
[Google Domains](https://domains.google/)