- Test-Seite (<h1>… OK</h1>) wird nur noch geschrieben wenn der Webroot leer ist, sonst klobbert ein zweiter Lauf existierende Hugo-Inhalte. - chown -R statt chown auf den Webroot, damit der SFTP-User auch Files die der Script-Lauf erzeugt hat (z.B. die Test-Seite selbst) überschreiben kann. Sonst SSH_FX_PERMISSION_DENIED beim Re-Upload derselben Datei via SFTP.
lxc-hugo-host
Setup-Script für minimalistische Hugo-Hosting-Container unter Proxmox.
Richtet einen frischen Debian-12-LXC-Container in einem Schritt ein:
- Nginx mit Security Headers (HTTP only, TLS via vorgelagertem Reverse-Proxy)
- SSH-Daemon als reiner SFTP-Server (kein Shell-Login von außen)
- SFTP-User mit Chroot auf
/var/www - UFW, fail2ban, unattended-upgrades, sysctl-Hardening
- Public Key direkt im Script hinterlegt
Konfiguration
Vor dem ersten Lauf einmalig den eigenen Public Key oben im Script eintragen:
SSH_PUBKEYS="ssh-ed25519 AAAA... user@host"
Mehrere Keys: eine Zeile pro Key innerhalb der Variable.
Pro neuem Server
1. Container in Proxmox erstellen
- Template:
debian-12-standard - Unprivileged: ja
- 512 MB RAM, 1 Core reicht
2. In den Container
Auf dem Proxmox-Host:
pct enter <ctid>
3. Script ausführen
curl -fsSL https://git.kgva.ch/karim/lxc-hugo-host/raw/branch/main/setup-hugo-host.sh \
| bash -s -- meine-domain.ch
Das Script:
- installiert und konfiguriert alles (inkl.
apt update+upgrade) - legt den SFTP-User
webedit-meine-domain-chan - gibt am Ende die fertige Deploy-Zeile aus
4. Reverse-Proxy für TLS
Im Nginx Proxy Manager (oder Caddy) ein Proxy-Host anlegen:
- Domain:
meine-domain.ch - Forward zu:
http://<container-ip>:80 - SSL: Let's Encrypt
5. Deployen
Vom Arbeitsrechner:
hugo --minify
lftp -u webedit-meine-domain-ch, sftp://<container-ip> \
-e "mirror -R --delete public/ /meine-domain.ch/; quit"
Wegen Chroot ist der Zielpfad /meine-domain.ch/, nicht
/var/www/meine-domain.ch/.
Installation von lftp falls noch nicht da:
brew install lftp # macOS
apt install lftp # Debian/Ubuntu
Mehrere Sites pro Container
Script einfach nochmal laufen lassen — neue nginx-Site + neuer SFTP-User werden zusätzlich angelegt, das bestehende Setup bleibt unangetastet.
./setup-hugo-host.sh weitere-domain.ch
SSH-/SFTP-Config auf dem Client (optional)
Damit du dir die langen User-/Hostnamen nicht merken musst, in
~/.ssh/config ergänzen:
Host meine-domain
HostName 192.168.1.46
User webedit-meine-domain-ch
IdentityFile ~/.ssh/id_ed25519
Dann reicht:
lftp -e "mirror -R --delete public/ /meine-domain.ch/; quit" sftp://meine-domain
Sicherheits-Modell
| Angriffsfläche | Status |
|---|---|
| Port 22 (SSH-Shell) | Geschlossen — kein Shell-Login möglich |
| Port 22 (SFTP) | Nur Key-Auth, User chrooted auf /var/www |
| Port 80 (nginx) | Statische Files, Security Headers |
| Port 443 | Nicht im Container — Reverse-Proxy davor |
| Administration | Nur via Proxmox-Host (pct enter) |
| Auto-Updates | Security-Patches täglich, Reboot 03:00 |
| Key-Management | Public Key im Script (Git-versioniert) |
Key rotieren / neue Maschine hinzufügen
- Neuen Public Key oben im Script in
SSH_PUBKEYSergänzen, committen - Auf jedem bestehenden Server Script erneut laufen lassen
(überschreibt
/etc/ssh/sftp-keys/<user>/authorized_keys)
Alternativ einzeln per Hand die authorized_keys updaten.