Files
jonnybravo a62b6d36f8
Test & Deploy Hugo Docker CMS / test-and-deploy (push) Successful in 4m17s
Anpassung README
2026-09-08 14:59:15 +02:00

6.3 KiB
Raw Permalink Blame History

Hugo Docker CMS

Hugo-basiertes CMS im Docker-Stack mit Caddy als TLS-Reverse-Proxy. Markdown-Dateien einfach in content/ ablegen – Hugo rendert sie automatisch.

Architektur

                    Port 5443
Browser ── HTTPS ──→ Caddy ── HTTP ──→ Hugo (live-reload)
                     :2-alpine       hugomods/hugo:latest
                     self-signed     markdown → HTML
Komponente Image Aufgabe
Hugo hugomods/hugo:latest (0.165+) Rendert .md-Dateien, live-reload via --watch
Caddy caddy:2-alpine HTTPS-Terminierung, Reverse-Proxy → Hugo:1313

Verzeichnisstruktur

hugo_docker/
├── docker-compose.yml       # Hugo + Caddy Stack
├── Caddyfile                # TLS + Reverse-Proxy
├── scp_copy.py              # SCP-Transfer + SSH Docker-Restart mit Health-Check
├── content/                 # ← .md-Dateien hier ablegen (Host-Mount)
├── crt/                     # Self-signed Zertifikate
├── site/                    # Hugo-Config, Layouts, CSS
│   ├── hugo.toml
│   ├── entrypoint.sh        # Auto-Frontmatter + Besitzer-Fix (chown) + Hugo-Server
│   ├── assets/css/main.css  # Modernes CSS (oklch, dark mode, grid)
│   └── layouts/             # HTML-Templates
├── ansible/
│   ├── deploy.yml           # Playbook
│   ├── tasks.yml            # Geteilte Tasks (DRY)
│   ├── templates/           # Caddyfile.j2, hugo.toml.j2
│   └── molecule/default/    # CI-Tests (Ubuntu Docker)
└── .gitea/workflows/
    └── deploy.yml           # CI: Molecule-Test → Deploy

Schnellstart (lokal)

# Zertifikate generieren (nur einmal)
python3 -c "
import sys; sys.path.insert(0,'../Python_Skripte/create_selfsign')
from selfsign_ca import generate_and_save_cert
generate_and_save_cert(cert_common_name='localhost', cert_name='localhost')
"

# Container starten
docker compose up -d

# HTTPS aufrufen
curl -k https://localhost:5443/

Nutzung

# Neue Seite anlegen – .md-Datei in content/ werfen
cat > content/mein-artikel.md << 'EOF'
---
title: "Mein Artikel"
date: "2026-09-08"
---

Inhalt im **Markdown**-Format.
EOF

# Kein Neustart nötig – Hugo erkennt Änderungen automatisch
docker compose restart hugo   # nur bei komplett neuen Dateien

SCP-Sync (scp_copy.py)

Skript zum Synchronisieren lokaler .md-Dateien auf den Ziel-Host und Neustarten des Hugo-Containers via SSH:

cd hugo_docker
python3 scp_copy.py

Ablauf:

  1. SCP kopiert alle .md-Dateien aus scr/ nach dest
  2. docker compose restart hugo wird via SSH auf dem Ziel-Host ausgeführt
  3. Health-Check pollt curl https://localhost:5443/ bis Hugo 200 antwortet (max 15 s)

Alle Pfade sind dynamisch aus dest abgeleitet — compose_file wird aus dem content/-Pfad berechnet (content/ → docker-compose.yml). Keine hartkodierten Pfade.

Frontmatter

Der Entrypoint (site/entrypoint.sh) fügt automatisch fehlendes YAML-Frontmatter in .md-Dateien ein – extrahiert Titel aus der ersten #-Überschrift, Datum aus dem Datei-Änderungsdatum.

Hugo benötigt diesen ----Block:

---
title: "Meine Seite"
date: "2026-09-08"
---

Mit dem Entrypoint kannst du beliebige .md-Dateien in content/ werfen.

Permission-Handling

Der Hugo-Container läuft als root (notwendig für den Build-Lock). Der Entrypoint gibt den Besitz modifizierter .md-Dateien per chown an den Host-User zurück — gesteuert über HOST_UID/HOST_GID in docker-compose.yml:

environment:
  HOST_UID: "1000"
  HOST_GID: "1000"

Kein sudo chown-Gefrickel mehr — SCP-Overwrites klappen nach jedem Restart.

Deployment (Ansible)

Auf entfernten Host ausrollen:

cd ansible
ansible-playbook -i "ras-dan-01," deploy.yml

Variablen (optional):

ansible-playbook -i "ras-dan-01," deploy.yml \
  -e "target_hostname=ras-dan-01 target_port=5443"

Das Playbook legt alles unter ~/.docker/hugo/ auf dem Ziel-Host ab, rendert Templates mit Hostname/Port und startet die Container.

Zertifikate

Generiert mit Python_Skripte/create_selfsign/selfsign_ca.py (lokales Tool). Jedes Zertifikat enthält eine SAN (Subject Alternative Name) Extension – Pflicht für moderne Browser.

# CA systemweit vertrauen (optional, für Browser ohne Warnung)
sudo cp crt/ca.crt /etc/ca-certificates/trust-source/anchors/hugo-docker-ca.crt
sudo update-ca-trust

# Firefox / qutebrowser (NSS-Store)
certutil -A -d sql:$HOME/.pki/nssdb/ -t "CT,," \
  -n "Hugo Docker CA" -i crt/ca.crt

CI/CD (Gitea Actions)

Workflow in .gitea/workflows/deploy.yml – läuft auf Runner mit Label shell:

Push auf main
  → molecule test (Ubuntu Docker)
    → syntax, create, prepare, converge, idempotence, verify, destroy
  → ansible-playbook deploy auf ras-dan-01

Voraussetzungen auf dem Runner:

  • Docker + Docker Compose
  • molecule + molecule-plugins[docker] (vorinstalliert)
  • ansible-core (vorinstalliert)
  • SSH-Agent mit Key für ras-dan-01

CSS-Features

Modernes Theme in site/assets/css/main.css:

  • oklch()-Farbraum mit light-dark() – automatisch hell/dunkel
  • CSS Grid Layout (Header – Main – Footer)
  • TOC (Table of Contents) als aufklappbares <details>-Element
  • Code-Highlighting mit Catppuccin-Mocha-Theme
  • Responsive (max-width: 840px)

Hugo-Version

  • Image: hugomods/hugo:latest (aktuell 0.165.0, August 2026)
  • hugo.toml verwendet locale statt languageCode (v0.158+)
  • Goldmark-Renderer mit unsafe: true (HTML in Markdown erlaubt)

Troubleshooting

Problem Lösung
Neue .md-Dateien erscheinen nicht docker compose restart hugo (Entrypoint läuft nur beim Start)
Browser zeigt Zertifikatswarnung CA in NSS-Store importieren (s.o.)
Caddy startet nicht docker compose logs caddy – TLS-Zertifikate prüfen unter crt/
Zertifikatsfehler "no SAN" Zertifikate mit selfsign_ca.py neu generieren (SAN ist jetzt enthalten)
Molecule-Test schlägt fehl ansible_remote_tmp: /tmp/.ansible in molecule.yml prüfen
502 Bad Gateway nach Deploy ssh <host> "docker compose -f ~/.docker/hugo/docker-compose.yml logs hugo"
Permission denied bei SCP HOST_UID/HOST_GID in docker-compose.yml prüfen, ggf. chown manuell ausführen