
Waldemar Schneider
IT-Systemintegrator, der sowohl die Produktionshalle als auch den Serverraum versteht.
© 2026 Waldemar Schneider
Portfolio

Portfolio-Website ws-informatik.ch
Inhalt
Projektübersicht
Eine persönliche Portfolio-Website wurde von Grund auf geplant, entwickelt und auf eigener Infrastruktur betrieben. Das Projekt umfasst lokale Entwicklung mit Flask, Deployment auf einem Proxmox-LXC, öffentliche Erreichbarkeit über einen Cloudflare Tunnel sowie eine professionelle E-Mail-Adresse mit vollständiger DNS-Absicherung.
1. Situation (Ausgangslage)
Ein klassischer PDF-Lebenslauf zeigt Stationen, aber keine praktische Arbeitsweise. Zertifikate allein sagen wenig über tatsächliche Erfahrung mit realen Systemen aus. Gesucht war eine Plattform, die Berufserfahrung und Projekte umfangreicher und nachvollziehbarer darstellt als es ein Lebenslauf erlaubt, gleichzeitig selbst als Kompetenznachweis dient und langfristig erweiterbar bleibt.
2. Task (Zielsetzung)
- Lokale Entwicklungsumgebung: Flask-basierte Website auf dem Laptop aufsetzen, anpassen und versionieren.
- Server-Deployment: Die Applikation produktionsreif auf einem LXC-Container (Proxmox) betreiben - mit Nginx, Gunicorn und SSH-Absicherung.
- Öffentlicher Launch: Die Website über eine eigene Schweizer Domain erreichbar machen, ohne eingehende Ports zu öffnen.
- Professionelle E-Mail: Eine eigene Adresse unter der Domain einrichten, vollständig mit SPF, DKIM und DMARC abgesichert.
- Dynamisches Projektsystem: Neue Projekte sollen allein durch Ablegen einer Markdown-Datei auf der Website erscheinen - kein HTML-Editieren nötig.
3. Action (Umsetzung)
A. Lokale Entwicklung und Anpassung
Als Basis wurde das Ovro Flask Template (Python 3.12, Flask 3.0, Bootstrap 5, Jinja2) gewählt. Flask wurde bewusst gegenüber schwereren Frameworks wie Django oder Laravel bevorzugt: minimaler Overhead, keine Build-Toolchain, und das Deployment auf einem Linux-Server ist direkt verständlich und erklärbar. Die lokale Umgebung nutzt eine Python-venv zur Paket-Isolation, eine .env-Datei für Konfiguration und Git mit einem selbst gehosteten Forgejo-Server als Remote.
Das Template wurde inhaltlich und strukturell umgebaut: sieben Sektionen (Hero, Über mich, Skills, Berufserfahrung, Lernprojekte, Portfolio, Kontakt), ein JavaScript-gesteuertes Popup-System für neun Detailansichten, Client-seitige Pagination für Portfolio-Kacheln sowie eigene Logo-Varianten für Dark- und Light-Mode. Impressum und Datenschutzerklärung wurden nach Schweizer DSG-Anforderungen erstellt.
B. Deployment auf Proxmox LXC
Für das Hosting wurde ein unprivilegierter Debian 12 LXC-Container auf dem Proxmox-Hypervisor angelegt. Der Web-Stack besteht aus Nginx als Reverse Proxy und Static-File-Server, Gunicorn als WSGI-Server zwischen Nginx und Flask, sowie systemd-Units für automatischen Start und einfache Verwaltung. DEBUG=False und ein zufällig generierter SECRET_KEY wurden in der serverseitigen .env gesetzt.
Die SSH-Absicherung folgt dem Principle of Least Privilege: ein dedizierter Deploy-User mit ED25519-Key-Authentifizierung, Passwort-Login deaktiviert, sudo-Rechte beschränkt auf exakt die benötigten Befehle (git pull, systemctl restart gunicorn, apt update/upgrade). Der Deploy-Workflow läuft über Forgejo: lokal entwickeln, committen, pushen, auf dem Server pullen und Gunicorn neustarten.
C. Domain, Cloudflare Tunnel und öffentlicher Launch
Die Domain ws-informatik.ch wurde bei einem Schweizer Registrar registriert. DNS-Management wurde auf Cloudflare umgestellt. Statt klassischer Port-Weiterleitung (Port 80/443 in der Firewall öffnen) wurde ein Cloudflare Tunnel eingesetzt: der cloudflared-Daemon im LXC baut eine ausgehende verschlüsselte Verbindung zu Cloudflare auf. Kein eingehender Port wird geöffnet, die Heimnetz-IP bleibt verborgen, HTTPS kommt automatisch über Cloudflares Universal SSL. Eine Redirect Rule leitet www dauerhaft auf die Root-Domain um.
D. Professionelle E-Mail
Uber Infomaniak (Schweizer Anbieter, Server in der Schweiz) wurde eine Mailbox unter der eigenen Domain eingerichtet. In Cloudflare DNS wurden MX-, SPF-, DKIM- und DMARC-Records gesetzt. DMARC wurde zunächst auf p=none (Beobachtungsmodus) konfiguriert, um den Mailfluss zu validieren, bevor eine restriktivere Policy gesetzt wird. Automatische Mailclient-Konfiguration wurde über CNAME-Records für autoconfig und autodiscover eingerichtet.
E. Dynamisches Projektsystem (Markdown-Rendering)
Im letzten Schritt wurde ein Markdown-Rendering-System in Flask integriert. Projektdokumentationen liegen als .md-Dateien mit YAML-Frontmatter in einem projects/-Ordner. Flask liest diese Dateien, wandelt den Inhalt mit python-markdown in HTML um und stellt jede Seite unter /projekt/<slug> bereit. Die Portfolio-Sektion auf der Startseite generiert ihre Kacheln dynamisch aus denselben Dateien: Titel, Teaser, Bild und Datum kommen aus dem Frontmatter, die Pagination wird automatisch berechnet. Ein neues Projekt hinzufügen bedeutet: Markdown-Datei in den Ordner legen, committen, deployen - fertig.
4. Result (Ergebnis & Verifikation)
Die Website ist unter https://ws-informatik.ch öffentlich erreichbar. Gunicorn und Nginx laufen als systemd-Dienste und starten automatisch nach einem Reboot. Der Cloudflare Tunnel ist aktiv und stabil, HTTPS funktioniert ohne eigenes Zertifikatsmanagement. Die E-Mail-Adresse ist voll funktionsfähig, SPF, DKIM und DMARC sind in Cloudflare DNS eingetragen und verifiziert. Das dynamische Projektsystem rendert Markdown-Dateien korrekt inklusive Inhaltsverzeichnis, Code-Blöcken und Tabellen. Neue Projekte erscheinen automatisch auf der Startseite, sobald eine .md-Datei mit Frontmatter im projects/-Ordner liegt.
Lessons Learned
- Flask in Production braucht Gunicorn: Der eingebaute Flask-Entwicklungsserver ist nicht für produktiven Betrieb geeignet. Gunicorn als WSGI-Server davor zu schalten ist der Standardweg, und das Konzept (Nginx leitet an Gunicorn weiter, Gunicorn spricht WSGI mit Flask) ist direkt auf viele andere Python-Webprojekte übertragbar.
- Cloudflare Tunnel als sichere Alternative zu Port-Forwarding: Der Tunnel ermöglicht öffentlichen HTTPS-Zugang ohne eingehende Firewall-Regeln. Das ist konzeptuell anders als ein klassisches VPN, aber für einzelne Web-Applikationen die praktischere Lösung.
- Principle of Least Privilege konsequent umsetzen: Ein dedizierter Deploy-User mit genau den nötigen sudo-Rechten reduziert den Schaden bei einem kompromittierten Account erheblich. Die sudoers-Konfiguration mit absoluten Pfaden ist dabei wichtig.
- Trennung von Inhalt und Darstellung zahlt sich aus: Das Markdown-Frontmatter-System macht neue Projekte zu einem reinen Redaktionsschritt ohne HTML-Kenntnisse. Dieselben
.md-Dateien lassen sich gleichzeitig in Obsidian als Dokumentation nutzen. - DNS-Änderungen brauchen Zeit und einen klaren Kopf: Die Kombination aus Registrar, Cloudflare DNS, MX-Records, SPF/DKIM/DMARC und Tunnel-Konfiguration hat viele Abhängigkeiten. Änderungen sequenziell durchführen und nach jeder Änderung warten und verifizieren spart Fehlersuche.