LLM Context¶
This file maintains the current state of the ndots project for LLM assistants. Update it when making significant changes.
Goal¶
Declarative NixOS + nix-darwin configuration with self-hosted services, monitoring, and mesh VPN. All managed via flakes, deployed with just. Modules are reusable and documented for external consumers.
Constraints & Preferences¶
- Ponytail mode (lazy senior dev) - minimal code, no over-engineering
- No clutter comments (no
---dividers, no ASCII art), comments explain why not what - Secrets:
office.yamlfor office machines,server.yamlfor servers - Sops modules only enable services; hosts declare secrets and wire paths
- Caddy config is imperative (editable on the box, no rebuild)
just deployauto-detects NixOS vs Darwin;just deploy <host>for remote- Don't commit until tested and verified
- Service ports in 4xxx range to avoid clashes
Current State¶
Done¶
- Beszel hub on obox, agents on semi/dsd/obox/mach
- FileBrowser Quantum on all NixOS hosts (root, Tailscale-only, sops passwords)
- Stirling PDF on obox (branded "semi.sh PDF", update notifications off)
- Caddy on obox (imperative config)
- Syncthing:
.notes+.dumpsynced across all devices - Tailscale on all hosts
- Shared virtualisation module (docker system+rootless, podman)
- Opencode config reorganized (default.nix, skills.nix, registry.nix)
- Docs site (MkDocs Material, GitHub Pages, ndots.semi.sh)
- Full module documentation: NixOS, Home, Darwin, Flake modules
- Package documentation: all custom packages documented
- Architecture docs expanded with nix-wire, overlays, packages, justfile, .sops.yaml
Deferred¶
- Excalidraw (docker + room server) - deferred, not deployed
- Stirling PDF Google Drive integration - paid feature, not configured
Architecture Summary¶
flake.nix→nix-wire.mkFlakeauto-wires modules + hosts from directoriesmodules/nixos/→nixosModules.*(default, beszel, filebrowser, virtualisation, tailscale, intel, stylix, hardware, hyprland, juspay, minecraft)modules/home/→homeModules.*(default, shell, editor, ai, browser, terminal, hyprland, darwin, stylix, + standalone modules)modules/darwin/→darwinModules.*(default, settings, yabai, brew, stylix, sharedModules)modules/flake/nix/→flakeModules.nix(nix package, gc, registry, caches)packages/→ auto-discovered, exposed via overlay aspkgs.<name>overlays/→ composes packages.nix + llm-agents overlayhosts/nixos/<name>/→nixosConfigurations.<name>(auto-set hostname)hosts/darwin/<name>/→darwinConfigurations.<name>hosts/home/<user>.nix→homeConfigurations.<user>parts/→ Flake-Parts (treefmt, devShells, pre-commit, disko schemas)config.nix→ shared user + builder data (plain nix, not a module)
Key Gotchas¶
config.users.users.<name>.uidcauses infinite recursion in NixOS eval - use hardcoded 1000- Syncthing doesn't expand
~- useconfig.home.homeDirectoryfor absolute paths - Stirling PDF env-based admin only works on first boot with empty DB
- Beszel agent needs to run as user for rootless Docker (0700 on
/run/user/<uid>/) - AMD GPU bug: SKIP_GPU=true on mach (beszel issue #1799)
podman.dockerSocket.enableconflicts withdocker.enableoci-containersdefaults to podman if both enabled - setbackend = "docker"to force- Excalidraw
REACT_APP_BACKEND_V2_WS_BASE_URLis browser-side - must be public URL - FileBrowser Quantum indexing
/can fail if DB is corrupt - clear/var/lib/filebrowser-quantum/* - obox does NOT import
nixosModules.default(server, skips stylix/home-default/cachy kernel) - ISO forces
nvix.variant = "bare"and disables android module (scrcpy fails on aarch64) nix-wireauto-setsnetworking.hostNamefrom the host directory name- The
hmshorthand is created viamkAliasOptionModuleper-host - opencode-vim overlay patches stale node_modules hashes + relaxes bun version check