Welcome to the first post 😀

Starting today, I will write a small post almost every day about the things that I am personally and professionally involved with.

I would like to begin by reporting on how I set up this blog:

For this, I have installed the tool Hugo.

Hugo is written in Go and allows you to create static websites, such as this blog, without needing to run a server with Node.js or .NET. The finished website consists only of ready-made HTML pages and images, which only need to be sent to the browser.

The content has to be written in Markdown and there are plenty of themes available for every usecase.

As you can see, the loading time is already quite fast and you don’t need to host an expensive server.

Create your webpage

If the tool is installed, create a new project with

hugo new site mywebsite

and then switch to the new directory with

cd mywebsite

It is recommended that git is installed in order to create a new repository using the following commands:

git init
git submodule add https://github.com/theNewDynamic/gohugo-theme-ananke.git themes/ananke

which install an example theme using submodule.

In a Unix/Linux terminal, the theme can be added to the configuration file hugo.toml using the command

echo "theme = 'ananke'" >> hugo.toml

Finally, the development server can be started using the command:

hugo server

and usually accessed through the address http://localhost:1313/ in a browser.

Changes are updated directly in the browser as long as the server is running.

To create a new page, use the command

hugo new content posts/my-first-post.md

which can be accessed at http://localhost:1313/posts/my-first-post/

The new file my-first-post.md contains a header, as well as content:

+++
title = 'My First Post'
date = 2023-09-05T23:09:00+01:00
draft = true
+++
## Introduction

This is **bold** text, and this is *emphasized* text.

Visit the [The GitFather's Blog](https://blog.kloubert.dev) website!

Once the first pages are completed, they can now be generated for the finished homepage:

hugo

The output files will be placed in the subdirectory public/ and can be opened through the index.html file.

Automatic Build and Deployment Process with GitHub

If the website is not updated very often, it is usually sufficient to do everything manually from building to saving on the web server.

However, it is more convenient to have a build and release pipeline on Azure DevOps, GitLab, or GitHub.

Personally, I run a Raspberry Pi with Gitea from home.

However, since this requires a lot of effort to set up, I will explain it using GitHub Actions as an example.

This is usually free and completely sufficient for private use.

The good thing about this is that the setup is very simple, as you only need to upload a YAML file like publish.yaml to the subdirectory .github/workflows/ in your GitHub repository.

GitHub recognizes this automatically and immediately starts the tasks as described there.

The publish.yaml could look like this, for example:

name: Build and publish

on:
  push:
    branches:
      - main

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Build website
        run: bin/hugo -D --config ./hugo.toml
      - name: Cleanup target directory
        uses: appleboy/ssh-action@master
        with:
          host: ${{ secrets.SSH_HOST }}
          port: ${{ secrets.SSH_PORT }}
          username: ${{ secrets.SSH_USERNAME }}
          key: ${{ secrets.SSH_KEY }}
          script: |
            rm -rfv ~/transfer/blog.example.com
            mkdir -v -p ~/transfer/blog.example.com
            sudo rm -rfv /var/www/blog.example.com/*            
          script_stop: true
      - name: Upload directory
        uses: appleboy/scp-action@master
        with:
          host: ${{ secrets.SSH_HOST }}
          port: ${{ secrets.SSH_PORT }}
          username: ${{ secrets.SSH_USERNAME }}
          key: ${{ secrets.SSH_KEY }}
          source: "public/*"
          target: "~/transfer/blog.example.com"
      - name: Move to target
        uses: appleboy/ssh-action@master
        with:
          host: ${{ secrets.SSH_HOST }}
          port: ${{ secrets.SSH_PORT }}
          username: ${{ secrets.SSH_USERNAME }}
          key: ${{ secrets.SSH_KEY }}
          script: |
            sudo mv -v ~/transfer/blog.example.com/public/* /var/www/blog.example.com
            sudo chown -R -v www-data:www-data /var/www/blog.example.com/*            
          script_stop: true

With

name: Build and publish

the display name is set for display the action on GitHub.

on:
  push:
    branches:
      - main

This specifies that the GitHub Action should be executed when changes are pushed to the main branch.

Next, the steps to be executed are defined:

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

Here, the action is executed in a current Ubuntu container and the code is checked out at the beginning using actions/checkout@v4.

The step

      - name: Build website
        run: bin/hugo -D --config ./hugo.toml

builds the website with an x64 binary, which can be downloaded at https://github.com/gohugoio/hugo/releases and must be placed in the subdirectory bin/ of the GitHub repository.

      - name: Cleanup target directory
        uses: appleboy/ssh-action@master
        with:
          host: ${{ secrets.SSH_HOST }}
          port: ${{ secrets.SSH_PORT }}
          username: ${{ secrets.SSH_USERNAME }}
          key: ${{ secrets.SSH_KEY }}
          script: |
            rm -rfv ~/transfer/blog.example.com
            mkdir -v -p ~/transfer/blog.example.com
            sudo rm -rfv /var/www/blog.example.com/*            
          script_stop: true

uses the appleboy/ssh-action to delete the directory on the target server.

The host, port, username, and SSH key of the target server are stored as secrets.

With appleboy/scp-action, the created files from the public/ folder will be uploaded to the target server:

      - name: Upload directory
        uses: appleboy/scp-action@master
        with:
          host: ${{ secrets.SSH_HOST }}
          port: ${{ secrets.SSH_PORT }}
          username: ${{ secrets.SSH_USERNAME }}
          key: ${{ secrets.SSH_KEY }}
          source: "public/*"
          target: "~/transfer/blog.example.com"

The last step

      - name: Move to target
        uses: appleboy/ssh-action@master
        with:
          host: ${{ secrets.SSH_HOST }}
          port: ${{ secrets.SSH_PORT }}
          username: ${{ secrets.SSH_USERNAME }}
          key: ${{ secrets.SSH_KEY }}
          script: |
            sudo mv -v ~/transfer/blog.example.com/public/* /var/www/blog.example.com
            sudo chown -R -v www-data:www-data /var/www/blog.example.com/*            
          script_stop: true

moves the uploaded files to /var/www/blog.example.com folder and assigns them to user and group www-data.

The files can then be easily hosted using lighttpd, NGINX, or Apache.

Once set up, you save yourself a lot of work and stress and you learn something in the process 👍

Have fun!