Jeg har nu omlagt backuppen af min NixOS-hjemmeserver og er skiftet fra et simpelt dagligt script til backup hver time. Ikke helt så elegant som på den Mastodon-instans, som min ven administrerer – her har vi et ZFS-snapshot hvert 20. minut – men jeg er også tilfreds med denne løsning. Og jeg må sige, at jeg synes bedre og bedre om NixOS. Uden AI ville det dog være alt for kompliceret til, at jeg kunne forstå det, men efterhånden kan jeg i det mindste læse de færdige Nix-filer. Jeg har overvejet at skifte serveren til en almindelig Linux, men så længe det fungerer så godt...
-
/etc/nixos: Hele NixOS-konfigurationen (alle .nix-filer).
-
/opt/minecraft: Alle verdener og data fra Minecraft-serveren.
-
/opt/satisfactory: Gemte spil og konfiguration af Satisfactory-serveren.
-
/opt/Blog: Kildekoden og indholdet af bloggen.
-
/opt/ui: Mastodon-UI-filerne.
-
/opt/audiobookshelf: Lydbøgerne og den tilhørende database.
Det hele ender på et S3-lager, der er monteret via RClone.
NixOS-konfigurationen
{ config, pkgs, ... }:
{
# BorgBackup-konfiguration
services.borgbackup.jobs.hourly = {
# Sti til repository i S3-mountet
repo = "/opt/S3/Backup/NixOSHomeServer_Borg";
# Intet kodeord påkrævet
encryption.mode = "none";
# Komprimering for endnu mere pladsbesparelse
compression = "auto,zstd";
# Stierne der skal sikkerhedskopieres
paths = [
"/etc/nixos"
"/opt/minecraft"
"/opt/satisfactory"
"/opt/Blog"
"/opt/ui"
"/opt/audiobookshelf"
];
# Udførelse hver time
startAt = "hourly";
# Initialiser automatisk repository, hvis det mangler
doInit = true;
# Opbevaringsregler (Pruning)
prune.keep = {
within = "1d"; # Alle snapshots fra de sidste 24 timer
daily = 7;
weekly = 4;
monthly = 12;
};
};
# Sørg for, at S3-mountet er klar, før Borg starter
systemd.services.borgbackup-job-hourly = {
requires = [ "rclone-s3-mount.service" ];
after = [ "rclone-s3-mount.service" ];
};
}
Oprindeligt var mit blog-setup planlagt som et rent IPv6-projekt via WireGuard, da det hele kører på en homeserver (man kan i øvrigt få gratis IPv6-adresser hos route64.org). For at øge tilgængeligheden har jeg nu tilføjet en ekstern IPv4-proxy (tak til @Larvitz).
I den forbindelse opstod der dog straks SSL-problemer: Da både A- og AAAA-recorden oprindeligt kørte via proxyen, fejlede Let's Encrypt-valideringen på min server.
Løsningen: „IPv6-hacket“
Løsningen var eksplicit at pege AAAA-posten direkte mod min servers WireGuard-IP i stedet for også at lede den gennem proxyen.
- Domæne:
blog.burningboard.org
- A-record (Proxy):
194.28.98.217
- AAAA-record (Server):
2a11:6c7:f05:a8::2 (WireGuard)
Gennem denne direkte AAAA-post til min WireGuard-IP kan Let’s Encrypt fortsat nå min server direkte via IPv6 (da AAAA-recorden som standard prioriteres) og udstede SSL-certifikatet. IPv4-trafikken videresendes krypteret fra proxyen til mig.
Den endelige konfiguration
For at kommunikationen skal fungere problemfrit, var vi nødt til at tilpasse Caddy-serverne:
1. På min server (NixOS, blog.nix)
For at de rigtige besøgs-IP'er ankommer korrekt og ikke bliver overskrevet af proxyens IP, skal denne markeres som betroet:
services.caddy.globalConfig = ''
servers {
trusted_proxies static 2a06:9801:1c:1000::10
}
'';
2. På den eksterne proxy (Caddy)
For at proxyen kan kontakte min server korrekt via HTTPS, skal den sende værtsnavnet (SNI) med:
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
}
}
Bloggen er nu tilgængelig via både IPv4 og IPv6, sikkert krypteret, og min hjemme-IP forbliver stadig privat! 🚀
Det vigtigste først: De vante Markdown-filer forbliver fundamentet – jeg er bare stor fan af denne ukomplicerede løsning. Men under motorhjelmen er der sket meget:
Jeg har skruet en del på setuppet:
📂 MD-filer: Blogstrukturen forbliver simpel på Markdown-basis.
🌍 Mere global end nogensinde: Min blog understøtter nu oversættelser til 43 sprog. Ja, inklusive klingonsk! 🖖 (Qapla'!)

Planen var en fuldautomatisk realtidsoversættelse baseret på browserens sproggenkendelse. Spoiler: Det virkede kun delvist. Man mærker det: AI er imponerende, men endnu ikke helt "der", hvor vi gerne vil have den.
Løsningen: Jeg oversætter nu blot hvert indlæg på forhånd til alle de fastlagte sprog, hvilket også er betydeligt bedre for søgemaskinerne (SEO). Hvis den automatiske genkendelse svigter, kan I manuelt vælge jeres foretrukne sprog via globus-ikonet, som derefter gemmes helt ukompliceret via en cookie.
Oversættelserne udføres nu med Gemini 3 Flash, hvilket giver overraskende gode resultater. Man bør dog holde et vågent øje med AI'en: I den første bulk-kørsel blev tagsene fejlagtigt også oversat, hvilket naturligvis ikke var planlagt.
Koden er stadig tilgængelig (skriv bare en besked til mig, hvis du er interesseret) 👍 Vær dog opmærksom på, at systemet nu kræver sin egen Gemini API-nøgle 🔑.
Jeg har for nylig skiftet min blog fra WriteFreely til en egenudviklet løsning: MD-Blog (MD står naturligvis for Markdown). Anledningen var en mislykket opdatering af det gamle system – men i sidste ende var det det perfekte skub til at forenkle alt radikalt og få fuld kontrol over designet.
Kernen i det hele er simple Markdown-filer i data/-mappen, som bliver omdannet til moderne HTML i realtid. Resultatet er lynhurtigt, fungerer uden en database og ser nu præcis ud, som jeg havde forestillet mig, takket være mit eget designsystem (inklusive Dark Mode). Der er endda en moderne Mastodon-delingsknap med ombord nu.
Hvis I er interesserede i koden eller det enkle setup, er I velkomne til at kontakte mig på Mastodon!
Egentlig er idéen bag #Winboat fremragende, men implementeringen virker i øjeblikket stadig en smule ustabil. Siden installationen i starten af året kørte systemet ganske vist, men i dag nægtede softwaren fuldstændig at fungere.
Imaget meldte pludselig om utilstrækkelig arbejdshukommelse (RAM). Jeg forsøgte stadig at løse problemet manuelt, hvilket desværre gjorde systemet definitivt ubrugeligt. I stedet for at investere mere tid i fejlfinding, skiftede jeg direkte til Dockurr Windows-imaget – dette udgør alligevel det tekniske grundlag for Winboat.

1. Forberedelse
Da jeg bruger Podman, oprettede jeg først de nødvendige mapper på mit host-system. På den måde bevares dataintegriteten, hvis containeren skal genoprettes:
mkdir -p $HOME/Windows/System
mkdir -p $HOME/Windows/Shared
2. Startkommandoen
Vigtig bemærkning: Erstat pladsholderne i variablerne -e USERNAME og -e PASSWORD med dine personlige loginoplysninger.
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
Så snart containeren er aktiv, kan du tilgå Windows-instansen direkte via din browser:
http://127.0.0.1:8006

3. Opsummering
Jeg behøvede kun at køre ovenstående kommando én gang. I den daglige drift kan Windows-miljøet nu styres ganske komfortabelt via disse genvejskommandoer:
- Start:
podman start windows
- Stop:
podman stop windows (eller luk ned direkte inde i Windows)
- Tjek status:
podman ps -a
Yderligere links:
Jeg har installeret min egen blog — primært for at lære #NixOS bedre at kende. Overraskende nok gik det hele ret ukompliceret.
WriteFreely passer rigtig godt til det: minimalistisk, hurtigt opsat og uden for meget fyld. Perfekt til bare at komme i gang og lære noget undervejs. Konfigurationen er behageligt overskuelig. Et par indstillinger sat, mappe forberedt, reverse proxy foran — færdig.
Sådan ser min nuværende NixOS-konfiguration ud:
{ 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 til generering af ActivityPub-nøgler: Føderation kræver openssl
systemd.services.writefreely.path = [ pkgs.openssl ];
# Automatisk oprettelse af datamappen med de korrekte rettigheder
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}
}
'';
}
Det var i det væsentlige det. NixOS gør det virkelig nemt at konfigurere sådanne tjenester rent og holde dem reproducerbare.