Meine deklarative Konfiguration für NixOS und macOS, aufgebaut mit Nix Flakes, Home Manager und nix-darwin. Das Repository enthält ein modulares System für Desktop, Gaming, Entwicklung und persistente Daten.
Das Repository dient als zentrale Definition meiner Linux- und macOS-Systeme. Systemkonfiguration, Benutzerumgebung, Anwendungen, Dotfiles und eigene Pakete werden möglichst vollständig über Nix verwaltet.
Der Desktop basiert auf meinem eigenen Wayland-Compositor splice (Smithay), der die Desktop-Shell selbst mitbringt.
NixOS läuft produktiv als Hauptsystem auf meinem Desktop und hat das frühere CachyOS-System vollständig ersetzt. Die Konfiguration ist im Alltag stabil und flüssig; aktuell gibt es nur vereinzelte Verbesserungen, die Weiterentwicklung läuft aktiv weiter. Die VM dient nur noch dazu, Änderungen vorab zu testen.
Der Desktop synchronisiert iCloud-Kalender alle fünf Minuten mit vdirsyncer.
khal stellt die Kalender-App bereit; Datum und Uhrzeit in der Bar
öffnen zusätzlich eine Monats- und Terminübersicht. Nach dem ersten Rebuild wird
das Konto einmalig eingerichtet:
splice-calendar-setupDer Befehl erwartet eine Apple-ID und ein app-spezifisches Passwort. Beide werden im GNOME-Keyring gespeichert und nicht in die Nix-Konfiguration geschrieben.
Das Setup verfolgt einige grundlegende Prinzipien:
- reproduzierbare und deklarative Systemkonfiguration
- möglichst wenig manuell verwalteter Systemzustand
- gemeinsame Module für VM und physische Hardware
- eigener minimalistischer Wayland-Desktop
- Gaming ohne unnötige Desktop-Abhängigkeiten
- kontrollierte Persistence statt dauerhaft veränderlichem Root-Dateisystem
- eigene Nix-Pakete für Software, die nicht passend in nixpkgs verfügbar ist
Die Flake stellt zwei NixOS-Konfigurationen und eine nix-darwin-Konfiguration bereit.
Meine produktive Workstation und das Hauptsystem.
Sie enthält neben der gemeinsamen Basis die für den realen Desktop benötigten Komponenten wie Gaming, Hardwareintegration und Desktop-Anwendungen.
Testsystem für die Entwicklung und Validierung der Konfiguration.
Die VM wird verwendet, um Änderungen an NixOS, Home Manager, splice und der Persistence zu testen, ohne das produktive Desktop-System zu beeinflussen.
nix-darwin-Konfiguration für den Apple-Silicon-Mac. Home Manager verwaltet dort die gemeinsame Entwicklungsumgebung und die macOS-spezifischen Anwendungen. NixOS verwendet Fish als Login-Shell; macOS bleibt bei der nativen Zsh unter /bin/zsh.
Home Manager kopiert Nix-Anwendungen zunächst nach ~/Applications/Home Manager Apps, damit Spotlight mit vollständigen App-Bundles arbeiten kann. Die nix-darwin-Aktivierung verlinkt diese Apps zusätzlich direkt nach /Applications, ohne dort vorhandene fremde Apps zu überschreiben. Der von nix-darwin erzeugte Ordner /Applications/Nix Apps wird entfernt, solange er leer ist.
Als Window-Manager läuft OmniWM (modules/features/omniwm.nix) mit seinem Niri-Layout, also scrollenden Spalten wie splice. Die linke Option-Taste übernimmt die Rolle von Super, die Belegung folgt der splice-Konfiguration; die rechte Option-Taste bleibt für Zeichen wie @, € und [ ]. Die Einstellungen liegen wie bei splice als normale Datei in dotfiles/omniwm/settings.toml; Änderungen aus dem OmniWM-Einstellungsfenster landen direkt dort. Programme und Screenshots startet skhd, weil OmniWM selbst keine Programme starten kann. Beim ersten Start fragt macOS nach Bedienungshilfen und Eingabeüberwachung für OmniWM sowie nach Bedienungshilfen (und für Screenshots Bildschirmaufnahme) für skhd.
.
├── flake.nix
├── flake.lock
│
├── modules/
│ ├── hosts/ # desktop/, vm/, mac.nix – setzen nur Features zusammen
│ ├── features/ # ein Feature pro Datei (NixOS-, Home-Manager- und Darwin-Teil)
│ ├── packages/ # Overlay `pkgs.local.*` für ../packages
│ ├── monitors.nix # zentrale Output-Namen
│ └── checks.nix
│
├── packages/
│ ├── claude-desktop.nix
│ └── ...
│
├── dotfiles/
├── scripts/
└── wallpapers/
Die Konfiguration folgt dem dendritic pattern: flake-parts und import-tree laden jede Datei unter modules/ automatisch, und jede Datei registriert ihre Teile unter flake.modules.<klasse>.<name>.
features/: ein Feature pro Datei, zum Beispielaudio,streamdeck,greeter,splice,theming,terminal,shell,development,gaming. Hat ein Feature sowohl einen NixOS- als auch einen Home-Manager-Teil, hängt das NixOS-Modul den Home-Manager-Teil selbst überhome-manager.sharedModulesein. Der Host importiert dann nurnixos.<feature>.hosts/:desktop/undvm/enthalten neben der Host-Definition auch Hardware und Storage bzw. Disko;mac.nixist die nix-darwin-Konfiguration. Hosts wählen Features aus und setzen hostspezifische Werte.- Shell:
features/shell.nixenthältfish(NixOS, inklusive Login-Shell) undzsh(macOS). Gemeinsame Aliase stehen an einer Stelle. - Reine Home-Manager-Features (
theming,terminal,file-manager,starship,calendar,obsidian) werden vom Host direkt unterhome-manager.users.chris.importsaufgeführt.
Home Manager wird über die jeweilige NixOS- bzw. nix-darwin-Konfiguration eingebunden. Ein separater home-manager switch ist daher nicht notwendig.
Eigene Nix-Derivations (als pkgs.local.<name> über modules/packages/local.nix verfügbar) für Software, die nicht direkt oder nicht in der gewünschten Form aus nixpkgs verwendet wird.
Aktuell gehören dazu unter anderem:
- Claude Desktop
Electron-/Chromium-Apps werden mit --password-store=gnome-libsecret gestartet, da die Session XDG_CURRENT_DESKTOP=splice setzt und Chromium das Keyring-Backend sonst nicht erkennt. Claude Desktop läuft zusätzlich über XWayland (--ozone-platform=x11), weil die native Wayland-Variante beim ersten Start keine korrekte Fensterumrandung erhält.
Versionen und Hashes werden mit scripts/update-packages geprüft; --apply schreibt sie in die Nix-Dateien.
Deklarativ übernommene Anwendungskonfigurationen, zum Beispiel dotfiles/MangoHud/MangoHud.conf.
Persistente Laufzeitdaten, Accounts, Tokens und vergleichbare zustandsbehaftete Daten gehören dagegen nicht in dieses Verzeichnis.
Der Desktop ist bewusst als schlankes Wayland-System aufgebaut.
Die zentrale Komponente ist mein eigener Compositor splice auf Basis von Smithay.
Die Desktop-Shell (Bar, Launcher, Wallpaper-Picker, Sperr- und Anmeldebildschirm, Benachrichtigungen, Tray) zeichnet der Compositor selbst (builtin_shell = true).
Die einzelnen Komponenten werden getrennt entwickelt und über die Flake als feste Inputs eingebunden.
splice ist mein eigener Wayland-Compositor auf Basis von Smithay (Repository Splice-Compositor).
Das Projekt übernimmt unter anderem:
- Compositing (Direct Scanout, VRR, Tearing für Spiele) und Effekte
- Window Management
- Workspaces
- Fokussteuerung
- Keybindings
- Output-Verwaltung
- Integration mit der Desktop-Shell
Die Einbindung steht in modules/features/splice.nix, die Konfiguration selbst in
dotfiles/splice/config.toml. Sie wird nicht von Nix generiert, sondern als Symlink nach
~/.config/splice/config.toml gelegt, damit das Einstellungsfenster (splice-settings) sie direkt
bearbeiten kann und der Compositor sie live neu lädt.
Der Anwendungscode selbst wird nicht in diesem Repository gepflegt; das Repository wird als
Flake-Input splice eingebunden und liefert Paket und NixOS-Modul.
Im Greeter gibt es zwei Sitzungen: splice für den Alltag (nur Warnungen und Fehler in
~/.local/state/splice/compositor.log) und splice (Dev) zum Entwickeln (gesamte Ausgabe in
~/.local/state/splice/session.log, dazu alle 5 s Frame-Statistiken pro Monitor).
Die Desktop-Shell ist in den Compositor integriert. Sie wird über builtin_shell = true in
dotfiles/splice/config.toml eingeschaltet (der Compositor-Standard) und kommt mit dem splice-Input.
Quickshell ist nicht mehr Teil der Konfiguration.
Die grafische Sitzung wird über greetd gestartet.
Das Session-Setup kümmert sich anschließend um die benötigten Wayland-Komponenten und die Integration mit systemd und D-Bus.
Zum Desktop gehören außerdem unter anderem:
- PipeWire
- PipeWire-Filter
Mic Filter(Rauschunterdrückung und EQ auf dem jeweils gewählten Mikrofon) - xdg-desktop-portals
- Polkit-Agent
- Benachrichtigungen
- Screen Lock
- Wallpaper-Integration
Xwayland bleibt verfügbar, wenn Anwendungen es benötigen.
Die Ausgabenamen (main, top, side) sind zentral in modules/monitors.nix definiert und werden vom Greeter und dem XWayland-Dienst verwendet; die splice-Konfiguration nennt sie ebenfalls ([[outputs]]).
Die Session selbst (Startskripte, splice-session.target, Portal-Konfiguration) kommt aus dem NixOS-Modul des splice-Flakes; hier wird nur das Keyring-Portal ergänzt. Screen-Sharing läuft über splice-portal: Der Compositor fragt selbst, welcher Monitor oder welches Fenster geteilt wird.
Dark Mode ist systemweit Standard: color-scheme = prefer-dark in dconf (für Portal, GTK4, Electron, LibreWolf), GTK- und Qt-Theme sowie AppleInterfaceStyle = "Dark" auf dem Mac.
nix flake check baut Desktop und VM und prüft Formatierung (nixfmt) sowie ungenutzten Code (deadnix). Nach Änderungen an Splice-Compositor aktualisiert
scripts/update-splice-chain --pushden Flake-Lock (nixos), testet ihn und pusht nur bei Erfolg.
Das Desktop-System verwendet Btrfs.
Der Root-Zustand ist bewusst kurzlebig: Beim Booten wird das Root-Subvolume zurückgesetzt, sodass Änderungen außerhalb der explizit persistenten Bereiche nicht dauerhaft erhalten bleiben.
Damit bleibt das laufende System weitgehend aus der Nix-Konfiguration reproduzierbar.
Persistente Daten werden getrennt vom kurzlebigen Root verwaltet.
Dazu gehören beispielsweise:
- Benutzerdateien
- ausgewählte Systemzustände
- Logs
- notwendige Anwendungsdaten
- Passwortinformationen
journald wird persistent gespeichert, sodass Logs auch nach einem Root-Rollback und Neustart verfügbar bleiben.
Alte Root-Zustände können kurzfristig als Btrfs-Subvolumes aufbewahrt und anschließend automatisch bereinigt werden.
Das Ziel ist dabei nicht vollständige Zustandslosigkeit, sondern eine klare Trennung zwischen:
deklarativem Systemzustand
+
explizit persistentem Laufzeitzustand
LibreWolf ist der primäre Browser und als Standardbrowser für HTTP, HTTPS und HTML registriert (modules/features/browser.nix, Super+B).
- Add-ons werden per Policy von addons.mozilla.org erzwungen installiert und aktualisieren sich selbst; uBlock Origin bringt LibreWolf mit.
- DRM (Widevine) ist aktiviert, ebenso der Download des Widevine-Moduls.
- Dark Mode: Statt RFP läuft FPP mit allen Zielen außer
CSSPrefersColorScheme, damit Webseiten das dunkle Farbschema sehen. - Angemeldet bleiben: Cookies und Websitedaten werden beim Beenden nicht gelöscht.
- Oberfläche: kompakt, mit festem Toolbar-Layout (
browser.uiCustomization.state) unddotfiles/librewolf/userChrome.css: durchscheinender Rahmen in den GTK-Farben, abgerundete Ecken, Seite als Karte, keine Fensterknöpfe.
Nur zum Konfigurieren und Flashen von Maus und Tastatur über WebHID. Eine udev-Regel (70-asus-hidraw-uaccess.rules, muss vor 73-seat-late.rules liegen) gibt allen ASUS-HID-Geräten uaccess, also Maus per Kabel, Dongle und Firmware-Update-Modus; die Keychron-Tastatur bekommt ihn schon über die OpenRGB-Regeln.
OpenRGB übernimmt die RGB-Steuerung der Desktop-Hardware.
Die vorhandene OpenRGB-Konfiguration wurde vom früheren CachyOS-System übernommen.
Die Hardwareintegration erfolgt systemweit über NixOS einschließlich der benötigten udev-Regeln.
streamdeck-ui wird über das NixOS-Modul installiert. Das Modul bindet die
mitgelieferten udev-Regeln ein. Ein Home-Manager-Systemd-Dienst startet den
Controller zusammen mit der grafischen Sitzung ohne sichtbares Fenster. Die Konfigurationsoberfläche
bleibt über den Launcher verfügbar. Die Tasten-Icons werden aus Papirus über
stabile Pfade unter ~/.local/share/streamdeck-icons bereitgestellt.
Die Desktop-Konfiguration enthält ein eigenes Gaming-Modul.
Dazu gehören unter anderem:
- Steam
- Prism Launcher
- Faugus Launcher
- Heroic Games Launcher
- Vesktop
- GameMode
- GOverlay (inklusive MangoHud)
- notwendige 32-Bit-Grafikunterstützung
GameMode kann Spielen temporär optimierte Systemressourcen zur Verfügung stellen.
GOverlay dient zur Konfiguration von MangoHud. MangoHud wird dabei bereits als
Laufzeitabhängigkeit von GOverlay mitgeliefert und zeigt Performance-Informationen
wie FPS, Frametimes und Hardwareauslastung an. Die bestehende MangoHud- und
GOverlay-Konfiguration (dotfiles/MangoHud/MangoHud.conf) wird beim ersten
Home-Manager-Lauf als beschreibbarer Startwert übernommen, damit spätere
Änderungen über GOverlay möglich bleiben.
Gamescope ist nicht zwingender Bestandteil des Setups und wird nur ergänzt, wenn ein konkreter Anwendungsfall dafür entsteht.
Die Entwicklungsumgebung wird ebenfalls deklarativ verwaltet.
Sie enthält unter anderem Werkzeuge für:
- Rust
- Python
- Node.js
- Git
- Neovim / LazyVim
- Zed
- Compiler- und Build-Werkzeuge
- CLI- und Suchwerkzeuge
Allgemeine Werkzeuge gehören in die System- bzw. Home-Konfiguration.
Projektabhängige Toolchains und SDKs sollen dagegen bevorzugt über projektspezifische Nix-Devshells bereitgestellt werden.
Ein Teil der Konfiguration des früheren CachyOS-Systems wurde in das Repository übernommen.
Dazu gehören beispielsweise Einstellungen für:
- Kitty
- Neovim / LazyVim
- GTK
- Vesktop
- OpenRGB
- MangoHud / GOverlay
Dabei wird zwischen deklarativer Konfiguration und Laufzeitdaten unterschieden.
Accounts, Tokens, Sessions und andere sensible oder veränderliche Daten werden nicht einfach als Dotfiles ins Repository übernommen.
Die Konfiguration verwendet Nix Flakes.
flake.lock fixiert die verwendeten Versionen und Commits, wodurch Builds reproduzierbar bleiben.
Neben nixpkgs und Home Manager werden auch die eigenen Desktop-Projekte als Inputs eingebunden.
Dadurch benötigt ein normaler System-Build keine benachbarten Git-Checkouts von splice.
Änderungen an diesen Projekten werden erst übernommen, wenn der entsprechende Flake-Input aktualisiert wird.
Die Desktop-Konfiguration kann gebaut werden mit:
nix build .#nixosConfigurations.desktop.config.system.build.toplevelFalls die experimentellen Features nicht global aktiviert sind:
nix build .#nixosConfigurations.desktop.config.system.build.toplevel \
--extra-experimental-features "nix-command flakes"Analog lässt sich die VM-Konfiguration bauen:
nix build .#nixosConfigurations.vm.config.system.build.toplevelDie macOS-Konfiguration lässt sich vor der Aktivierung evaluieren bzw. bauen:
nix build .#darwinConfigurations.mac.systemZunächst die gewünschten Flake-Inputs aktualisieren:
nix flake updateDanach kann die entsprechende Konfiguration gebaut bzw. aktiviert werden.
Auf dem Desktop:
sudo nixos-rebuild switch --flake .#desktopIn der VM:
sudo nixos-rebuild switch --flake .#vmAuf macOS:
darwin-rebuild switch --flake .#macVor einem Switch kann die Konfiguration ohne Aktivierung geprüft werden:
nix build .#nixosConfigurations.desktop.config.system.build.toplevel