Diese Seite — Zola, Git, GitHub Actions
Diese Seite läuft mit Zola — einem statischen Site-Generator, der aus Markdown-Dateien fertige HTML-Seiten baut. Kein PHP, kein Datenbankserver, kein WordPress, das gepatcht werden will. Nur Dateien, die auf einem Server liegen.
Hier dokumentiere ich, wie das Setup aussieht: von der Installation auf meinem Rechner (openSUSE Tumbleweed) bis zum automatischen Deployment auf den Server, wann immer ich etwas pushe.
Was ist Zola?
Zola nimmt Markdown-Dateien und ein HTML-Template und baut daraus eine fertige statische Website. Das Ergebnis ist ein Ordner voller HTML-, CSS- und JS-Dateien, die man einfach auf einen Webserver legen kann — ohne Laufzeitumgebung, ohne Datenbank.
Der Vorteil: Es gibt nichts, das angegriffen werden kann. Keine Nutzerdatenbank, kein Login-Formular, kein CMS. Die Seite ist so sicher wie das Dateisystem des Servers.
Der kleine Nachteil: Man braucht einen lokalen Workflow. Man schreibt lokal, baut lokal (oder lässt das bauen von einem CI-System erledigen), und deployed dann. Das klingt nach mehr Aufwand als es ist.
Zola auf openSUSE Tumbleweed installieren
Zola ist direkt im offiziellen Tumbleweed-Repository. Bei einem Rolling Release wie Tumbleweed vor jedem Install kurz die Paketlisten aktualisieren:
sudo zypper refresh
sudo zypper install zola
Fertig. Keine zusätzlichen Paketquellen, kein Herunterladen von Binaries von irgendwo.
Zum Prüfen ob es geklappt hat:
zola --versionProjekt anlegen
mkdir ~/webprojekte
cd ~/webprojekte
zola init meine-seite
Zola fragt ein paar Dinge: URL der Seite, ob Sass-Kompilierung gewünscht ist, ob Syntaxhervorhebung aktiviert werden soll. Das lässt sich alles später in der zola.toml ändern — also einfach mit Enter durchklicken.
Die entstehende Struktur:
meine-seite/
├── zola.toml # Konfiguration der Seite
├── content/ # Markdown-Dateien (Blogartikel, Seiten)
├── templates/ # HTML-Templates
├── static/ # Statische Dateien (CSS, Bilder)
├── themes/ # Themes als Git-Submodule
└── public/ # Wird von Zola gebaut — entsteht erst nach `zola serve` oder `zola build`, nicht in GitTheme einbinden
Ich nutze das Terminus-Theme. Themes werden als Git-Submodule eingebunden — so bleibt das Theme aktualisierbar, ohne dass man es kopiert und vergisst.
cd meine-seite
git init
git submodule add https://github.com/ebkalderon/terminus themes/terminus
In der zola.toml dann das Theme aktivieren:
theme = "terminus"Mit GitHub verbinden
Privates Repository auf GitHub anlegen (ohne README, ohne .gitignore — das kommt von lokal), dann:
# .gitignore anlegen, damit der gebaute Output nicht in Git landet
echo "public/" >> .gitignore
git add .
git commit -m "Initial commit"
git remote add origin https://github.com/DEIN-USER/DEIN-REPO.git
git push -u origin main
Man beachte um 22:00 Uhr: Wenn man git init macht und danach direkt git push versucht, ohne vorher einen Commit gemacht zu haben, wird das nix, weil der Branch main noch nicht existiert. Erst committen, dann pushen.
Lokale Vorschau
Bevor etwas deployed wird, kann man sich die Seite lokal ansehen:
zola serve
Zola startet einen lokalen Webserver und öffnet die Seite unter http://127.0.0.1:1111. Änderungen an Markdown-Dateien oder Templates werden automatisch neu geladen.
GitHub Actions: automatisches Deployment
Der interessante Teil. Jedes Mal wenn ich in den main-Branch pushe, läuft eine GitHub Action, die Zola baut und das Ergebnis per rsync auf den Server überträgt.
Datei anlegen unter .github/workflows/deploy.yml:
name: Deploy
on:
push:
branches: [main]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- name: Repository auschecken
uses: actions/checkout@v4
with:
submodules: true # holt das Theme-Submodul mit
fetch-depth: 0
- name: Zola installieren
uses: taiki-e/install-action@v2
with:
tool: zola@0.22.1 # Version anpassen auf eigene lokale Version
- name: Zola bauen
run: zola build
- name: SSH Key einrichten
run: |
mkdir -p ~/.ssh
echo "${{ secrets.SSH_PRIVATE_KEY }}" > ~/.ssh/deploy_key
chmod 600 ~/.ssh/deploy_key
ssh-keyscan -H ${{ secrets.SERVER_HOST }} >> ~/.ssh/known_hosts
- name: Deployen
run: |
rsync -avz --delete -e "ssh -i ~/.ssh/deploy_key -o StrictHostKeyChecking=no" \
public/ \
${{ secrets.SERVER_USER }}@${{ secrets.SERVER_HOST }}:${{ secrets.SERVER_PATH }}/
Der --delete-Parameter bei rsync sorgt dafür, dass gelöschte Dateien auch auf dem Server entfernt werden. Wichtig, sonst sammeln sich alte Seiten an. Nicht das mir das schonmal passiert wäre.
Secrets in GitHub hinterlegen
Die sensiblen Zugangsdaten kommen nicht in den Workflow, sondern als Secrets ins Repository. In GitHub unter Settings → Secrets and variables → Actions:
| Secret | Inhalt |
|---|---|
SSH_PRIVATE_KEY | Privater SSH-Key für den Deployment-User |
SERVER_HOST | IP-Adresse oder Domain des Servers |
SERVER_USER | Nutzername auf dem Server |
SERVER_PATH | Zielpfad auf dem Server, z.B. /var/www/meine-seite |
Der öffentliche Teil des SSH-Keys muss auf dem Server in ~/.ssh/authorized_keys des Deployment-Users stehen.
Dev-Branch für mehrere Rechner
Ich sitze manchmal am Laptop, manchmal am Desktop. Damit der aktuelle Stand überall verfügbar ist, ohne direkt auf main zu pushen und damit ein Deployment auszulösen:
# Einmalig den dev-Branch erstellen und pushen
git checkout -b dev
git push -u origin dev
Auf dem zweiten Rechner:
git fetch
git checkout dev
Der dev-Branch löst keinen Deployment-Workflow aus — der reagiert nur auf main. Wenn ein Stand fertig ist:
git checkout main
git merge dev
git push
Fertig — die Seite aktualisiert sich automatisch.
Der Workflow im Alltag
Markdown-Datei schreiben
→ zola serve zum lokalen Prüfen
→ git add . && git commit -m "Neuer Artikel"
→ git push
→ GitHub Action baut und deployed
→ Seite ist live
Dauert von Push bis live einen kurzen Moment, aber man weiß ja was man bekommt schon vorher.