I spy a CI
This is my first attempt at a blog where I can write about things that are exciting to me. Of course, I draw a blank when I think of where to start. But why not start with a guide on building this blog itself? After all, automating the deployment is half the fun!
I use Komodo extensively in my homelab. Paired with Forgejo, I can achieve a level of GitOps that makes managing all my containers so much easier. From one-click image updates to automated image builds, my server management is as easy as add, commit, and push.
To automate your own blog, you’ll need the following
- Git on your development machine (usually a PC or laptop)
- Forgejo (or Gitea)
- Komodo
Since publishing my blog publicly, I use Bunny.net for hosting. Komodo was great for the early stages, but I wanted to try something new with a CDN!
Create your blog
I chose Hugo because it provides a quick way to build and deploy static sites with markdown. With so many themes to choose from, I didn’t want to get stuck grooming the aesthetics without having written any actual content. I’ve read a few blogs that use Bear, and I like the simplicity of it. I’ve since switched to Notepadium purely for the aesthetics, but Bear was a great place to start!
Install Hugo
Follow the instructions on how to install Hugo on your OS of choice: https://gohugo.io/installation/
It’s usually as simple as:
choco install hugo-extended # Windows
brew install hugo # macOS
sudo pacman -S hugo # Arch Linux
Initialize the blog
Then, it’s time to create your blog!
hugo new site my-new-site
cd my-new-site
git init
# You can substitute the example below with a theme of your choosing
git submodule add https://github.com/janraasch/hugo-bearblog.git themes/hugo-bearblog
cp themes/hugo-bearblog/exampleSite .
hugo server
At this point, you can navigate to http://localhost:1313 to view your new blog! Familiarize yourself with the content folder which is where you can add or remove posts in the markdown format. There’s also a lot of opportunity for customization in hugo.toml.
Dockerfile & Compose
To run the blog as a Docker container, we require a Dockerfile (instructions on how to build the Docker image) and a Compose file (instructions on how to deploy the Docker image).
Dockerfile
# Source: https://docker.hugomods.com/docs/ci-cd/nginx/
#####################################################################
# Build Stage #
#####################################################################
FROM hugomods/hugo:exts as builder
# Base URL
ARG HUGO_BASEURL=https://blog.domain.tld
# Build site
COPY . /src
# Replace below build command at will.
RUN hugo --minify --enableGitInfo
# Set the fallback 404 page if defaultContentLanguageInSubdir is enabled,
# please replace the `en` with your default language code.
# RUN cp ./public/en/404.html ./public/404.html
#####################################################################
# Final Stage #
#####################################################################
FROM hugomods/hugo:nginx
# Copy the generated files to keep the image as small as possible.
COPY --from=builder /src/public /site
Compose
---
services:
my-blog:
image: git.domain.tld/my-blog/my-blog:latest
container_name: my-blog
Store the code
To save your blog, create a new repository in Forgejo (or wherever you host your repository) and follow the instructions to add the remotes associated with your local repository.
You can either store the code under your user or under an organization. I’ve chosen the latter so the Komodo user can publish the Docker image to the same repository that the code resides.
Make your way to the repository’s Settings > Webhooks. We’ll come back to it in a minute.
Komodo Configuration
Komodo has a whole menagerie of resources that we’ll use to automate blog deployment. First, we’ll create a Repo that points to the remote repository, then we’ll create a Build for building the Docker image. Then, we’ll need a Stack to deploy the Docker image. Finally, we’ll link it all together with a Procedure, which will be activated via Webhook.
Personally, I use a mix of UI and TOML to create the resources I require, but I’ll add both ways as we go along.
Repo
Create a new Repo and name it whatever you like. Select which server it’ll clone on, and which Builder will do the heavy-lifting (Server and Builder are the same in my case). I don’t want this to devolve into a Komodo Setup guide, so I’ll assume you have the other necessary components (Builder, Git Provider, Account). Disable the Webhook, as only the Procedure will handle those.
Replace the repo value with either your-organization/my-blog or your-user/my-blog
main.toml
[[repo]]
name = "my-blog"
[repo.config]
server = "my-server"
builder = "my-server"
git_provider = "git.domain.tld"
git_account = "komodo"
repo = "my-blog/my-blog"
webhook_enabled = false
Build
Create a new Build, and attach the Repo we just made. Configure your Image Registry and add a quick link to the repository if you desire. By default, Komodo will push the image to match the resource name. This can be changed in the Tagging section.
In the Pre Build section, you must add the following commands to enable the Hugo theme you’re using. Otherwise, your site will not load.
git submodule init
git submodule update
main.toml
[[build]]
name = "build-my-blog"
[build.config]
builder = "my-server"
image_name = "my-blog"
links = ["https://git.domain.tld/my-blog/my-blog"]
linked_repo = "my-blog"
webhook_enabled = false
image_registry = [{ domain = "git.domain.tld", account = "komodo", organization = "my-blog" }]
pre_build.command = """
git submodule init
git submodule update
"""
Stack
I build my stacks straight from TOML, as it’s usually a copy-paste from my fifty other stacks. If you want to create it in the UI, it’s very straightforward.
[[stack]]
name = "my-blog"
description = "My personal blog"
tags = ["blog"]
[stack.config]
server = "my-server"
links = ["https://blog.domain.tld"]
linked_repo = "my-blog"
Procedure
Lastly, we’ll create a procedure so that our previously created resources can be activated in-order. Create a new procedure, and add two Stages:
- Run Build: build-blog
- Deploy Stack: my-blog
Make sure Webhook is enabled, and copy the Webhook URL. In Forgejo, add a new ‘Forgejo’ webhook and paste the URL in ‘Target URL’. If you have a Webhook secret (configured in Komodo Core), paste it there as well. Leave everything else as-is.
[[procedure]]
name = "deploy-my-blog"
[[procedure.config.stage]]
name = "Build image"
enabled = true
executions = [{ execution.type = "RunBuild", execution.params.build = "build-my-blog", enabled = true }]
[[procedure.config.stage]]
name = "Deploy stack"
enabled = true
executions = [{ execution.type = "DeployStack", execution.params.stack = "my-blog", execution.params.services = [], enabled = true }]
Afterword
Now that we’ve created all the necessary resources and we’ve linked them together to run upon pushing code to the repository, it’s time to deploy! Write up a new post in your blog, and push to the repository to see the magic happen.
