karim ee4c7875ad Fix: Test-Seite + SFTP-User darf eigene Files überschreiben
- 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.
2026-05-26 00:01:29 +02:00

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-ch an
  • 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

  1. Neuen Public Key oben im Script in SSH_PUBKEYS ergänzen, committen
  2. Auf jedem bestehenden Server Script erneut laufen lassen (überschreibt /etc/ssh/sftp-keys/<user>/authorized_keys)

Alternativ einzeln per Hand die authorized_keys updaten.

S
Description
Setup-Script für Hugo-Hosting LXC-Container (Debian 12 + nginx + SFTP-only)
Readme 41 KiB
Languages
Shell 100%