New Digs
Welcome to the new and improved Matt5lot10.com! After a good 12 year run using good ol LAMP stack, it was high time to make a change for Matt5lot10.com. While PHP, MariaDB, and Nginx have been trustworthy and faithful friends of mine, it was high time I embraced a new look, simplified architecture, and improved security posture. With recent projects at Nutanix, Checkmarx, and now Kasten, I’ve embraced the simplicity and elegance of markdown and Jekyll hosted on GitHub pages.
Some good examples of sites I’ve created are:
It’s quick, easy, elegant, and just works. I figured I’d take the opportunity to embrace it for my personal site as well, although I didn’t want to be limited by GitHub’s storage limit for GitHub pages. I already have my containerized (docker-compose) set up with Swag, so it was a relatively light lift to switch over. Once I found the right Jekyll theme for a reasonable fee, Aditu, I was off to the races. A few core concepts I had to learn though, as implementing a Jekyll site locall required I actually see under the covers a bit, as GitHub pages handles the dirty work for you:
-
Ruby can be… frustrating - It’s the same old issue with any new dev project with dependencies and libraries, getting the environment setup. rbenv is a friend here for sure, but the mistake I made was I stumbled upon it too late… so I had a wonky setup for a minute on my server where I had both a local install and an rbenv install and it took me some cycles to untangle binaries and install locations. Long story short, don’t do what I did and install bundle, bundler, and ruby manually, just leave that all to rbenv. The nice thing is once you get bundle installed correctly, you don’t need to know any Ruby after the fact to build the site, just markdown.
-
ruby is only needed for build - I knew this already but in my excitement to get up and running, I didn’t stop to actually think through how Jekyll pages are built. Essentially jekyll is only used during the site build process, so you create the content you want in the predefined directory structure, run
bundle exec jekyll build
against the files, and out spits a fancy templatized site in the_site
directory. Simply pointing nginx, apache, or lighttpd at the_site
directory will serve up the site. There’s no web application server middleware you have to run, or docker container running jekyll serve continuously. But I forgot this and went down a rabbit hole of setting up a docker container for Jekyll to run constantly and monitor the directory, then port forward from 80 to the jekyll default of 4000. It was completely unnecessary. Instead once I took a step back, I realized my foolishness and nuked that portion of my docker-compose file and just ranbundle exec jekyll build
when I was ready to publish the site. -
GitHub and CI/CD Are Phun - Part of my decision to depart from my old LAMP stack architecture was so I could better embrace Source Control Management (SCM), in this case GitHub. Sure, before I’d dump my source code and SQL dumps up to GitHub for the old Matt5lot10.com, but I wasn’t really embracing GitHub as part of my authoring of the site. So often times I’d just make posts and pages directly on the web server and forget to check them in, so Production was always ahead of the source code repository, which as anyone who has worked on a coding or dev project knows, is no bueno. Instead, I wanted to promote GitHub as the source of truth for my site, where production would be downstream from the repository rather than the inverse. And while GitHub is SUPER useful for version tracking, traceability, and collaboration, it’s also GREAT for automation. Using a simple GitHub action with SSH remote commands, I could trigger the
git pull
andbundle exec jekyll build
commands on the web server automatically upon every push into the repository. GitHub Pages does this for you automatically using their own dockerized version, but it was a simple uplift to implement manually so GitHub could run actions on my web servers -
ETL is pretty simple with SQL and markdown - I needed a way to convert my blog posts, previously stored in a containerized MariaDB database, into individual markdown files for the new architecture. With a bit of SQL and bash, this was accomplished relatively easily:
#!/bin/bash
# MySQL database credentials
MYSQL_USER="<supersecretuser>"
MYSQL_PASSWORD="<supersecretpassword>"
MYSQL_DATABASE="<supersecretdb>"
# MySQL query to execute
MYSQL_QUERY="SELECT DATE_FORMAT(published, '%Y-%m-%d') AS formatdate, title, body, published FROM articles;"
# Directory to store output files
OUTPUT_DIR="/var/www/matt5lot10.com/_posts"
# MySQL command to execute the query
mysql -h localhost --port 3306 --protocol tcp -u"$MYSQL_USER" -p"$MYSQL_PASSWORD" -D"$MYSQL_DATABASE" -e "$MYSQL_QUERY" | awk 'NR>1' | while IFS=$'\t' read -r -a row; do
date="${row[0]}"
title="${row[1]}"
body="${row[2]}"
published="${row[3]}"
format_title=${title// /-}
format_title=${format_title//\,/}
filename="$date-$format_title"
output_file="$OUTPUT_DIR/$filename.markdown"
echo "---
layout: post
title: $title
date: $published -0500
image: '/images/12.jpg'
tags: Lifestyle
---
$body
" > $output_file
done
I did have to temporarily pull the mariaDB container off the defined network within the docker-compose file so that I could connect from the physical host to the container using the mysql-client to perform the ETL, but that only resulted in a few minutes of downtime for the site and if it was anything that couldn’t tolerate downtime (e.g. a business), I could have just done a mariadb_dump, spun up a separate container connected to the host’s network, and performed my ETL against it rather than the production database. But fortunatley I don’t think my loyal readers were much bothered by the downtime.
So yeah, we’re off to the races with the new site. Next on the chopping block are some legacy wordpress sites I also host. The goal here is to essentially eschew SQL databases and go all flat file, as relational databases are really overkill for a simple blog site. Stay tuned for updates to trains.matt5lot10.com and eastlandheights.org.