1. Executive Summary
Dein Hetzner-Server zeigt eine solide Sicherheitsbasis mit mehreren professionell umgesetzten Schutzmechanismen. Die Architektur mit Proxmox-Hypervisor, WireGuard-VPN, Docker-VM und Traefik-Reverse-Proxy ist gut durchdacht.
Stärken der Infrastruktur
- SSH nur über VPN erreichbar (ListenAddress 10.10.10.10) — kein öffentlicher SSH
- WireGuard-VPN mit einzelnem Peer — minimale Angriffsfläche
- CrowdSec IDS aktiv mit Firewall-Bouncer und Community Blocklist (4'820 blockierte IPs)
- Fail2ban aktiv für SSH-Schutz
- Authelia 2FA für sensible Dienste (n8n, Insights, Dashboard)
- Let's Encrypt HTTPS auf allen Diensten
- Unattended-Upgrades für automatische Sicherheitsupdates
- Wöchentliches Backup auf Hetzner Storage Box
- Keine Datenbanken direkt auf Host-Ports exponiert
Kritische Punkte, die sofort behoben werden sollten:
- Mehrere Services öffentlich zugänglich ohne Authentifizierung (Portainer, Open WebUI, LightRAG, Neo4j, Flowise, Lounger)
- UFW-Firewall auf Docker-VM inaktiv — nur CrowdSec als Schutz
- CSP-Header blockiert Google Tag Manager (GTM wird nicht korrekt geladen)
2. Infrastruktur-Übersicht
| Komponente | Details | Status |
| Hypervisor | Proxmox VE auf Hetzner EX44 (188.40.46.49) | OK |
| Docker VM | Ubuntu 24.04.3 LTS, Kernel 6.8.0-94 | OK |
| RAM | 32 GB (6.2 GB genutzt, 25 GB verfügbar) | OK |
| Disk | 193 GB (83 GB genutzt / 43%) | OK |
| Swap | Nicht konfiguriert (0 B) | WARNUNG |
| VPN | WireGuard (10.10.99.0/24) | OK |
| Reverse Proxy | Traefik v2.11 | OK |
| Container | 23 Container (20 aktiv) | INFO |
Netzwerk-Topologie
Internet (188.40.46.49)
│
├─ Proxmox Host (10.10.99.1)
│ ├─ WireGuard VPN (:51820) → 10.10.99.2 (dein Mac)
│ ├─ Proxmox UI (:8006) — nur intern
│ └─ SSH (:22) — nur VPN + intern
│
└─ Docker VM (10.10.10.10)
├─ Traefik (:80/:443) → einziger Public Entrypoint
├─ SSH (:22) — nur auf 10.10.10.10 (VPN only)
├─ CrowdSec (:6060/:8080 localhost)
└─ 20+ Docker Container (nur intern)
3. Netzwerk & Firewall
Öffentlich erreichbare Ports
| Port | Dienst | Bewertung |
| 80/tcp | Traefik (HTTP → HTTPS Redirect) | OK |
| 443/tcp | Traefik (HTTPS, Let's Encrypt) | OK |
| 51820/udp | WireGuard VPN (Proxmox Host) | OK |
OK Minimale Port-Exposition
Nur Port 80, 443 und WireGuard sind öffentlich erreichbar. SSH ist auf die interne IP 10.10.10.10 gebunden — vorbildlich.
Firewall-Status
KRITISCH UFW-Firewall ist inaktiv auf Docker-VM
Die UFW-Firewall ist deaktiviert (Status: inactive). Die iptables INPUT-Chain hat die Default-Policy ACCEPT mit nur einer CrowdSec-Rule. Das bedeutet: Falls CrowdSec ausfällt, gibt es keine Firewall-Schutzschicht.
Hinweis: UFW und Docker haben bekannte Kompatibilitätsprobleme (Docker umgeht UFW-Regeln). CrowdSec mit dem Firewall-Bouncer ist hier die effektivere Lösung. Trotzdem wird eine zusätzliche Absicherung empfohlen.
Proxmox Host Firewall
WARNUNG Proxmox Host hat keine iptables-Regeln
Die INPUT-Chain auf dem Proxmox Host hat die Default-Policy ACCEPT ohne Regeln. Der Host verlässt sich komplett auf die Hetzner-Netzwerk-Konfiguration. Empfohlen: Proxmox Firewall (pve-firewall) aktivieren.
4. SSH & Zugangskontrolle
| Parameter | Wert | Bewertung |
| ListenAddress | 10.10.10.10 (nur VPN) | HERVORRAGEND |
| PasswordAuthentication | no | OK |
| Shell-Benutzer | Nur root und sync | OK |
| Fail2ban (SSH) | Aktiv, 0 Bans (keine Angriffe möglich über VPN) | OK |
HERVORRAGEND SSH-Konfiguration
SSH ist ausschliesslich über die VPN-IP 10.10.10.10 erreichbar. Passwort-Login ist deaktiviert. Dies ist eine der besten Absicherungen — SSH-Brute-Force-Angriffe sind physisch unmöglich, da der Port nicht öffentlich erreichbar ist.
WARNUNG Nur Root-Zugang vorhanden
Es gibt keinen separaten Admin-Benutzer. Best Practice wäre ein dedizierter User mit sudo-Rechten und deaktiviertem PermitRootLogin. Da SSH nur über VPN erreichbar ist, ist das Risiko jedoch gering.
5. Docker & Container Security
Container-Übersicht (20 aktiv)
| Container | Image | Alter | Status |
| traefik | traefik:v2.11 | 5 Wochen | OK |
| authelia | authelia:4.38 | 13 Monate! | VERALTET |
| n8n | n8nio/n8n:latest | 5 Wochen | OK |
| portainer | portainer-ce:latest | 3 Wochen | OK |
| open-webui | open-webui:main | 2 Monate | UPDATE |
| flowise | flowise:latest | 6 Wochen | OK |
| neo4j | neo4j:5.26-community | 6 Wochen | OK |
| lightrag | lightrag:latest | 2 Monate | UPDATE |
| crawl4ai | crawl4ai:all-amd64 | 15 Monate! | VERALTET |
| qdrant | qdrant:latest | 3 Monate | UPDATE |
| 5× postgres | postgres:16-alpine / pgvector:pg16 | 5–7 Wochen | OK |
| morovision-web | nginx:alpine (custom) | Aktuell | OK |
KRITISCH Authelia 4.38 ist 13 Monate alt
Authelia ist dein zentraler Authentifizierungsdienst. Version 4.38 kann bekannte Sicherheitslücken enthalten. Die aktuelle Version ist 4.39.x. Ein Update ist dringend empfohlen — gerade weil Authelia den Zugang zu sensiblen Diensten schützt.
WARNUNG crawl4ai ist 15 Monate alt
Das Image unclecode/crawl4ai:all-amd64 ist stark veraltet. Falls nicht aktiv genutzt, sollte der Container entfernt werden.
Docker Socket Exposition
WARNUNG Docker Socket an Traefik & Portainer gemountet
Beide Container haben Zugriff auf /var/run/docker.sock (read-only bei Traefik). Ein kompromittierter Container mit Docker-Socket-Zugriff kann den gesamten Host übernehmen. Portainer hat vollen Zugriff. Empfehlung: Portainer nur über VPN erreichbar machen.
Datenbank-Isolation
OK Keine Datenbanken auf Host-Ports exponiert
Alle 5 PostgreSQL-Container und Neo4j sind nur innerhalb des Docker-Netzwerks erreichbar. Kein Port wird an 0.0.0.0 gebunden — vorbildlich.
6. Traefik Reverse Proxy & TLS
| Konfiguration | Wert | Bewertung |
| HTTP → HTTPS Redirect | Aktiv (global via entryPoint) | OK |
| TLS/SSL | Let's Encrypt (ACME httpChallenge) | OK |
| acme.json Permissions | -rw------- (600) | OK |
| exposedByDefault | false | OK |
| Traefik Dashboard | Basic Auth geschützt | OK |
| HSTS Header | Aktiv (31536000s, includeSubdomains, preload) | OK |
OK Traefik-Konfiguration ist solide
exposedByDefault: false — Container müssen explizit aktiviert werden
- HSTS mit Preload aktiviert
- Dashboard mit BasicAuth geschützt
- ACME-Zertifikatsdatei korrekt geschützt (chmod 600)
Alle öffentlich erreichbaren Subdomains
| Subdomain | Dienst | Auth | Bewertung |
| morovision.ch | Website (nginx) | Öffentlich (korrekt) | OK |
| auth.morovision.ch | Authelia | Login-Portal | OK |
| n8n.ai.morovision.ch | n8n Automation | Authelia 2FA | OK |
| dashboard.ai.morovision.ch | MV Dashboard | Authelia + secure-headers | OK |
| insights.morovision.ch | MV Insights | Authelia 2FA | OK |
| track.morovision.ch | Insights Track | Authelia 2FA | OK |
| flowise.ai.morovision.ch | Flowise AI | Authelia 2FA | OK |
| traefik.ai.morovision.ch | Traefik Dashboard | BasicAuth | OK |
| portainer.ai.morovision.ch | Portainer | KEINE Middleware! | KRITISCH |
| chat.ai.morovision.ch | Open WebUI | KEINE Middleware! | KRITISCH |
| lightrag.ai.morovision.ch | LightRAG API | KEINE Middleware! | KRITISCH |
| neo4j.ai.morovision.ch | Neo4j Browser | KEINE Middleware! | KRITISCH |
| lounger.morovision.ch | Lounger App | Keine Middleware | PRÜFEN |
KRITISCH 4 sensible Services ohne Authentifizierung öffentlich erreichbar
Die folgenden Dienste sind über das Internet erreichbar ohne jegliche Authentifizierungs-Middleware:
- Portainer — Docker-Management-UI mit vollem Container-Zugriff. Hat eigenes Login, aber sollte zusätzlich mit Authelia oder
vpn-only Middleware geschützt sein.
- Open WebUI (chat.ai.morovision.ch) — KI-Chat-Interface. Hat eigenes Login, aber API-Endpoints könnten ungeschützt sein.
- LightRAG (lightrag.ai.morovision.ch) — RAG-API mit Zugriff auf Wissensdatenbank. API vermutlich komplett offen.
- Neo4j (neo4j.ai.morovision.ch) — Graph-Datenbank-Browser mit Zugriff auf alle Daten.
Empfehlung: Mindestens authelia oder besser vpn-only Middleware auf alle diese Router setzen.
7. Authentifizierung & Autorisierung
Authelia-Konfiguration
| Parameter | Wert | Bewertung |
| Default Policy | deny | HERVORRAGEND |
| TOTP (2FA) | Aktiviert (SHA1, 6-digit, 30s) | OK |
| WebAuthn | Deaktiviert | INFO |
| Password Policy | zxcvbn min_score 3 | OK |
| Password Hashing | Argon2id (3 iter, 64MB, 4 parallel) | OK |
| Backend | File-based (users_database.yml) | OK (single user) |
OK Authelia ist gut konfiguriert
Default-Policy deny, 2FA mit TOTP, starkes Password-Hashing (Argon2id) und eine gute Passwort-Policy. Die geschützten Dienste (n8n, Insights, Track, Flowise, Dashboard) erfordern alle 2FA.
Authentifizierungs-Matrix
| Dienst | Schutzschicht 1 | Schutzschicht 2 | Schutzschicht 3 |
| n8n | Authelia 2FA | n8n eigenes Login | — |
| Dashboard | Authelia | secure-headers | — |
| Insights / Track | Authelia 2FA | App-Login | — |
| Flowise | Authelia 2FA | — | — |
| Traefik Dashboard | BasicAuth (usersfile) | — | — |
| Portainer | Portainer Login | Keine Middleware | — |
| Open WebUI | WebUI Login | Keine Middleware | — |
| LightRAG | OFFEN | — | — |
| Neo4j | Neo4j Login | Keine Middleware | — |
8. Datensicherheit & Secrets
Environment-Dateien
| Datei | Permissions | Bewertung |
| /opt/localAIagent/.env | -rw------- (600) | OK |
| /opt/localAIagent/lightrag/.env | -rw-r--r-- (644) | WARNUNG |
| /opt/localAIagent/mv-insights/.env | -rw-r--r-- (644) | WARNUNG |
WARNUNG Zwei .env-Dateien sind world-readable
lightrag/.env und mv-insights/.env haben Permissions 644 (alle können lesen). Diese Dateien enthalten wahrscheinlich API-Keys und Datenbank-Passwörter. Fix: chmod 600 auf beide Dateien.
Authelia Secrets
OK Secrets-Verzeichnis korrekt eingebunden
Authelia Secrets sind als :ro (read-only) Volume gemountet.
9. Monitoring & Intrusion Detection
CrowdSec
| Metrik | Wert |
| Status | Aktiv |
| Firewall Bouncer | cs-firewall-bouncer v0.0.34, letzte Abfrage: 23.03.2026 10:15 |
| Community Blocklist | 4'820 aktive Bans |
| Traefik-Logs analysiert | 65'180 Zeilen |
| HTTP Bruteforce geblockt | 1'377 IPs (via CAPI) |
| Crawler geblockt | 144 IPs |
| Scanner geblockt | 43 IPs |
OK CrowdSec ist aktiv und funktioniert
CrowdSec analysiert die Traefik Access-Logs und die System-Logs. Der Firewall-Bouncer ist verbunden und die Community Blocklist ist aktiv. Das System profitiert von der kollektiven Intelligenz des CrowdSec-Netzwerks.
Fail2ban
OK Fail2ban aktiv für SSH
Läuft seit dem 18.03.2026. Da SSH nur über VPN erreichbar ist, wurden logischerweise 0 Bans registriert. Fail2ban dient hier als zusätzliche Sicherheitsschicht.
Automatische Updates
OK Unattended-Upgrades aktiv
Sicherheitsupdates werden automatisch installiert. Letzte Updates: 19.03.2026 (snapd, libssh).
10. Backup & Recovery
| Aspekt | Details | Bewertung |
| Backup-Script | weekly-backup.sh | OK |
| Zeitplan | Sonntags 03:00 Uhr (Crontab) | OK |
| Ziel | Hetzner Storage Box (u545392) | OK |
| Retention | 4 Wochen | OK |
| Umfang | PostgreSQL-Dumps, Configs, Docker Volumes | OK |
| Recovery-Test | Unbekannt | PRÜFEN |
OK Professionelles Backup-System
Wöchentliches Backup auf externe Hetzner Storage Box mit 4 Wochen Retention. Das Script sichert Datenbanken, Konfigurationen und Docker Volumes. Der Ansatz ist solide.
EMPFEHLUNG Recovery-Test durchführen
Es empfiehlt sich, einen Restore-Test durchzuführen, um sicherzustellen, dass die Backups tatsächlich wiederhergestellt werden können. Mindestens einmal pro Quartal.
11. Web Application Security (morovision.ch)
Security Headers
| Header | Wert | Bewertung |
| X-Frame-Options | SAMEORIGIN | OK |
| X-Content-Type-Options | nosniff | OK |
| X-XSS-Protection | 1; mode=block | OK |
| Referrer-Policy | strict-origin-when-cross-origin | OK |
| Permissions-Policy | camera=(), microphone=(), geolocation=() | OK |
| Content-Security-Policy | Restriktiv konfiguriert | PROBLEM |
| HSTS (via Traefik) | max-age=31536000; includeSubDomains; preload | OK |
WARNUNG CSP blockiert Google Tag Manager & SalesViewer
Die aktuelle Content-Security-Policy erlaubt nur script-src 'self' 'unsafe-inline'. Das blockiert:
- Google Tag Manager (GTM-KHHB23XH) — benötigt
https://www.googletagmanager.com
- SalesViewer — benötigt
https://*.salesviewer.com
- Google Analytics (via GTM) — benötigt
https://www.google-analytics.com
Die CSP muss erweitert werden, damit GTM und SalesViewer funktionieren.
Nginx-Konfiguration
OK Gute Grundkonfiguration
- Gzip-Kompression aktiv
- Static-Asset-Caching (30 Tage)
- HTML-Caching (1 Stunde, must-revalidate)
- Clean URLs (kein .html nötig)
- Nginx läuft als non-root User
HINWEIS Custom Error Pages zeigen index.html
404- und 500-Fehler werden auf index.html umgeleitet. Für eine Multi-Page-Site wäre eine dedizierte 404-Seite besser für die User Experience.
13. Empfohlene Massnahmen
Sofort (heute)
1. Authelia-Middleware auf ungeschützte Services setzen
In /opt/localAIagent/docker-compose.yml folgende Router um Middleware ergänzen:
# Portainer — VPN-only empfohlen (hat Docker Socket Zugang!)
- "traefik.http.routers.portainer.middlewares=vpn-only@file"
# Open WebUI
- "traefik.http.routers.openwebui.middlewares=authelia@file"
# LightRAG — hat vermutlich keine eigene Auth
- "traefik.http.routers.lightrag.middlewares=authelia@file"
# Neo4j
- "traefik.http.routers.neo4j.middlewares=vpn-only@file"
Danach: cd /opt/localAIagent && docker compose up -d
2. .env-Dateien absichern
chmod 600 /opt/localAIagent/lightrag/.env
chmod 600 /opt/localAIagent/mv-insights/.env
3. CSP für GTM & SalesViewer erweitern
In nginx.conf die Content-Security-Policy anpassen:
add_header Content-Security-Policy "default-src 'self';
script-src 'self' 'unsafe-inline' https://www.googletagmanager.com
https://*.salesviewer.com https://www.google-analytics.com;
style-src 'self' 'unsafe-inline' https://fonts.googleapis.com;
font-src https://fonts.gstatic.com;
img-src 'self' data: https://cdn.simpleicons.org
https://www.googletagmanager.com https://www.google-analytics.com;
connect-src 'self' https://n8n.ai.morovision.ch
https://www.google-analytics.com https://*.salesviewer.com;
frame-src https://www.googletagmanager.com;" always;
Diese Woche
4. Authelia auf 4.39.x updaten
# In docker-compose.yml ändern:
image: authelia/authelia:4.39
# Dann:
docker compose pull authelia
docker compose up -d authelia
⚠️ Vorher Release Notes prüfen — es könnte Breaking Changes geben.
5. crawl4ai updaten oder entfernen
# Falls nicht mehr benötigt:
docker compose stop crawl4ai && docker compose rm crawl4ai
# Falls benötigt — auf neuere Version updaten
6. Swap-Datei einrichten (Schutz gegen OOM)
fallocate -l 4G /swapfile
chmod 600 /swapfile
mkswap /swapfile
swapon /swapfile
echo '/swapfile none swap sw 0 0' >> /etc/fstab
Diesen Monat
7. Proxmox Firewall aktivieren
Im Proxmox Web-UI unter Datacenter → Firewall → Options: «Firewall» aktivieren und Regeln für SSH (nur VPN-Netz), WireGuard (UDP 51820) und HTTP/HTTPS (80/443) erstellen.
8. Recovery-Test durchführen
Einen Restore der letzten Backup-Daten auf einer separaten VM oder lokal testen, um sicherzustellen, dass die Wiederherstellung funktioniert.
Fazit
Gesamtbewertung: B+ (Gut mit Verbesserungspotenzial)
Die Infrastruktur ist grundsätzlich professionell aufgebaut. Die Architektur mit VPN, Traefik, Authelia 2FA und CrowdSec bietet eine solide Sicherheitsbasis. Das grösste Risiko sind die 4 öffentlich erreichbaren Dienste ohne Authentifizierungs-Middleware — insbesondere Portainer (Docker-Management) und LightRAG (vermutlich offene API). Diese Findings lassen sich in unter 30 Minuten beheben und würden die Bewertung auf A− heben.