Porting a Static Website From GoDaddy to AWS
This is my new blog! Welcome! I hope to post things here from time to time that will be helpful to others.
I had an old blog, it was www.tpedron.com/blog, a hosted WordPress app I had running on GoDaddy as part of my Basic Linux hosting package with the rest of my website. I had been paying approximately $150 CAD a year to GoDaddy (and had been since around 2015) to host a very simple static personal website (just HTML, CSS, JS + some file hosting), and this WordPress blog. I basically never used the blog and overall I had been paying for a lot more managed services and support from GoDaddy than I needed. I recently completed my AWS Solutions Architect Certification and didn’t really require GoDaddy to hold my hand anymore. I knew I could do this myself on AWS for far less (might cost me upwards of $25 CAD a year). So I did!
Below are the steps.
1. Initiate Domain Transfer on GoDaddy
On GoDaddy, I logged in and went to the products page. I first turned off the auto-renewal of my hosting package (this was approx. 30 days in advance). At this point, I committed to going through with this process.
Next, I turned off the domain lock setting and domain privacy protection settings (considered a downgrade on my plan) so I could begin the tpedron.com domain transfer process. I had to do this to enable retrieving the authorization code which was disabled.
Now that the “Get transfer authorization code” button enabled, I followed the steps to retrieve the code and saved it to a text file.
2. Accept Transfer on AWS Route53
Next, I logged into the AWS Route53 service console > Registered Domains and clicked on the “Transfer Domain” button. I went through the steps to select the domain name I wanted to transfer (which was tpedron.com of course), provided the transfer code, and selected the option to copy DNS settings from my existing DNS provider (also GoDaddy). This ensured that while the domain was being configured and in flux that the domain would still temporarily point to the old deployment of my website on GoDaddy.
Once this step was complete, the domain transfer was pending approval by GoDaddy and listed under the Domains > Pending Requests section.
This domain transfer process cost me~$12 USD/$18 CAD.
3. Complete Transfer on GoDaddy
I went back to GoDaddy and refreshed the products page a few times (it took some time for the website to reflect the state of the domain transfer). Eventually, the domain was shown in a transfer pending state with an Approve button which I clicked. The domain disappeared from the page and only my soon-to-be expired hosting package remained.
4. AWS Receives Confirmation
After a few minutes, AWS received approval confirmation from GoDaddy and the transfer was completed. I received a confirmation email as well. It said this process could take some time but for me, it was pretty instantaneous. I navigated to Domains > Registered Domains to find my domain name listed there.
Before continuing configuring Route53, I needed to port the actual website(HTML, CSS, JS, and other files like PDFs, images) over. Once completed, I could then return and point the domain name at the new website deployment by configuring the DNS records.
5. Create an AWS S3 Website
No need for me to reinvent the wheel on this, just follow the steps listed here to deploy a static website to S3. https://docs.aws.amazon.com/AmazonS3/latest/dev/WebsiteHosting.html
Once complete, I had a non-secure hosting of my website with a URL that looked like: http://<bucket name>.s3-website.<region>.amazonaws.com/
After following these steps and while still in the S3 console, I created 1 more private bucket to hold logs from Cloudfront (optional).
6. Create a CloudFront Distribution
In the AWS console, I then navigated to the CloudFront service. I created a new Web distribution (deployed it to all edge locations for performance reasons) with the origin domain name being the s3 bucket containing my website. I skipped the steps related to SSL certs/ alternate domains but would return later on to take care of that. I also set up default logging to the logs bucket I mentioned in step 5 (optional).
After the distribution was created, I was able to access a CloudFront distributed version of my website over HTTPS and HTTP with a URL that looked like https://<cloudfront id>.cloudfront.net.
I then navigated to the Behaviors configuration of the Distribution and updated it so that it redirects HTTP to HTTPS and allows GET, HEAD, and OPTIONS methods.
7. AWS Hosted Zone
With the newly created (and incomplete) CloudFront distribution information, I went back to Route53 to create a Hosted Zone to define the DNS records for the website and the domain. Creating a Hosted Zone provided me with the NS (Name Servers) and SOA (Start of Authority record) that were fine as they were.
I then created the following additional records:
- An A (IPV4) record with an empty name (so it's just tpedron.com) that aliases to the Cloudfront distribution (<cloudfront id>.cloudfront.net).
- An A (IPV4) record with name www that also aliases to the CloudFront distribution (<cloudfront id>.cloudfront.net). This allows tpedron.com and www.tpedron.com to go to the same target.
In the next step, a process kicks off that will introduce a CNAME record to this Hosted Zone that references an SSL certificate.
8. Request certificate in ACM
I navigated to the AWS Certificate Manager (ACM) service and requested a new DNS validation certificate with the following domains:
That request went into a pending validation status. Expanding the record in the table revealed a button “Create Record in Route53”. I clicked it and it created the CNAME DNS record on the hosted zone I created in Route53 previously.
This process was fairly quick and within a couple of minutes the certificate request went into an Issued state.
9. Update CloudFront Distribution With Certificate
I went back to the Cloudfront Distribution, clicked edit, and set my Alternate Domain names to be the same values I set on my certificate request:
I also set my SSL certificate to be a custom certificate and selected the one I had just been issued. Then I saved.
10. Update Registered Domain NS to match hosted zone
When I transferred my domain I selected the option to pull in the Name Servers from my previous DNS provider. Since I am hosting the website elsewhere and that deployment is ready in CloudFront, I needed to update the Name Servers on the Registered Domain to map to my Hosted Zone (setting this was in a different spot in the AWS console than the Hosted Zone DNS NS record). There was probably a way to set the NS values as part of the domain transfer process but I did not do that.
First, I copied all 4 NS values I had in my record to a text file, then navigated to Registered Domains > tpedron.com > Name Servers > Add or edit name servers. This opened a window where I could paste the 4 new NS values I had and remove the old ones that came with my domain transfer. Saving this kicks off a process on Route53 to finalize the changes and emails you when complete.
11. Wait for DNS changes to Propagate
DNS changes do not immediately propagate to the rest of the internet. It's a process that involves other systems refreshing their caches and can take up to 48 hours.
You can check using a tool like http://dns.squish.net/ to see what NS records are registered with your domain.
At this point, porting tpedron.com to AWS was complete. Look at that lock icon, it's beautiful!
12. Change Deployment Script
While my website is easy to maintain and the configurations are pretty much set in stone at this point, I still didn’t want to have to open up the AWS S3 console and drag my changed files in every time I made a change to my website (which is really just updating my index.html file 95% of the time). With my AWS credentials set as ENV vars, I wrote a simple shell script that will copy the latest version of my index.html file to the s3 bucket that hosts my website and then initiates a manual cache invalidation of the CloudFront Distribution to ensure the latest changes to my files are distributed online:
#!/bin/bashaws s3 cp index.html s3://<website bucket name>/index.htmlaws cloudfront create-invalidation \ --distribution-id <cloudfront distribution id> \ --paths "/*"
This process takes a minute or so to complete.
Hope that helps anyone!