blog/content/post/0001-hello-friend/index.md
2025-04-21 09:20:00 +02:00

242 lines
9.3 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

---
title: Hello, Friend
description: So I've decided to have a blog
slug: hello-friend
date: 2025-04-20 22:28:00+0200
categories:
- Technology
- Projects
tags:
- 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]]:
```yaml
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.
**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.
[1]: https://web.archive.org/web/20180810023635/http://martin.md/
[2]: https://ghost.org/
[3]: https://github.com/myles/awesome-static-generators
[4]: https://chirpy.cotes.page/
[5]: https://git.martin.md/radu/blog