Declarative cross-platform system configuration using Nix.
SystemNix manages both macOS (nix-darwin) and NixOS systems through a single, reproducible Nix flake. All system settings, packages, services, and user configurations are defined in code and applied consistently across machines.
| Category | Tools & Services |
|---|---|
| Languages | Go 1.26, Node.js, Bun, Python 3.13, Rust |
| Cloud & Infra | AWS CLI, GCP SDK, kubectl, Helm, Terraform, Docker |
| Development | Git, GitHub CLI, Git Town, JetBrains Toolbox, (editor of choice - NOT VS Code), Fish shell, tmux, Zellij |
| Desktop (NixOS) | Niri (Wayland tiling), Waybar, SDDM, Rofi, Ghostty, Kitty, Dunst, swaylock |
| Self-Hosted Services | Immich (photos), Forgejo (Git), SigNoz (observability), Homepage Dashboard, Hermes AI |
| AI/ML | Ollama (ROCm), llama.cpp, AMD NPU (XDNA) driver |
| Security | Gitleaks, sops-nix, AppArmor, Fail2ban, ClamAV, Touch ID for sudo (macOS) |
| Monitoring | SigNoz (18 alert rules, 5 dashboards), Gatus (30 health checks), ActivityWatch |
| Networking | Caddy reverse proxy (TLS), Unbound DNS with 2.5M+ blocked domains, DNSSEC |
| Storage | BTRFS with btrbk snapshots (daily + pre-deploy), ZRAM swap, monthly scrub |
- macOS (Apple Silicon) or Linux (x86_64) with Nix installed
- Administrative access
# Install Nix (Determinate Systems installer) curl --proto '=https' --tlsv1.2 -sSf -L https://install.determinate.systems/nix | sh -s -- install # Clone and apply configuration git clone https://github.com/LarsArtmann/SystemNix.git ~/projects/SystemNix cd ~/projects/SystemNix just setup # Complete setup just switch # Apply configuration
| System | Hardware | Configuration | Command |
|---|---|---|---|
| macOS (Lars-MacBook-Air) | Apple Silicon, 24GB RAM, 256GB SSD | flake.nix#Lars-MacBook-Air |
just switch |
| NixOS (evo-x2) | AMD Ryzen AI Max+ 395, 128GB RAM | flake.nix#evo-x2 |
just switch |
SystemNix/
├── flake.nix # Main entry point with flake-parts
├── justfile # Task runner for all operations
├── modules/nixos/services/ # 39 NixOS service modules (auto-discovered, ~37 enabled)
├── pkgs/ # 5 custom packages (jscpd, govalid, netwatch, openaudible, aw-watcher-utilization)
├── overlays/ # 25 overlay packages (17 shared + 8 Linux-only) via mkPackageOverlay
├── lib/ # 8 files exporting 13+ helpers (harden, ports, mkDockerServiceFactory, ...)
├── platforms/
│ ├── common/ # Shared across platforms (~80% of config)
│ │ ├── home-base.nix # Home Manager base (13 program modules)
│ │ ├── programs/ # Fish, Zsh, Bash, Starship, Git, tmux, ...
│ │ ├── packages/ # Cross-platform packages & fonts
│ │ └── core/ # Nix daemon settings
│ ├── darwin/ # macOS-specific (nix-darwin)
│ │ ├── default.nix # System config
│ │ ├── home.nix # User config
│ │ ├── services/ # LaunchAgents (ActivityWatch, Crush updates)
│ │ └── programs/ # Chrome policies, shell aliases
│ └── nixos/ # NixOS-specific
│ ├── system/ # Boot, networking, BTRFS snapshots, DNS blocker
│ ├── desktop/ # Niri, Waybar, SDDM, AI stack, security hardening
│ ├── hardware/ # AMD GPU/NPU, Bluetooth, hardware config
│ ├── programs/ # Rofi, swaylock, wlogout, Yazi, Zellij, Chromium
│ └── users/ # Home Manager user config
├── scripts/ # 29 operational scripts (26 shell + 3 Python)
└── docs/ # Architecture decisions (8 ADRs), status reports, troubleshooting
All services are defined as flake-parts modules, reverse-proxied through Caddy with TLS, and monitored by Gatus (33 health checks) + SigNoz (18 alert rules, 6 dashboards):
| Service | Port | URL | Description |
|---|---|---|---|
| Caddy | 443 | *.home.lan |
Reverse proxy with sops-managed TLS certs |
| Immich | 2283 | immich.home.lan |
Self-hosted Google Photos alternative (PostgreSQL + Redis + ML) |
| Forgejo | 3000 | forgejo.home.lan |
Self-hosted Git forge with GitHub mirror sync & Actions |
| SigNoz | 4317, 4318, 8080 | signoz.home.lan |
Observability: traces, metrics, logs + node_exporter + cAdvisor, 6 dashboards |
| Homepage | 8082 | dash.home.lan |
Service overview dashboard |
| Pocket ID | 1411 | auth.home.lan |
Passkey-based SSO/IDP + oauth2-proxy forward auth |
| Hermes | — | — | AI agent gateway (Discord bot, cron scheduler, multi-provider LLM) |
| Twenty CRM | 3200 | crm.home.lan |
Self-hosted CRM (Docker Compose: PostgreSQL + Redis) |
| Voice Agents | 7880 | — | AI voice agents (Docker: LiveKit + Whisper ASR with ROCm) |
| TaskChampion | 10222 | tasks.home.lan |
Taskwarrior sync server (cross-platform + Android) |
| Manifest | 2099 | manifest.home.lan |
Smart LLM router for AI agents (cost optimization) |
| Overview | 8083 | — | Local project dashboard (git repo discovery, stats, activity) |
| Dozzle | 8084 | logs.home.lan |
Real-time Docker container log viewer |
| Monitor365 | 3001 | monitor.home.lan |
Device monitoring agent + server dashboard |
| OpenSEO | 3002 | seo.home.lan |
Self-hosted SEO suite (rank tracking, keyword research) |
| Crush Daily | 8081 | daily.home.lan |
AI-powered development insights from Crush databases |
| PMA | — | — | Projects Management Automation (AI commit messages, repo discovery) |
| Dual-WAN | — | — | MPTCP dual-WAN with route health monitoring |
| Gatus | 9110 | status.home.lan |
Health check monitoring with Discord alerts |
| DNS Blocker | 53, 8050 | — | Unbound + dnsblockd, 23 blocklists, 2.5M+ domains blocked, DoT upstream |
| Mullvad VPN | — | — | WireGuard VPN with LAN bypass, route-based split tunneling |
| DiscordSync | — | — | Continuous Discord channel backup bot |
- 2.5M+ blocked domains across 23 blocklists (ads, trackers, malware, telemetry, gambling, native device trackers)
- Upstream: Quad9 (DNS-over-TLS) + Cloudflare fallback
- Local
.home.lanDNS records for all services - DNSSEC enabled, qname minimization
- DNS failover: Raspberry Pi 3 secondary resolver with VRRP VIP (planned)
- Niri: Scrollable-tiling Wayland compositor with 5 named workspaces, session save/restore
- Ghostty: Primary terminal (GPU-accelerated, native Wayland)
- Kitty: Backup terminal (GPU-accelerated, image display)
- Waybar: Custom status bar with workspaces, media, weather, DNS stats, power menu
- SDDM: Login manager with Catppuccin Mocha theme
- Theme: Catppuccin Mocha across all applications (GTK, Qt, terminal, browser)
- Backup WM: Sway configured as fallback
| Component | Configuration |
|---|---|
| CPU | AMD Ryzen AI Max+ 395 (Strix Halo), amd_pstate=guided |
| GPU | AMD integrated (amdgpu), Mesa latest, ROCm compute stack |
| NPU | AMD XDNA via nix-amd-npu, XRT runtime |
| Memory | 128GB unified, ZRAM swap (32GB), tuned for AI/ML workloads |
| Storage | BTRFS root (zstd) + /data (zstd:3), btrbk snapshots (daily + pre-deploy) |
| Boot | systemd-boot (50 generations), latest Linux kernel |
| Network | Realtek 2.5G Ethernet, MediaTek WiFi |
# Core workflow just setup # Initial setup (run once after clone) just switch # Apply configuration changes just update # Update flake inputs and packages just update-nix # Self-update Nix to latest version just test # Validate configuration (full build) just test-fast # Syntax-only validation (fast) just check # System status, git, disk usage # Quality just format # Format code with treefmt + alejandra just health # System health check just pre-commit-install # Install pre-commit hooks just pre-commit-run # Run all hooks on all files # Maintenance just clean # Comprehensive cleanup (Nix, caches, temp, Docker) just rollback # Revert to previous generation # NixOS services just dns-diagnostics # Full DNS diagnostics just immich-status # Check Immich service status just immich-backup # Run database backup just forgejo-sync-repos # Sync GitHub repos to Forgejo just hermes-status # Check Hermes gateway status just manifest-status # Check Manifest LLM router status just session-status # Check niri session save state just cam-status # Check EMEET PIXY webcam state # Taskwarrior just task-list # Show pending tasks just task-sync # Sync with TaskChampion server just task-backup # Export all tasks as JSON
Shared across macOS and NixOS via platforms/common/programs/:
| Program | Configuration |
|---|---|
| Fish | Primary shell, shared aliases, carapace completions, 5000 history |
| Zsh | Secondary shell with autosuggestions, syntax highlighting |
| Starship | Prompt with Catppuccin Mocha, performance-optimized |
| Git | GPG signing, SSH insteadOf HTTPS, git-town integration |
| tmux | Catppuccin theme, resurrect plugin, SystemNix dev session |
| FZF | Ripgrep integration, reverse layout |
| KeePassXC | Browser integration (Chromium + Helium) |
| Chromium | Enterprise policies, YouTube Shorts Blocker, HTTPS-only |
52 inputs — key ones below:
| Input | Purpose |
|---|---|
nixpkgs |
Package collection (unstable) |
nix-darwin |
macOS system management |
home-manager |
Cross-platform user configuration |
flake-parts |
Modular flake architecture |
niri |
Scrollable-tiling Wayland compositor |
nix-homebrew |
Declarative Homebrew management (macOS) |
sops-nix |
Secrets management with age encryption |
nix-amd-npu |
AMD NPU (XDNA) driver |
nix-ssh-config |
Shared SSH configuration |
crush-config |
AI assistant configuration |
hermes-agent |
AI agent gateway (Discord bot) |
silent-sddm |
SDDM theme with Catppuccin support |
signoz-src |
SigNoz observability source (built from source) |
signoz-collector-src |
SigNoz OTel collector source |
dnsblockd |
Custom DNS blocker (Go) |
treefmt-full-flake |
Code formatting (alejandra + more) |
nixos-hardware |
Hardware-specific NixOS modules |
helium |
Helium browser (macOS) |
nur |
Nix User Repository |
wallpapers-src |
Wallpaper collection |
Color schemes are defined locally in platforms/common/theme.nix (not via a flake input).
GitHub Actions workflow (.github/workflows/nix-check.yml) runs on every push/PR to master (Ubuntu runner):
- Flake evaluation:
nix flake check --no-build --all-systems - Package builds:
jscpd,govalid,aw-watcher-utilization - Statix: Nix anti-pattern linting
- Deadnix: Dead code detection
- Formatting:
nix fmt -- --check .
9 hooks configured via .pre-commit-config.yaml:
- gitleaks — secret detection
- alejandra — Nix formatting
- deadnix — dead code detection
- statix — Nix anti-patterns
- trailing-whitespace — whitespace cleanup
- nix-check — flake validation
- flake-lock-validate — lock file integrity
- shellcheck — shell script linting
- check-merge-conflicts — conflict marker detection
| Guide | Description |
|---|---|
| AGENTS.md | AI assistant guide and project conventions |
| Architecture Decisions | ADRs for key design choices |
| Project Status | Development status reports |
| Troubleshooting | Common issues and solutions |
| Architecture Diagrams | Mermaid diagram collection |
just test-fast # Quick syntax validation just clean && just switch # Clean and rebuild
nix profile add nixpkgs#gnupg
# Path: ~/.nix-profile/bin/gpgnix search nixpkgs <package-name>
just dns-diagnostics # Full DNS diagnostics just dns-restart # Restart DNS services just dns-test # Test resolution and blocking
- Make changes in
platforms/common/for cross-platform config - Use platform-specific directories for platform differences
- Run
just testbefore committing - Follow existing code style (2-space indentation for Nix)
Personal configuration. Adapt for your own use.