Self-hosting blog

So I decided I want to write a bit of tech blog from time to time, to capture random thoughts and ground myself a bit.

I looked at the current state of blog sites on-line, and I wasn’t satisfied.

I know about Medium and Substack, but they all seemed very complicated to me. I don’t want to use the Blogger, because I prefer to de-google myself, reduce my reliance on Google products.

I looked at Ghost, and it’s fine, but not free. The price is low, but it might be more fun to have something less professional.

Tumblr is old (although overwise very cool).

I found Letterpad somewhere on Reddit, and I’ve attempted to set up a blog there, but at some point it attempted to redirect me to https://letterpad.appupdate/site-info (looks like a missing slash somewhere). Adding the slash manually didn’t work.

Nothing worked, nothing is fun.

I like to keep my own notes in Markdown format, converting to HTML using Pandoc. Maybe this is the most lightweight solution? (It obviously isn’t, it’s overcomplicated and requires too much work - but that makes it more fun).

It’s trivial to use templates in Pandoc, so no scripting is required initially.

For hosting, I could just put them in public_html somewhere, but that would be too easy.

I’m not that experienced in Docker and containers, so let’s use that.

Also, since the source code is owned by me and it’s just htmls, I have no feer of vendor-lock in, so let’s use Google Cloud Platform. It might seem like it’s conflict with the initial requirements of de-googlification, but the GCP can be trivially switched for something else, it’s just running a container, so I don’t consider it a lock-in.

I looked how hard it would be to build a static site out of a bunch of HTML files, and the first result in the search was the official “httpd” image from docker at https://hub.docker.com/_/httpd. There’s an Apline version there and it looks maintained and lightweight. A full Apache HTTP Server to serve a few HTML files is probably an overkill, but on the other hand the Apache HTTP Server is super stable and very fast, so why not.

I use simple make file to convert Markdown files to HTML:

MDS=$(wildcard *.md)
HTMLS=$(MDS:.md=.html)

default: htmls

htmls: $(HTMLS)

%.html: %.md
    pandoc \
        --toc \
        --shift-heading-level-by=-1 \
        -c md.css \
        -o $@ \
        --template template.html \
        $<

The template might grow (there’s tons of examples over the internet), but initially we’ll start with:

<html>
    <head>
        <title>$title$</title>
        <style>
            body {
                font-family: sans-serif;
            }

            h1, div.body, div.menu {
                margin: auto;
                max-width: 800px;
            }
        </style>
    </head>
    <body>
        <div class="menu">
            <a href="index.html">Index</a>
        </div>
        <h1>$title$</h1>
        <div class="body">$body$</div>
    </body>
</html>

This builds HTML files. There’s also an index.md file:

# Index

-   2024:
    -   [2024-11-29: Hello, world](2024-11-29-hello.html)

It’s not automatically generated yet. It might be, at some point, but for now listing the articles manually feel like less work than auto-generating the index.

Let’s now try to wrap it in a container image. The official page of the httpd image contains basic instructions:

FROM httpd:2.4
COPY ./public-html/ /usr/local/apache2/htdocs/

Those two lines would be enough if the files resided in ./public-html.

My files are (for now) present directly in the directory, so I changed the second line to:

FROM httpd:alpine
COPY *.html /usr/local/apache2/htdocs/

This did not work, because of the file permissions, I guess the files are not world-readable when copied this way from my local workspace.

So I looked up how to fix the permissions and my full Dockerfile looks like this now:

FROM httpd:alpine
COPY --chmod=644 *.html /usr/local/apache2/htdocs/

I’ve build it using comands from the docs, but replacing docker with podman:

podman build -t techblog-test .
podman run -dit --name techblog-test -p 8080:80 techblog-test

This worked, I could access my pretty blog on http://localhost:8080/.

I’ve then created an Artifact Registry on GCP, and pushed it like this:

podman build --platform linux/amd64 . -t europe-central2-docker.pkg.dev/typesafe-org/techblog/techblog:latest
gcloud auth print-access-token | podman login -u oauth2accesstoken --password-stdin europe-central2-docker.pkg.dev
podman push europe-central2-docker.pkg.dev/typesafe-org/techblog/techblog:latest

I’ve then created a Cloud Run app, and it seems to be up at https://techblog-409179209141.europe-central2.run.app.

Next steps would be to set up a domain name for this, but as I remember, it takes a few commands on GCP, so I’ll leave this for later.