Ich habe jetzt mal das Backup meines NixOS Homeservers umgestellt und statt einem einfachen täglichen Script auf stündlich umgestellt. Nicht ganz so elegant wie auf der Mastodon Instanz, die mein Freund verwaltet – hier haben wir alle 20 Minuten einen ZFS Snapshot – aber mit der Lösung bin ich auch zufrieden. Und ich muss sagen NixOS gefällt mir immer besser. Ohne KI wäre es allerdings viel zu kompliziert, als dass ich es verstehen könnte, aber mittlerweile kann ich die fertigen Nix-Dateien zumindest lesen. Hatte mal überlegt den Server auf ein normales Linux umzustellen, aber solange das so gut funktioniert...
-
/etc/nixos: Die gesamte NixOS-Konfiguration (alle .nix Dateien).
-
/opt/minecraft: Alle Welten und Daten des Minecraft-Servers.
-
/opt/satisfactory: Spielstände und Konfiguration des Satisfactory-Servers.
-
/opt/Blog: Der Quellcode und die Inhalte des Blogs.
-
/opt/ui: Die Mastodon-UI Dateien.
-
/opt/audiobookshelf: Die Hörbücher und die zugehörige Datenbank.
Das ganze landet auf einem S3 Storage der via RClone gemoundet wurde.
Die NixOS Konfiguration
{ config, pkgs, ... }:
{
# BorgBackup Konfiguration
services.borgbackup.jobs.hourly = {
# Pfad zum Repository im S3-Mount
repo = "/opt/S3/Backup/NixOSHomeServer_Borg";
# Kein Passwort erforderlich
encryption.mode = "none";
# Kompression für noch mehr Platzersparnis
compression = "auto,zstd";
# Die zu sichernden Pfade
paths = [
"/etc/nixos"
"/opt/minecraft"
"/opt/satisfactory"
"/opt/Blog"
"/opt/ui"
"/opt/audiobookshelf"
];
# Stündliche Ausführung
startAt = "hourly";
# Repository automatisch initialisieren, falls es fehlt
doInit = true;
# Aufbewahrungsregeln (Pruning)
prune.keep = {
within = "1d"; # Alle Snapshots der letzten 24h
daily = 7;
weekly = 4;
monthly = 12;
};
};
# Sicherstellen, dass der S3-Mount bereit ist, bevor Borg startet
systemd.services.borgbackup-job-hourly = {
requires = [ "rclone-s3-mount.service" ];
after = [ "rclone-s3-mount.service" ];
};
}
Ursprünglich war mein Blog-Setup als reines IPv6-Projekt über WireGuard geplant, da das Ganze auf einem Homeserver betrieben wird (kostenlose IPv6-Adressen bekommt man übrigens bei route64.org). Um die Erreichbarkeit zu erhöhen, habe ich nun einen externen IPv4-Proxy dazugeholt (Danke @Larvitz).
Dabei gab es jedoch sofort SSL-Probleme: Da ursprünglich sowohl der A wie auch der AAAA Record über den Proxy liefen, schlug die Let's Encrypt-Validierung auf meinem Server fehl.
Die Lösung: Der „IPv6-Hack“
Die Lösung war, den AAAA-Eintrag explizit direkt auf die WireGuard-IP meines Servers zu richten, anstatt ihn ebenfalls über den Proxy zu leiten.
- Domain:
blog.burningboard.org
- A-Record (Proxy):
194.28.98.217
- AAAA-Record (Server):
2a11:6c7:f05:a8::2 (WireGuard)
Durch diesen direkten AAAA-Eintrag auf meine WireGuard-IP erreicht Let’s Encrypt meinen Server weiterhin direkt via IPv6 (da der AAAA-Record standardmäßig priorisiert wird) und stellt das SSL-Zertifikat aus. Der IPv4-Traffic wird vom Proxy verschlüsselt an mich weitergereicht.
Die finale Konfiguration
Damit die Kommunikation reibungslos klappt, mussten wir die Caddy-Server anpassen:
1. Auf meinem Server (NixOS, blog.nix)
Damit die echten Besucher-IPs korrekt ankommen und nicht durch die IP des Proxys überschrieben werden, muss dieser als vertrauenswürdig markiert werden:
services.caddy.globalConfig = ''
servers {
trusted_proxies static 2a06:9801:1c:1000::10
}
'';
2. Auf dem externen Proxy (Caddy)
Damit der Proxy meinen Server korrekt per HTTPS anspricht, muss er den Hostnamen (SNI) mitschicken:
reverse_proxy [https://[2a11:6c7:f05:a8::2]:443](https://[2a11:6c7:f05:a8::2]:443) {
header_up Host {host}
transport http {
tls_server_name blog.burningboard.org
}
}
Der Blog ist jetzt über IPv4 und IPv6 erreichbar, sicher verschlüsselt und meine Heim-IP bleibt trotzdem privat! 🚀
Das Wichtigste vorab: Die gewohnten Markdown-Dateien bleiben die Basis – ich bin einfach ein großer Fan dieser unkomplizierten Lösung. Aber unter der Haube hat sich viel getan:
Ich habe einiges am Setup geschraubt:
📂 MD-Files: Die Blog-Struktur bleibt simpel auf Markdown-Basis.
🌍 Globaler als je zuvor: Mein Blog unterstützt jetzt Übersetzungen in 43 Sprachen. Ja, inklusive Klingonisch! 🖖 (Qapla'!)

Geplant war eine vollautomatische Echtzeit-Übersetzung basierend auf der Browser-Spracherkennung. Spoiler: Es hat nur teilweise funktioniert. Man merkt: Die KI ist beeindruckend, aber noch nicht ganz "da", wo wir sie gerne hätten.
Die Lösung: Ich übersetze jetzt einfach jeden Beitrag vorab in alle festgelegten Sprachen, was auch deutlich besser für die Suchmaschinen (SEO) ist. Falls die automatische Erkennung mal nicht greift, könnt ihr über das Weltkugel-Icon eure bevorzugte Sprache manuell festlegen, die dann ganz unkompliziert via Cookie gespeichert wird.
Die Übersetzungen werden nun mit Gemini 3 Flash durchgeführt, was erstaunlich gute Ergebnisse liefert. Allerdings sollte man der KI genau auf die Finger schauen: Im ersten Bulk-Durchgang wurden fälschlicherweise auch die Tags mitübersetzt, was so natürlich nicht geplant war.
Der Code ist weiterhin verfügbar (schreibt mir bei Interesse einfach eine Nachricht) 👍 Beachtet aber, dass das System jetzt einen eigenen Gemini API Key 🔑 benötigt.
Ich habe kurzerhand meinen Blog von WriteFreely auf eine Eigenentwicklung umgestellt: MD-Blog (das MD steht natürlich für Markdown). Der Auslöser war ein fehlgeschlagenes Update des alten Systems – am Ende war es aber der perfekte Anstoß, um alles radikal zu vereinfachen und die volle Kontrolle über das Design zu gewinnen.
Das Herzstück sind einfache Markdown-Dateien im data/-Ordner, die zur Laufzeit in modernes HTML umgewandelt werden. Das Ergebnis ist blitzschnell, kommt ohne Datenbank aus und sieht dank eigenem Design-System (inklusive Dark Mode) jetzt genau so aus, wie ich es mir vorgestellt habe. Sogar ein moderner Mastodon-Share-Button ist jetzt direkt mit an Bord.
Falls ihr Interesse am Code oder dem schlanken Setup habt, meldet euch gerne über Mastodon bei mir!
Eigentlich ist die Idee hinter #Winboat hervorragend, doch die Umsetzung scheint aktuell noch etwas instabil zu sein. Seit der Installation Anfang des Jahres lief das System zwar, doch heute hat die Software komplett den Dienst verweigert.
Das Image meldete plötzlich unzureichenden Arbeitsspeicher (RAM). Ich habe noch versucht, das Problem manuell zu beheben, was das System jedoch leider endgültig unbrauchbar gemacht hat. Anstatt weitere Zeit in die Fehlersuche zu investieren, bin ich direkt auf das Dockurr Windows-Image umgestiegen – dieses bildet ohnehin die technische Basis von Winboat.

1. Vorbereitung
Da ich Podman verwende, habe ich zunächst die erforderlichen Verzeichnisse auf meinem Host-System erstellt. So bleibt die Datenintegrität gewahrt, falls der Container neu erstellt werden muss:
mkdir -p $HOME/Windows/System
mkdir -p $HOME/Windows/Shared
2. Der Startbefehl
Wichtiger Hinweis: Ersetze in den Variablen -e USERNAME und -e PASSWORD die Platzhalter durch deine persönlichen Zugangsdaten.
podman run -d \
--name windows \
-p 8006:8006 \
--device=/dev/kvm \
--cap-add NET_ADMIN \
-e RAM_SIZE="8G" \
-e USERNAME="Carsten" \
-e PASSWORD="1234" \
-e LANGUAGE="German" \
-v $HOME/Windows/System:/storage:Z \
-v $HOME/Windows/Shared:/shared:Z \
--stop-timeout 120 \
dockurr/windows
Sobald der Container aktiv ist, kannst du die Windows-Instanz direkt über deinen Browser aufrufen:
http://127.0.0.1:8006

3. Zusammenfassung
Den oben genannten Befehl musste ich lediglich einmal ausführen. Im täglichen Betrieb lässt sich die Windows-Umgebung nun ganz komfortabel über diese Kurzbefehle steuern:
- Starten:
podman start windows
- Stoppen:
podman stop windows (oder direkt innerhalb von Windows herunterfahren)
- Status prüfen:
podman ps -a
Weiterführende Links:
Ich habe mir einen eigenen Blog installiert — vor allem, um #NixOS besser kennenzulernen. Überraschenderweise ging das alles ziemlich unkompliziert.
WriteFreely passt dafür richtig gut: minimalistisch, schnell eingerichtet und ohne viel Ballast. Perfekt, um einfach loszulegen und nebenbei etwas zu lernen. Die Konfiguration ist angenehm übersichtlich. Ein paar Optionen gesetzt, Verzeichnis vorbereitet, Reverse Proxy davor — fertig.
So sieht meine aktuelle NixOS-Konfiguration dafür aus:
{ config, pkgs, ... }:
{
services.writefreely = {
enable = true;
host = "blog.burningboard.org";
settings = {
server = {
port = 8080;
min_log_level = "debug";
};
app = {
host = "https://blog.burningboard.org";
single_user = true;
landing = "/read";
wf_modesty = true;
federation = true;
public_stats = true;
theme = "write";
};
};
stateDir = "/opt/writefreely";
};
# Fix für die ActivityPub-Schlüsselgenerierung: Föderation erfordert openssl
systemd.services.writefreely.path = [ pkgs.openssl ];
# Automatisches Erstellen des Datenverzeichnisses mit den korrekten Berechtigungen
systemd.tmpfiles.rules = [
"d /opt/writefreely 0700 writefreely writefreely -"
];
services.caddy.virtualHosts."blog.burningboard.org".extraConfig = ''
reverse_proxy 127.0.0.1:8080 {
header_up Host {host}
header_up X-Real-IP {remote_host}
header_up X-Forwarded-For {remote_host}
header_up X-Forwarded-Proto {scheme}
}
'';
}
Das war's schon im Wesentlichen. NixOS macht es wirklich einfach, solche Dienste sauber zu konfigurieren und reproduzierbar zu halten.