blog/content/post/0001-hello-friend/index.md
Radu C. Martin 5cb1e60fc3
All checks were successful
Build and deploy website / Build and Push Hugo Site (push) Successful in 47s
post: 0001-hello-friend
2025-04-20 22:44:09 +02:00

9.3 KiB
Raw Blame History

title description slug date categories tags
Hello, Friend So I've decided to have a blog hello-friend 2025-04-20 22:28:00+0200
Technology
Projects
homelab
self-hosting
docker-compose
Hugo

Introduction

This is -- technically -- not my first time hosting a blog, but it is the first time this decade.

The first time I tried hosting a blog was in 2009, the year I got my domain. The domain came with an introductory offer of free web hosting for a year. So I figured out just enough MySQL and FTP to yeet a WordPress installation on there and make it run. As I remember it, I got as far as installing a custom theme I really liked and writing maybe three posts, all within the first month. Then the blog just sat there until the hosting expired, untouched.

The second time was a bit later, after I got into self-hosting. The Internet Archive says it was 2018 [1], so it must be true. That time, I never actually posted anything—I was mainly just interested in deploying the site.

Which brings us to now: the third attempt. This time, the marginal cost of setting up a blog is negligible since Im already self-hosting plenty of services for personal use. That doesnt mean Ill be more active than before, but the blog will probably stay up longer than a few months.

Why a blog?

What reasons do I have for keeping a blog, aside from the challenge of setting up the infrastructure and implementation?

I guess I have a confession to make. Though maybe its not really a confession—because I think its true for pretty much every technically inclined person in a technical field for the love of it: I have way too many personal projects. Some of them I finish, but most never get touched.

I see the blog as a way of keeping myself accountable: keep projects small enough to fit in a blog post (or make them blog-post-divisible), and prioritize the ones that are interesting enough to write about.

Also, finishing a personal project with a blog post gives it a sense of closure. Its like informal documentation or a post-mortem analysis. Theres always stuff Id like to improve, but if I keep focusing on the same thing forever, the list of things I want to do will never shrink.

Another benefit of writing everything down: itll serve as a reference for future-me when I inevitably forget what I did or how I did it. Thinking of future-me using this as a reference also forces present-me to be a bit more thorough, even if I dont expect many people to read it.

And finally, as always, its about the journey, not the destination. Im not expecting every post here to be about a completed project—but they will all be about something I found interesting enough to write down.

Yes, but why a blog?

All those reasons are fine, but none of them actually require a blog. I could write tweets (lol), Facebook posts, TikToks. Even if I want to self-host, I could use Mastodon instead of a blog.

A blog is… old people media. And Im not old people, right?

In this case (and not only… womp womp) I am old people. I still prefer the idea of smaller, distributed, simple sites and services like in the old internet, rather than the centralized, data-mining, attention-grabbing mess we have now. Also, Mastodon just doesnt feel like the right format. Its definitely what Id use instead of Twitter, but not for “documentation.”

A blog feels more fitting. Its extremely free-form, no size limits either way. I can define groups, filters, organize stuff with labels…

How a blog

Now that I'm settled on the why, let's take a look at the how.

Different concepts (CMS vs static websites)

Keeping with the “old internet” spirit, one of the first requirements I nailed down—besides self-hosting—was that the blog should be statically generated. I did try deploying Ghost  [2], and I appreciated its polish (everything looks great on that platform). But I quickly realized any CMS would be overkill for what Im trying to do, and itd diverge from the simple, GitOps-style deployment I want.

So on one hand, CMSs are polished but come with way too many features I wont use. On the other hand, using a static site generator lets me write posts in Markdown, push them to git, and have them deployed automatically with CI/CD. EZ.

The vast world of static website generators

Once I decided to go with a static site generator, I discovered—of course—there are a lot of them. Theres even an awesome GitHub page  [3] listing a bunch, but it was honestly overwhelming.

After some browsing, mostly through Google and Reddit, I narrowed it down to two main contenders: Jekyll and Hugo.

Jekyll is the older, more established option. Tons of GitHub stars, tons of themes.

Hugo is the newer option—fewer stars, but written in Go and supposedly much faster. Looked solid, too.

Decision

For my use case, the differences werent that important. Faster compilation doesnt matter when deploying via CI/CD. The language its written in doesnt make a real difference.

In the end, I just looked for themes. I stumbled on this one called Chirpy  [4] and liked it best. So: Jekyll it is.

Decision, revisited

Or… is it?

One thing I kept noticing when looking up “Jekyll vs Hugo” was how everyone wrote blog posts about migrating from Jekyll to Hugo. I found none going the other way. And everyone mentioned how annoying the migration was.

So I figured, why not try Hugo before committing? I quickly deployed a Hugo site and… yeah, it compiled much faster, even with just three articles. Went from four seconds to under one. Not a big deal now, but it scales.

Plus: Hugo auto-refreshes the page on save (nice), and its more self-contained—easier to install and maintain, which is great for CI.

Long story short: I found a Hugo theme similar to Chirpy and migrated everything over even before the blog technically went live. Win-win?

Infrastructure Both of the themes I looked at are designed for easy GitHub

Pages deployment. Fork the theme, add your content, push—CI/CD handles the rest.

But wheres the fun in that? Hosting it on GitHub isn't very “old internet”, and Im already self-hosting my own git forge, so everythings ready to go.

Self-Hosting I had a few options for deployment. My first idea was to go

self-contained: after the site is built, the files get copied into an nginx container and pushed to my forgejo container registry. Then its deployed via Docker Compose and updated by Renovate.

I tried this—and while its straightforward to implement—it didnt sit well with me. Renovate only updates the digest after a new image is published, so every deployment meant two commits: noisy. Also, building a whole nginx image just to serve a few static files felt redundant—especially when I already have an nginx image serving static pages for another service.

So I went with a more “traditional” route: after the site is built, its copied via SSH to a target machine where the folder is mounted to the existing nginx container. Easier, faster, less overhead.

In the end, the meat of the deployment is in the publish workflow, which can also be referenced in the repository itself  [5]:

name: "Build and deploy website"

on:
  push:
    branches:
      - main
    paths-ignore:
      - .gitignore
      - README.md
      - LICENSE

# Allow one concurrent deployment
concurrency:
  group: "blog"
  cancel-in-progress: true

jobs:
  build-push:
    name: Build and Push Hugo Site
    runs-on: ubuntu-latest

    steps:
      - name: Checkout
        uses: actions/checkout@v4
        with:
          fetch-depth: 0

      # Build and test site

      - name: Cache Hugo resources
        uses: actions/cache@v4
        env:
            cache-name: cache-hugo-resources
        with:
            path: resources
            key: ${{ env.cache-name }}

      - uses: actions/setup-go@v5
        with:
            go-version: "^1.17.0"
      - run: go version

      - name: Setup Hugo
        uses: https://github.com/peaceiris/actions-hugo@v2
        with:
            hugo-version: "latest"
            extended: true

      - name: Build
        run: hugo --minify --gc

      - name: Copy website to destination server
        uses: https://github.com/garygrossgarten/github-action-scp@release
        with:
          local: public
          remote: /srv/docker/nginx/html/blog
          host: ${{ secrets.SSH_HOST }}
          port: ${{ secrets.SSH_PORT }}
          username: ${{ secrets.SSH_USER }}
          privateKey: ${{ secrets.SSH_PRIVATE_KEY }}
          rmRemote: true

Rules... Nay, guidelines

  • I dont do projects to write a blog post. I write blog posts to document projects.

  • No promises about future posts. That never works out (Ill explain why that is… in a future post).

What to expect, and how often can be expected No expectations. No schedule.

No guarantees of quality or consistency. Youve been warned.

Postscriptum: I started writing this post on April 7th, but only managed to publish it now. Is that an indicator of how often I'm going to actually publish stuff? Yes, probably it is. Aaaaanyway, I'm out.