Im Februar 2022 habe ich mein Blog auf neue Füße gestellt. Bisher wurde es mittels Wordpress betrieben. Ab jetzt kommt Hugo zum Einsatz.

Warum der Umzug?

Wordpress ist der Platzhirsch unter den Lösungen zum Publizieren von Inhalten. Es wird ein umfangreicher Werkzeugkasten geliefert, der fast keine Wünsche offen lässt. Für alles Weitere gibt es einen Berg an Plugins. Für viele Blogger ist Wordpress daher eine gute Lösung.

Im Fall meines Blogs sind die Anforderungen recht gering. Ich möchte Texte veröffentlichen und diese mit ein paar Bildern aufhübschen. Darüber hinaus soll mein Blog nichts können.

  • Keine Werbung
  • Keine Analysen
  • Keine Kommentarfunktion

Einfach nichts, dass mir unnötige Arbeit in Sachen Moderation oder DSGVO macht.

Um Wordpress derart spartanisch zu gestalten, muss man einiges machen. Es sind mehrere Plugins nötig, um all die ungenutzten Funktionen abzuschalten. Man könnte es schon unter das Motto “Mehr ist weniger” stellen.

Trotz dieser strengen Diät bleibt Wordpress immer noch eine datenbankgestützte Anwendung, die bei jedem Aufruf Code ausführt. Daraus ergibt sich eine gewisse Angriffsfläche und somit Wartungsaufwand. Updates wollen eingespielt und Backups erstellt werden.

Mir stellte sich also die Frage: Geht das auch einfacher?
Die Antwort ist: Ja, mit Hugo.

Was ist Hugo?

Hugo ist ein “Static Page Generator”. Das bedeutet, dass die finale online gestellte Webseite nur aus statischen Inhalten besteht. Einfach nur HTML, CSS und ggf. JavaScript. Auf dem Server läuft keinerlei Code. Es gibt daher auch keine Datenbank. Code wird nur beim Bauen der Seite ausgeführt. Dies geschieht lokal, oder im Rahmen einer CI Pipeline.

Daraus folgt:

  • Weniger Angriffsfläche
  • Weniger Updates
  • Kein Weniger Wartungsaufwand

Die Inhalte selbst werden in Markdown Syntax erstellt. Dies ist eine sehr einfach zu erlernende Sprache, um formatierte Texte zu erstellen.

Voraussetzungen

Im Rahmen des Artikels kommt ein macOS zum Einsatz. Die Anforderungen sind somit darauf abgestimmt.

  • Eine IDE der Wahl zum Bearbeiten von Textdateien
  • Homebrew zum Installieren von Hugo
  • git zum Laden von Themes und Verwalten der Sourcen
  • Nodejs zum Importieren von Wordpress Inhalten
  • Docker zum Verpacken der Seite
  • GitLab für die Erstellung einer CI Pipeline

Auf anderen Betriebssystemen muss eine Alternative zu Homebrew eingesetzt werden.

Docker und GitLab sind optional. Die von Hugo erzeugte Seite kann natürlich auch via FTP auf einen Webspace geladen werden.

Eine Seite mit Hugo erstellen

Hugo installieren

Informationen zu Hugo findet man unter https://gohugo.io/.
Ebenso finden sich dort Anleitungen, um Hugo auf diversen Betriebssystemen zu installieren (https://gohugo.io/getting-started/installing/).

Im Fall eines macOS mit Homebrew ist die Aufgabe mit einem Befehl erledigt.

$ brew install hugo

Eine neue Seite anlegen

Das Erstellen einer neuen Seite erfolgt ebenfalls denkbar einfach (https://gohugo.io/getting-started/quick-start/):

Man navigiert in der Console in sein Projekte Verzeichnis. Dort führt man folgenden Befehl aus:

$ hugo new site meineSeite

Es wird ein neues Unterverzeichnis meineSeite erstellt. In diesem liegt die neu erstellte Seite und das Schreiben kann losgehen.

Ein Theme einbinden

Themes werden via git als Submodule eingebunden. In meinem Fall verwende ich das Theme Hugo-Paper (https://github.com/nanxiaobei/hugo-paper).

$ git submodule add https://github.com/nanxiaobei/hugo-paper.git themes/paper

Anschließend muss die config.toml angepasst werden.

theme = "paper"

Soll ein anderes Theme zum Einsatz kommen, müssen die Pfade und Namen entsprechend angepasst werden.

Inhalte erstellen

Die einzelnen Beiträge der Seite befinden sich unter meineSeite/content. Dort wird für jeden Beitrag eine Markdown Datei angelegt (mein-erster-artikel.md).

Der Aufbau der Datei ist einfach zu verstehen:

---
title: "Mein erster Artikel"
date: "2022-02-14"
draft: true
---

## Überschrift

Absatz 1.
Satz 1.
Satz 2.

Absatz 2.
Satz 1.
Satz 2.

### Untergeordnete Überschrift

Eine Liste:
* Punkt 1
* Punkt 2
  * Punkt 2.1
* Punkt 3

Man kann auch *kursiv* oder **fett** schreiben.

Der obere Teil, von --- begrenzt, enthält die Meta-Daten der Seite. In diesem Fall den Titel, das Datum der Veröffentlichung und dass die Seite noch ein Entwurf ist (draft = true). Entwürfe werden beim abschließenden Bauen der Seite für den produktiven Einsatz nicht berücksichtigt.

Im unteren Teil befindet sich der Beitrag selbst. Beispiele für übliche Formatierungen mit Überschriften, Absätzen, Listen und Hervorhebungen sind gegeben. Weitere Formatierungen sind, in zahlreich vorhandenen Tutorials zu Markdown, im Netz zu finden.

Möchte man in dem Artikel Bilder verwenden, ist es sinnvoll, anstatt der mein-erster-artikel.md ein neues Verzeichnis mit dem Namen mein-erster-artikel zu erstellen. In diesem legt man dann die Datei index.md an. Die Bilder können dann einfach mit in dem Verzeichnis abgelegt werden.

Ein Bild wird folgendermaßen eingebunden:

![Ein Bild](bild.jpeg)

In den eckigen Klammern wird der Alternativtext erfasst, in den runden Klammern der relative Pfad zum Bild.

Vorschau

Wärend des Schreibens möchte man gern eine Vorschau des Beitrags betrachten können. Dafür bietet Hugo eine Einfache Möglichkeit.

$ hugo server -D

Der Befehl startet einen lokalen Hugo Server. Im Browser erreicht man ihn unter http://localhost:1313. Änderungen an den Beiträgen werden nach dem Speichern sofort angezeigt.

Inhalte aus Wordpress übernehmen

Nun sollen bestehende Beiträge aus dem Wordpress Blog zur neuen Hugo Seite übertragen werden.

Export

Der erste Schritt besteht darin, die Export Funktion von Wordpress zu verwenden. Dabei ist zu beachten, dass man den Export für alle Inhalte verwendet. Das Ergebnis ist eine .xml Datei.

Umwandlung

In der .xml sind die Beiträge in Wordpress-Markup enthalten. Somit sind sie direkt nicht für eine Integration in Hugo geeignet. Sie müssen zunächst in Markdown übersetzt werden.

Auf GitHub gibt es ein sehr nützliches Werkzeug für diesen Anlass. https://github.com/lonekorean/wordpress-export-to-markdown
Um es nutzen zu können, wird eine lokale Nodejs Installation benötigt.

Für die Umwandlung legt man sich zunächst ein neues Verzeichnis an. Dann kopiert man die Wordpress Export Datei dort hinein und benennt sie zu export.xml um.

$ npx wordpress-export-to-markdown

In einem geführten Dialog kann man etliche Optionen für die Umwandlung festlegen. Die Standardwerte sind aber schon sehr gut. Anschließend wandelt das Programm die Beiträge in Markdown um, lädt die verwendeten Bilder von der Wordpress Seite und legt alles schön sortiert in einzelnen Ordnern ab.

Import

Eigentlich muss man nun nur noch die Ergebnisse der Umwandlung in das content Verzeichnis der Hugo Seite kopieren. Es bietet sich aber an, den Markdown Code noch zu formatieren. Ggf. können auch noch die Metadaten der Beiträge angepasst werden.

Eine Hugo Seite mit Docker verpacken

Eine Hugo Seite lässt sich sehr einfach mittels Nginx in ein Docker Image verpacken. Dazu wird im Projekt ein Dockerfile angelegt. Dessen Inhalt sieht folgendermaßen aus:

FROM nginx:alpine
ADD ./public /usr/share/nginx/html

Ist eine lokale Docker Installation vorhanden, kann man folgende Schritte ausführen:

$ docker build -t myHugoSite .
$ docker run -d -p 8080:80 myHugoSite

Die Seite ist nun im Browser unter http://localhost:8080 erreichbar.

Bauen der Seite mit GitLab CI

Ist man Nutzer von GitLab, kann man eine einfache CI/CD Pipeline zum Bauen der Hugo Seite erstellen. Dazu legt man im Basisverzeichnis des Projekts die Datei .gitlab-ci.yml mit folgendem Inhalt an.

variables:
  GIT_SUBMODULE_STRATEGY: recursive
  
stages:
  - build
  - package

hugo:
  stage: build
  image: registry.gitlab.com/pages/hugo:latest
  script:
  - hugo
  artifacts:
    paths:
    - public

package-main:
  stage: package
  image: docker:git
  services:
    - docker:dind
  script:
    - 'echo $CI_BUILD_TOKEN | docker login -u gitlab-ci-token --password-stdin registry.gitlab.com'
    - 'docker build --no-cache -t registry.gitlab.com/myUserName/blog:latest .'
    - 'docker push registry.gitlab.com/myUserName/blog:latest'
  only:
    - main

Im ersten Schritt wird die Seite mittels des hugo:latest Image gebaut. Im zweiten Schritt wird das Image gebaut und in der GitLab Registry hinterlegt.

registry.gitlab.com/myUserName/blog:latest muss natürlich noch auf den eigenen Benutzer- und Repo-Namen angepasst werden.

Wie man das erstellte Image auf einen Server ausrollt, ist jedem selbst überlassen.

Keine Bastelei ohne unerwartete Probleme

Zusammenspiel von Themes und CI/CD

Hat man das Git Submodule des Themes über ssh eingebunden, schlägt die CI Pipeline fehl. Das eingesetzte hugo:latest Image beinhaltet kein ssh. Das Submodule muss via https adressiert werden, um es clonen zu können.

Unveröffentlichte Artikel

Eine Hugo Seite kann Artikel nicht automatisch veröffentlichen. Bei diesem Artikel habe ich draft="false" und das Datum in die Zukunft gesetzt. Dann habe ich die Seite gebaut, und erwartet, dass der Artikel zum gesetzten Datum automatisch auftaucht. Passiert ist es nicht.

Im ersten Moment fühlte es sich wie ein Bug, oder ein fehlendes Feature an. Aber nach genauerem darüber nachdenken, wurde es völlig klar. Eine statische Seite kann nicht Artikel in Abhängigkeit zum aktuellen Datum anzeigen. Es läuft ja kein Code auf dem Server.

Man lernt nie aus.

Man kann natürlich die CI Pipeline nutzen, um eine geplante Veröffentlichung durchzuführen. Man setzt das Datum des Artikels wie gewünscht und richtet einen Bauvorgang mit Zeitplan ein.

Zusammenfassung

Es wurde gezeigt, wie man ein Blog auf Wordpress Basis zu Hugo migrieren kann. Dabei wurde eine neue Hugo Seite erstellt und Inhalte aus dem Wordpress Blog übertragen. Ebenfalls wurde die Einrichtung einer CI Pipeline zum bauen der Seite in GitLab gezeigt.