Posted on

Hello, world!

This is my first post in my new blog to test if everything works the way I want it to - but also to give you some information on how I set it up.

Motivation?

The idea of having a blog always existed, but I never had enough motivation to actually implement everything the way I wanted to. I tend to start projects and develop them until they are "good enough" for me, but it always lack the amount of documentation to make it useful to others. This had to end - or it will be another forgotten side project - we will see. However, two of my colleagues gave me the final push to actually do it as they were very interested in my homelab setup (shout out to Enno and Henry 🙂).

The requirements

It was pretty clear that I wanted to use a static site generator. The main reason is to minimize maintenance and attack surface. I already have enough stuff that wants to be kept up-to-date or surprises you with CVEs. I also didn't want to fiddle with slow and bloated setups nor did I want to have complex database setups and use runtime-evaluated code to show some simple pages.

Major downside of static site generators is, well, the lack of dynamic editing. Deployment is also somewhat clunky as you need to upload the whole site to the server every time something is changed. So this needs to be automated to reduce the friction to a minimum (at the end, I want to document stuff easily, if it gets too complicated, I will just skip it 😉)

I was also pretty sure that I wanted to use a git-based workflow - I am used to it, it has a built in "editing history" and is perfect for text editing - I can write blog posts on a potato as long as it runs git. I also like to use Markdown - it is the de facto standard for documenting Software projects and is the default of every static site generator under the sun that I know of.

The stack

The main ingredients for the blog are

I used a bit with Hugo in the past, but never enjoyed it to work with it - Zola on the other hand is just simple enough to do the job and also pretty fast. Also, it is packaged with Arch Linux and was easy to try out. I found a nice theme for it (apollo, MIT-licensed) and modified it to my needs. I am not the best web developer in the world, so it was nice that someone else did all the hard work for me.

Gitea was easy, as I already had a git server running. I did not want to have the blog publicly accessible, as I'd like to keep my drafts private. Act runner was as well set up already, so I just had to write the workflows for it.

Gitea build workflow

The main blog branch is protected, so that I can have a PR-based workflow. Every commit will build the blog using a workflow, so that nothing can sneak in that is not buildable.

name: Build blog
on:
  push:
    branches:
      - "**"
      - "!main" # do not build on main, deploy will handle that

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - name: Starting action...
        run: echo "Branch ${{ gitea.ref }} will be built for project ${{ gitea.repository }}."
      - name: Checkout blog
        uses: actions/checkout@v3
        with:
          submodules: true
      - name: Install zola
        uses: taiki-e/install-action@v2
        with:
          tool: zola@0.21.0
      - name: build blog
        run: zola build
      - name: Upload blog artifact
        uses: actions/upload-artifact@v3
        with:
          name: blog
          path: public

Safe Deployment

On every merge to main it will be build again and deployed to the server. All I need to do to post(or fix) something is to push some commits to a PR and merge it if I want to release it. Artifacts are uploaded to the server and can be downloaded if required, but usually I just use zola serve locally to keep the surprises to a minimum.

Deploying the site to my server gave me some headaches, as I didn't want to have any compromises in terms of security. For this reason, I wanted to use ssh to transfer the files to the server - the ssh user should no unnecessary privileges and only be able to write to the web root. Gitea luckily has support for secrets, so I can store the ssh private key in gitea and use it in the workflow.

name: Build and deploy blog
on:
  push:
    branches:
      - main

jobs:
  buildAndDeploy:
    runs-on: ubuntu-latest
    steps:
      - name: Starting action...
        run: echo "Branch ${{ gitea.ref }} will be built for project ${{ gitea.repository }}."
      - name: Update package cache
        run: apt-get update
      - name: install rsync
        run: apt-get -yq install rsync
      - name: Checkout blog
        uses: actions/checkout@v3
        with:
          submodules: true
      - name: Install zola
        uses: taiki-e/install-action@v2
        with:
          tool: zola@0.21.0
      - name: build blog
        run: zola build
      - name: setup ssh agent
        uses: webfactory/ssh-agent@v0.9.0
        with:
          ssh-private-key: ${{ secrets.HTTP_DEPLOY_PRIVATE_KEY }}
      - name: deploy blog
        run: rsync -e "ssh -o StrictHostKeyChecking=no" -r -v -P --delete public/* deploy-user@example.com:.

User creation and ssh key setup was done manually and is pretty straight forward. Create a system user(no account expiration, no home folder):

useradd -r deploy-user

and disable everything that is not strictly required for transferring the files in /etc/ssh/sshd_config

Match User deploy-user
        AuthorizedKeysFile /path/to/user/authorized_keys # required as we don't have a home folder
        AllowTcpForwarding no
        X11Forwarding no

We can then use the authorized_keys file to store the ssh private key and further restrict what the user can do. I chose rsync for transfer - it comes with a handy script to restrict the user to a specific directory called rrsync (man page), so that my authorized_keys file looks like this:

command="/usr/bin/rrsync /path/to/blog/webroot",no-agent-forwarding,no-port-forwarding,no-user-rc ssh-rsa AAAA...

Conclusion

I am pretty happy with the result and if you can read this, It worked 😁. We will see how it goes, but I think it is a good start for a blog. I will slowly add my projects that I already finished to the site and maybe add some more content in the future (yes, also the homelab setup, I hear you).