Building my blog

Posted by Tom on March 18, 2023 · 21 mins read
#programming #aws #jekyll #git #github

Building this blog was fun, but it was hard work. Part of the difficulty was because I build it from the ground up, from the code to the server. To avoid this manual work, I could have used a blog building service like Wordpress, but that would have robbed me of the opporunity to learn how the underlying technology works. It probably would have cost me more too, though it would have been faster.

This project was difficult and fun precisely because I made it myself. Despite my inexperience, I enjoyed learning how each component worked and fit together. The end product is something I’m proud of and is useful to me. Now, I’d like to share the process and what I’ve learned.

Though this walkthrough assumes familiarity with terms such as server and network, I’ve tried to make it friendly to less-technical people by explaining the technology in simple terms. First, I’ll explain my motivations for the project and the requirements I had for the implementation. Second, cover the design and the tools I used to build it. Third, I’ll break down the costs, and fourth, I’ll explain what it’s like to use the blog. Last, I’ll go over changes and improvements I’d like to make.

Motivations and Requirements

First, when starting any project it’s a good to seriously consider your motivations for doing so. All too often I’ve found myself stuck halfway through a project wondering why I bothered. I then see my reasons were vague or have passed, thus causing me to either drop or change the direction of the project entirely. I’ve found this to be a sad and inefficient way to work that quickly leads to burnout. For those reasons, I think it’s best to thoroughly examine your motivations before you start.

For this project, my motivations were as follows: 1) to understand website technology, 2) to have a space to share my interests, and 3) to practice writing and develop my thinking.

  1. Having just completed my Bachelor of Cybersecurity, I wanted a project to put my IT skills into practice. While I had built a website before, I had used Wordpress so learnt little about the underlying technology. What I wanted now was to understand how each component worked and how they could be used to form a website.
  2. I love talking about things I’m passionate about, but not everyone shares the same enthusiasm for my topics of interest. Unsurprisingly, this was especially true while I studied Freud in a philosophy class. Nobody wanted to hear how symbolic identification resolves the Oedipus complex, much to my disappointment. To avoid boring people to death, I needed someplace to ramble where readers could retreat at the first bout of boredom.
  3. I find writing beneficial because it helps me develop and organise my thoughts. As a student of philosphy, this makes writing invaluable. While writing on its own is beneficial, having an audience encourages me to think deeper and express my ideas more clearly. Moreover, writing with specific people in mind gives me more motivation to write, thus stimulating me to develop my thoughts further. My hope was that having a blog would encourage me to write more frequently, thus increasing those benefits.

After my motivations were clear, I thought about the requirements I had for the end product. These were as follows:

  1. Simple to use. I didn’t want posting to involve any coding.
  2. Portable. I wanted the ability to publish posts and make code changes on most computers. Bonus if I could publish posts from my phone.
  3. Version controlled. If I made a change that broke my site, I needed something to revert the changes. Ideally, I’d be able to restore my blog to any point in its history.
  4. Cheap as chips. Websites are hosted on servers and servers cost money to use. I had no intention to monetise my blog, so I wanted to spend as little as possible.

Implementation

With these requirements in mind, I did some research and settled on a design that fit the bill. To provide the code for the website, I used a tool called Jekyll. For keeping a history of code changes I used Git, and to make the code portable I used Github. I also used Github to deploy website updates to my host server. Finally, I used Amazon Web Services for cheap website hosting.

Jekyll

To get any website running, you need code. While I enjoy coding, I didn’t want to do much for this project. All I wanted was some basic code for a website that I could edit later. That’s why I used Jekyll, it generates website code for you. While it did require me to use the command line (the text interface for your computer) I found it very easy to use. All I needed to do was type jekyll new blog into the command line and Jekyll generated the code in a flash. From there, I added content to the Home and About pages Jekyll had also generated. To add blog posts to website, I needed to create new pages manually. These pages needed to follow a format called Markdown so that Jekyll would know how to render the text.

To determine the form and function of pages on the site, Jekyll uses a templating scheme it calls themes. These themes can be free or paid for and are easy to edit if you’re savvy with HTML and CSS. For my own site, I chose the Clean Blog theme from Start Bootstrap. I’ve slightly modified it since, but this wasn’t necessary to get the blog running.

The websites Jekyll generates have additional benefits, but first I’ll need to explain the difference between dynamic and static websites. A dynamic website is one that runs code on the server to provide functionality. An example would be Facebook, which has code running on servers to provide you with personalised content. By contrast, a static site has no code running on a server. An example would be this blog, where the content stays the same for every user.

As running code on servers costs money, having a static site keeps operational costs low as no code is run. It also means pages render quickly and keeps loading times constant, even with high traffic. Another advantage is that security concerns are basically non-existen as there’s no code for hackers to exploit. As you may have inferred, Jekyll generates static sites, so I’m able to enjoy these benefits for my blog.

Git and Github

To keep track of changes made to my website, I used a version control tool called Git. Yes, it has a funny name - the reasons its creator gave it that name are funny too. Git has been around since 2005 and was originally developed by the guy who created the Linux operating system: Linus Torvalds. Since then, it’s become a standard tool in the software industry. It’s probably one of my favourite tools and I use it every day as a software developer.

Once set up, Git will keep a history of file changes within a folder. These changes may then be saved as revisions which can be restored or compared against other revisions. After generating my website with Jekyll, I used Git to maintain the history of the project.

Another feature of Git is that you can upload a copy of your project and its history to an online repository such as Github. From there, you can import the project onto other machines and continue editing where you left off. You can even edit your project online using Github’s browser based editor. To make my project portable, I uploaded it to Github using Git.

Amazon Web Services

To get my blog online, I used several web services provided by Amazon, namely S3, Route 53, Certificate Manager and Cloudfront. Each of these services are priced using Amazon’s pay-as-you-go model and end up costing me about $1.23 USD each month on average. That’s actually cheaper than chips. Thankfully, Amazon provides documentation to set up websites like mine, so the process was mostly straightforward. Unfortunately, there were a few steps where I got stuck, so I recommend following this guide instead which covers the issues I encountered.

As for the services themselves, here’s a brief rundown on what each of them do and what I used them for.

S3

Amazon’s Simple Storage Service (S3 for short) is essentially a folder you can access on the Internet with a URL. These folders, or “buckets”, as Amazon calls them, are always online and can be integrated with a wide variety of services. In my case, I set up an S3 bucket as the host server for my website and integrated it with Github. This integration lets Github upload the website every time I save a new revision to the repository. This ensures the site hosted by S3 is always up to date. For more on how this works, please see this guide.

It’s worth noting here that I could only use S3 as my server because my website is static. To quickly recap, a static site runs no code on the server, while a dynamic site does. As S3 buckets are designed for storage, they can’t run any code for you. Therefore, you can only use them as a server if your site is static.

Once uploaded to S3, my website becomes accessible on the web via this URL: http://discursiveloop.com.s3-website-ap-southeast-2.amazonaws.com. But that’s not the URL you’re seeing in the address bar. To set that up, I had to use Amazon’s DNS service: Route 53.

Route 53

Of all the things I did to set up this blog, getting the custom URL working was the most confusing part. To give a simplified explanation, I had to buy a domain name (like discursiveloop.com) and then tell Amazon to use it as an alias for my S3 bucket. In reality, it was much more complicated, but explaining how it works is beyond the scope of this post. For those interested in the details, please see the documentation provided here by Amazon.

Beyond being confused, another frustration was purchasing this particular domain. While there are thousands of domains listed on Route 53, discursiveloop.com was not. l eventually bought it on GoDaddy and this cost roughly $25. This was frustrating because Amazon offered $12 for most .com listings at the time, so it would have been cheaper if it was listed there. To make matters worse, GoDaddy’s yearly fees for re-registering domains seemed to be variable and more expensive than Amazon’s. To avoid having to pay the more expensive renewal fee, I followed this guide to transfer the domain to Route 53. This cost me another $12.

Cloudfront & Certificate Manager

Finally, I wanted people to have a secure connection while visiting my site. To do that, I needed to enforce HTTPS over HTTP. This has the effect of encrypting data as its transferred between visitors and the server, thus making the data unreadable if intercepted. This also means your browser won’t warn you that your my site might be dodgy. Unfortunately, S3 does not support HTTPS so I needed to use two more services from Amazon to set this up: Cloudfront and Certificate Manager.

In a nutshell, Cloudfront gives you access to a bunch of servers distributed around the globe, something called a content delivery network. These servers can be set up to forward, cache and serve content like the pages on my website. The closer you live to one of these servers, the quicker the content will load as there is less distance for the data to travel. Since Amazon has these servers all over the world, you can pick the regions where your content to load quickest. Incidentally, Cloudfront servers can deliver your content using HTTPS, but only if you supply them with something called an SSL certificate.

An SSL certificate is something a server can present to browsers to certify its trustworthiness. A browser will look at the certificate and will ask the certificate issuer (called a certificate authority) whether they trust that server. If they do, you can begin communicating via HTTPS. As you might have guessed, Amazon can issue these certificates via their Certificate Manager service so I requested one for my site.

Putting this into practice, I set up a Cloudfront network to serve the contents of my S3 bucket, i.e. my website. Then I configured these servers to present my SSL certificate to get HTTPS working. Now when someone visits my site, their browser will receive the certificate and will ask Amazon if the site is trustworthy. Amazon should say yes (unless the certificate has expired) so the visitor will be able to communicate securely with the server using HTTPS.

Since Cloudfront was now serving the content from my S3 bucket, I needed to reconfigure my custom domain so that it was an alias for Cloudfront instead of the bucket. Now, when people visit https://discursiveloop.com, they see content served to them by the Cloudfront servers, which in turn comes from my S3 bucket. While you can still access the content from S3, it will be with HTTP.

Recap

That’s a lot to remember, so here’s a quick summary of the set up:

  1. Jekyll generates the code for my website and can be used to generate pages for posts I write.
  2. Git tracks the revisions I make to the website and can be used to revert to previous revisions.
  3. Github stores the website code and its history in an online repository. This makes the blog portable to other devices.
  4. Github also uploads the website to an S3 bucket on Amazon any time I save a new revision to the respository.
  5. S3 serves the pages of my site which can be accessed by a URL it provides.
  6. The contents of the bucket are forwarded to a Cloudfront delivery network which uses an SSL certificate to enable HTTPS.
  7. Content is now being served from Cloudfront, which is retrieved from S3.
  8. I set up a custom domain as an alias for the Cloudfront servers using Route 53. This lets people visit the site by going to https://discursiveloop.com.

Costs

Honestly, I’m shocked by how little I paid. Here’s a quick breakdown of the costs (prices are in USD):

  1. $25 for discursiveloop.com from GoDaddy (would have been $12 if it was listed on Amazon).
  2. $12 to transfer the domain to Amazon from GoDaddy.
  3. $12 yearly renewal fee for the domain (this has since changed to $13).
  4. $0.01 per month for S3 storage.
  5. $0.50 per month for a hosted zone in Route 53 (I didn’t cover this above but it had to do with setting up the domain).
  6. An additional 10% of the total in tax due to living in Australia.

In total, the first year of running the blog amounted to $41.26. For the following year, it cost $14.86. As more people visit my blog, I will incur more fees from Cloudfront as it bills per HTTPS request. That being said, you get 10,000,000 free requests per month and beyond that it’s $0.0125 for every 10,000 requests. I doubt this number will increase due to an increase in visitors though. This is a blog after all.

User Experience

So, what’s it like actually using the blog? The process is pretty straightforward, but it’s still a bit more manual than I’d like. Currently, the steps for posting look like this:

  1. Write my post in a Markdown text editor like Obsidian.
  2. Copy the post onto a device that has Git and Jekyll installed.
  3. Add links for images, including content tags and the date of the post.
  4. Tell Jekyll to regenerate my website, now with the new post.
  5. Save the changes with Git and upload them to Github, this kicking off a new deployment to S3.

Ideally, I’d like to write my posts and have steps 2 through 5 happen automatically. This is definitely achievable, but for now the manual steps will have to do.

Changes and Improvements

The blog is now functional, but it’s missing some features I’d like to add:

  1. Email subscriptions for content updates.
  2. A navbar to allow readers to jump to sections in my posts.
  3. Dark mode for easier reading.

Something I don’t want to add is a comments section. I don’t want to moderate comments or pay for a service to store and load them. If you’ve got something to say, I’d love to hear it via email or in person, but no comments for now.

As for changes, I’d like to experiment with the React Javascript library for a more hands on alternative to Jekyll. Thanfully, this wouldn’t require changes to the rest of the design as you can build static sites with React too.

Final Thoughts

As you can see, this project took a lot of work. It required me to learn a wide variety of tools and services, many of which I had never used before. Nevertheless, I had a lot of fun doing it and learnt a lot in the process. I’m still surprised by how little it costs to run, though any cost savings are certainly offset by the amount of time I spent on the project. If you’re interested in learning more about the technology I mentioned in this post, I highly recommend building a blog of your own.