So you want a techblog, huh?
The blog
I think many fellow infrastructure nerds can relate to this:
You want your own meaningful workload hosted in a cloud environment that use the technologies you are interested in, without incurring too much personal cost.
In my case I want to be as close to a “real production” workflow as possible, utilizing my own underlying Cloud Platform architecture on AWS, supported with identity management from Microsoft Entra ID. This in combination with a wish for a page you can write down some thoughts, be it just for fun or as something to promote as part of “your career brand” makes “the blog” an easy choice for many, me included.
So in order to kick off this blog - Why not describe how I have built my blog? So meta.
Disclaimer: This is not a step-by-step guide for how to set up your own blog, but you can certainly use this as inspiration.
The architecture
Some key principles I wanted to stick to for my blog:
- Use well-known software that is well supported and used by the community.
- Avoid bloat and keep it minimalistic.
- Optimize for cost-efficiency.
- Blog posts should be based on markdown and commited code.
These principles led me to a combination of using Jekyll and Amazon S3 with Static web pages enabled.
Jekyll is a minimalistic, but powerful static site generator based on Ruby. Much of its popularity comes much from the fact that it integrates seamlessly with GitHub Pages, enabling you to host great static pages for free!
Now, I could of course use GitHub Pages for my blog, but that kills some of the purpose with the blog in the first place, which was to host it in my own AWS platform.
Amazon CloudFront with custom-domain and SSL-integration with AWS Certificate Manager (ACM) support only makes sense for this setup. Additional low-hanging fruits can be picked by enabling AWS Web Application Firewall (WAF) as well.
Useful references
- The official Jekyll site
- GitHub Docs - About GitHub Pages and Jekyll
- AWS Docs - Use an Amazon CloudFront distribution to serve a static website
AWS infrastructure
The AWS infrastructure I built my blog on can easily be summarized in a diagram which showcases the components involved.
I will not dive deeper into how the various components are configured for now. This may be the topic of a future blog post! Check out this Knowledge Center post by AWS if you would like to know more about this.
Jekyll
Getting started
Getting started with Jekyll in a static page is quite easy. In just a few steps described in the official quickstart guide, you can have your base page ready.
Note: Some Jekyll themes does not perfectly align with the Quickstart guide in terms of versions and configuration settings. If you already know which Jekyll theme you want to use, I recommend reading through the documentation for set-up for that specific theme as well before you decide how to bootstrap your page.
Note 2: If you are using a Mac, you should follow the Jekyll on macOS documentation in order to avoid problems with the old Ruby versions that comes pre-installed in macOS.
Useful commands
Developing locally with Jekyll is a breeze. Some useful key commands you should know about:
-
jekyll build- Builds/Generates your site to the_sitedirectory -
jekyll serve- Serves your site locally and also continuously builds on source file changes. -
bundle install- Installs any plugin gems defined in your Gemfile
Combining the jekyll commands with bundler command bundle exec ensures that jekyll will only build or serve with the specified gems in your Gemfile.lock file.
bundle exec jekyll serve- launches a HTTP server locally on your machine with default addresshttp://127.0.0.1:4000, using theGemfile.lock-specified gems. Athttp://127.0.0.1:4000you can verify that the site is able to build and that posts looks as they should before you commit your changes to your repository.
GitHub Actions workflow
I use GitHub Actions for my CI/CD flows. Building and deploying your Jekyll site to a Cloudfront-distribution backed by an S3 bucket enabled for static website hosting can be done with the following job stebs.
Note that I reference GitHub Actions variables vars.AWS_S3_BUCKET_NAME and vars.AWS_CLOUDFRONT_DISTRIBUTION_ID. I define the values of these outside of the code for reusability and to support multiple environments.
Installation and configuration of Ruby:
- name: Set up Ruby
uses: ruby/setup-ruby@v1
with:
ruby-version: "3.3.5"
bundler-cache: true
Jekyll site building using the bundle exec jekyll build command:
- name: "Build Site"
run: bundle exec jekyll build
env:
JEKYLL_ENV: production
Sync directory to S3 bucket enabled for static site hosting. The sync command with the --delete flag is useful in order to not end up with old content in the bucket that is no longer present in your project:
- name: "Deploy to AWS S3"
run: aws s3 sync ./_site/ s3://$ --delete --cache-control max-age=604800
Create invalidation of any current cache in CloudFront in order to immediately reflect the updated site:
- name: "Create AWS Cloudfront Invalidation"
run: aws cloudfront create-invalidation --distribution-id $ --paths "/*"
Note! You need to authenticate to AWS with AWS CLI in some way prior to these steps. Methods of doing this may vary.
I currently use a static IAM user access key id and secret retrieved from a 1Password vault, but will in the future use short-lived credentials with OIDC between my AWS environment and GitHub.
How do I get my architecture diagrams into Jekyll?
This was one of my first concerns when thinking about a blog solution. I want to show diagrams for various solutions, but I don’t want to maintain manual screenshots. Thankfully this is also made easy with Jekyll!
I found this gem (pun intended), called jekyll-drawio which quite simply uses the online diagram viewer at https://app.diagrams.net to render your .drawio files.
Since draw.io diagrams are just xml-based files, they make sense to store directly in the project repository and track their changes with git. If you use the local draw.io client, you can save directly to your project and almost instantly see changes in the static site when it is served locally with bundle exec jekyll serve. Neat!
First, add the gem to your Gemfile Jekyll plugins group
group :jekyll_plugins do
gem "jekyll-drawio", "~>1.0.0"
end
Once that is done, you can reference .drawio files in your Markdown files like this:
{% drawio path="<path-to-diagram-file.drawio>" page_number=<number-usually-0> height=<diagram-height-in-pixels> %}
Note! The path to the diagram is relative to the project root (i.e. same place you have your Gemfile), NOT the markdown file! Page number index starts from 0, so that is normally what you will specify.
To summarize
So now I have the blog - And even a first post to go with it! For future posts I might dive a little bit deeper into the Infrastructure as Code managed with Terraform behind it.