published on
tags: uberspace Gitolite Git hugo

Hugo mit Gitolite3 auf Uberspace nutzen

Hugo ist nicht nur der Name eines alkoholischen Getränks, sondern mit ihm kann man auch sehr sinnvolle Sachen anstellen. Webseiten generieren nämlich. So wie auch hier auf diesem Blog.

Aber anders, als von den gewöhlichen CMS her gewohnt, generiert Hugo statische HTML-Seiten und ist damit im Vergleich zu jedem PHP-Monstrum rasend schnell. Dafür ist die Einrichtung nicht ganz so einfach, aber mit ein wenig Linux-Kenntnissen kein Problem.

Was man braucht

Jeder Hoster, auf dem man statische Dateien hosten kann, also so ziemlich alle, kommt in Frage. Um aber das letzte bisschen Komfort herauszuholen, und Hugo mit Hilfe von Git(olite) zu automatisieren, braucht man schon etwas mehr: Dafür kann ich meinen Hoster uberspace empfehlen. Mit dem dort vorhandenen SSH-Zugang haben wir alles, was man braucht.

Hinweis: Diese Anleitung setzt Gitolite v3 voraus. Auf uberspaces ist aber standardmäßig nur Gitolite v2 installiert. Die Installation von Gitolite v3 auf einem uberspace habe ich bereits in einem anderen Blogartikel beschrieben.

Hugo lokal

Zuerst lädt man sich die aktuelle Version von Hugo auf seinen lokalen Rechner. Dabei ist es egal, ob Linux oder Windows, Hugo läuft dank der Programmiersprache Go plattformübergreifend. Um Hugo immer zur Hand zu haben, sollte es auch noch im Path liegen.

Anschließnd kann man mit Hugo herumexperimentieren: Um eine Hugo-Seite anzulegen, gibt es bereits eine sehr gute Anleitung auf der offiziellen Website, daher spar’ ich mir das hier. Allgemein ist die Dokumentation von Hugo recht gut und hilft bei vielen Problemen schnell weiter. Dort ist auch beschrieben, wie man Themes verwendet oder erstellt.

Hugo auf dem Server

Die lokal generierte Seite könnte man jetzt mit Hilfe von SFTP auf den uberspace übertragen. Aber das bei jeder Änderung neu machen? Ist doch viel zu aufwendig! Zum Glück kann man auf dem uberspace sehr gut Dinge automatisieren…

Zu Beginn müssen wir Hugo auf dem Server installieren (0.24.1 jeweils mit der aktuellen Version ersetzen, Stand 2.7.2017):

$ wget https://github.com/gohugoio/hugo/releases/download/v0.24.1/hugo_0.24.1_Linux-64bit.tar.gz
$ tar -xzf hugo_0.24.1_Linux-64bit.tar.gz
$ mv hugo ~/bin/hugo

So installiert bringt uns Hugo natürlich noch nichts, dafür muss noch Git her:

Git(olite) einrichten

Ihr braucht sowohl Git auf dem lokalen Rechner als auf dem Server. Natürlich ist das aber bei uberspace schon vorinstalliert. Git gibt es auch für nahezu alle Plattformen (inkl. Windows).

Um jetzt die lokale Seite unter git zu stellen, reicht diese drei Befehle im Verzeichnis der Hugo-Seite aus:

$ git init .
$ git add --all
$ git commit -m "Hugo-Seite eingecheckt!"

Auf dem Server legen wir jetzt ein Repository unter gitolite an:

In der Datei conf/gitolite.conf im Admin-Repository müssen z.B. die folgenden Zeilen eingefügt werden:

Hinweis: $REPO_NAME, $GITOLITE_USERNAME und später $DOMAIN sind keine Variablen der Shell, sondern müssen durch die entsprechenden Werte der eigenen Installation ersetzt werden.

repo $REPO_NAME
    RW+                         =    $GITOLITE_USERNAME

Mit einem anschließenden Commit und Push zum Server wird das neue Repo auch angelegt. Jetzt kann es als origin des lokalen Repos hinzugefügt werden:

$ git remote add origin user@host.uberspace.de:repo-name

Pushen würde jetzt zwar gehen, aber eine Änderung in den Quelldateien würde noch kein Erstellen der Website auslösen.

Git hooks to the rescue!

Auf dem Server haben wir jetzt ein angelegtes Repository für unsere Website und können in dieses Änderungen einchecken. Damit jetzt auch die Website bei jedem git push auch automatisch geneirert wird, benutzen wir einen sog. Git Hook. Dies ist eine Scriptdatei, die nach einer bestimmten Git-Aktion auf dem Server ausgeführt wird (z.B. eben ein push).

In einer normalen Git-Installation sind solche Hooks schnell und einfach anzulegen, bei Verwendung von gitolite ist dies aber etwas komplizierter: In der Datei .gitolite.rc im Homeverzeichnis muss die folgende Zeile auskommentiert werden:

LOCAL_CODE                =>  "$rc{GL_ADMIN_BASE}/local",

Anschließend kann im gitolite-admin-Repo im neu anzulegenden Ordner local/hooks/repo-specific die Datei deploy-hugo-web angelegt werden (genau so übernehmen):

#!/bin/sh
# Die folgende Variable speichert den Pfad zum Repository um das es geht.
GIT_REPO=$HOME/repositories/$GL_OPTION_HUGO_REPO

# Die folgende Variable speichert den Pfad zum tmp Ordner in dem dann der Hugo
# Befehl ausgefuehrt wird um die deine Seite in den Webroot zu befoerdern.
TMP_GIT_CLONE=$HOME/tmp/tmp-hugo-build-$RANDOM

# Die folgende Variable speichert den Pfad zum Webroot
PUBLIC_WWW=/var/www/virtual/manuelhu/$GL_OPTION_HUGO_DOMAIN/

# Hier geht's dann ans eingemachte:
# Mit "git clone" wird Dein Repository in das tmp-Verzeichnis geklont
git clone $GIT_REPO $TMP_GIT_CLONE

# Altes www-Verzeichnis löschen und neu anlegen
rm -rf $PUBLIC_WWW
mkdir $PUBLIC_WWW

# Dein persoenliches .bash_profile wird aktiviert damit der
# Hugo-Befehl benutzt werden kann.
. /home/manuelhu/.bash_profile

# Hugo generiert die Seite aus dem tmp-Verzeichnis heraus
# in den Webroot hinein.
HUGO_CACHEDIR=$HOME/tmp hugo -s $TMP_GIT_CLONE/hugo -d $PUBLIC_WWW

# Das tmp-Verzeichnis wird geloescht und das Shell-Programm beendet.
rm -Rf $TMP_GIT_CLONE

# Berechtigungen setzen
chmod 755 $PUBLIC_WWW
find $PUBLIC_WWW -type f -exec chmod 644 {} \;
find $PUBLIC_WWW -type d -exec chmod 755 {} \;

exit

Diese muss lokal im Admin-Repo dann mit chmod +x als ausführbar gekennzeichnet werden.

Im Block für das entsprechende Repository in der Datei conf/gitolite.conf müssen jetzt noch ein paar Zeilen ergänzt werden, damit gitolite auch weiß, dass wir einen Hook in unserem Repo haben wollen:

Nochmaliger Hinweis: $REPO_NAME, $GITOLITE_USERNAME und $DOMAIN sind keine Variablen der Shell, sondern müssen durch die entsprechenden Werte der eigenen Installation ersetzt werden.

Die verwendete Domain muss natürlich zuvor auch auf den uberspace aufgeschaltet worden sein.

    option ENV.HUGO_REPO        =    "$REPO_NAME.git"
    option ENV.HUGO_DOMAIN      =    "$DOMAIN"
    option hook.post-receive    =    deploy-hugo-web

Der Hook kann auf diesem Weg (durch die Optionen) auch für mehrere Repositories (und damit Websites) verwendet werden. Die Datei des Hooks muss dafür auch nur einmal angelegt werden, der Block in der Konfigurationsdatei muss aber natürlich für jedes Repository neu hinzugefügt und konfiguriert werden.

Anschließend wird durch einen Push des Admin-Repos die neue Konfiguration aktiv. Jetzt sollte nach einem Push des Hugo-Repos zum uberspace-Server die Seite unter $DOMAIN zu sehen sein.

Das Wort zum Schluss: Hugo aktualisieren

So in etwa alle 1-2 Monate erscheint einen neue Version von Hugo. Das Aktualisieren ist gleich dem Installieren oben. Es müssen immer sowohl lokal und auf dem Server die gleichen Hugo-Versionen installiert sein, sonst gibt es möglicherweise Probleme.

Da Hugo ja selbst nicht vom Internet aus erreichbar läuft, ist eine Aktualisierung auch nicht zwingend vom Sicherheitsaspekt aus notwendig. Dieser Blog läuft beispielsweise immer noch auf Hugo v0.21, obwohl bereits v0.24 erschienen ist. Oft haben neue Hugo-Version die Eigenheit, bestehende Features zu ändern und damit zu älteren inkompatibel zu sein.