Rebase the fork branches and refresh nixpkgs, home-manager, and the approved ancillary inputs. Update kernel and release metadata, adapt removed package and Home Assistant options, and keep Determinate Nix on its tested nixpkgs revision to avoid duplicate Boost patches. Retire Sharry and its public endpoint because copyparty replaces it. Document the GitHub mirror gate and require real devshell and system builds in the upgrade validation workflow.
18 KiB
Architecture
This flake does not use the stock pattern of calling nixosSystem once per host in
flake.nix. Instead it runs a single lib.evalModules evaluation over its own
module tree, producing one big top-level config (self.nixfiles) from which the real flake
outputs (nixosConfigurations, homeConfigurations, nixosModules, deploy, …) are derived.
Per-host files declare options (nixos.systems.<name>); the machinery in
nixos/default.nix and
home-manager/default.nix turns those into evaluated NixOS /
home-manager configurations.
The top-level evaluation
flake.nix's outputs builds a nixfiles attrset via evalModules over:
- An inline module that seeds
_module.args(lib,pkgsFlakes,hmFlakes,self,inputs,pkgs'), setsnixos.secretsPath = ./secrets, and sets the global deploy-rs SSH optiondeploy-rs.deploy.sshOpts = [ "-i" ".keys/deploy.key" ]. nixos/modules/misc/assertions.nixfrom the unstable nixpkgs (so the top-level evaluation has the standardassertions/warningsoptions).nixos/— definesnixos.*options (systems,modules,allAssignments,vpns,secretsPath) andmkSystem.home-manager/— defineshome-manager.*options (homes,modules) andmkHome.deploy-rs.nix— definesdeploy-rs.*and renders the deploy config.- Every file in the
configslist — the boxes themselves (nixos/boxes/plusnixos/installer.nix; the home-manager entries are currently commented out, see Home-manager).
The resulting nixfiles.config is mapped onto flake outputs:
Top-level option (nixfiles.config) |
Flake output |
|---|---|
nixos.systems.<name>.rendered |
nixosConfigurations.<name> |
home-manager.homes.<name>.configuration |
homeConfigurations.<name> |
nixos.modules |
nixosModules |
home-manager.modules |
homeModules |
deploy-rs.rendered |
deploy |
nixfiles itself is also a flake output, so anything in the top-level config can be addressed
directly — e.g. build-iso builds
.#nixfiles.config.nixos.systems."<host>".configuration.config.my.buildAs.iso. The flake also
exposes lib (the extended unstable nixpkgs lib, including lib.my), inputs, nixpkgs
(the pkgs' channel sets), and overlays.default (the custom packages from
pkgs/).
Per platform (eachDefaultSystem), the flake produces:
packages— everything frompkgs/, flattened.checks— everyhomeConfigurations.*.activationPackageplus deploy-rs's owndeployChecks.devShells.default— thenumtide/devshellfromdevshell/(see deployment.md).ci.<system>— one attr per buildable thing (system-<name>,home-<name>with@mangled to-at-,package-<name>, plusshell), consumed by CI;ciDrvis alinkFarmof all of them.
Systems: systemOpts and mkSystem
Each entry of nixos.systems is a submodule defined by systemOpts in
nixos/default.nix:
| Option | Type / default | Meaning |
|---|---|---|
system |
enum of defaultSystems |
Nix platform string, e.g. "x86_64-linux". |
nixpkgs |
one of unstable/stable/mine/mine-stable, default "unstable" |
nixpkgs channel for the system. |
home-manager |
same enum, defaults to nixpkgs |
home-manager channel. |
hmNixpkgs |
same enum, defaults to nixpkgs |
nixpkgs channel used for home-manager's own pkgs when it doesn't share the system's. |
docCustom |
bool, default false |
Include nixfiles' custom modules in the generated NixOS manual (slow). |
assignments |
attrsOf assignmentOpts |
The box's network assignments (see networking.md). |
extraAssignments |
attrsOf attrsOf assignmentOpts |
Extra assignments for things not on the box itself (e.g. the routers' floating VIP entries). |
configuration |
custom merged type | The actual NixOS configuration module(s); merging runs mkSystem. |
rendered |
unspecified, default configuration |
What ends up in nixosConfigurations.<name> — overridden for boxes built as something other than a plain system (e.g. installer renders config.my.asISO, containers render config.my.asContainer). |
mkSystem does the real work:
- It selects the channel's nixpkgs flake (
pkgsFlakes.${config'.nixpkgs}).- It imports
nixos/lib/eval-config.nixby hand because the flake force-setslib; otherwiseeval-config.nixwould import its own unextended copy. - The supplied library is the channel's
pkgs.libextended withlib.myand aversionOverlaythat stampssystem.nixoswith the flake revision and channel.
- It imports
specialArgsgives every module access toself,inputs,pkgsFlakes, the box's ownpkgsFlake,allAssignments(every box's assignments), andsystems(all ofnixos.systems). Passing these viaspecialArgs(rather than moduleimports) avoids infinite recursion.- The module list is: the home-manager channel's
nixosModules.default, every module innixos.modules(the shared modules, see below), an inline module, and the box's ownconfigurationdefinitions (wrapped withinlineModule'so error messages keep file provenance). - The inline module wires the plumbing:
_module.args:secretsPath,vpns(the flake-levelnixos.vpns), the box's ownassignments, andpkgs'— an attrset of all four nixpkgs channels for this box's platform, so a module can grab a package from another channel (e.g.pkgs'.stable.foo).system.nameis the attribute name of the box.networking.hostName/networking.domaindefault from theinternalassignment (see networking.md).nixpkgs.systemis set and the overlays computed at flake level (lib overlay + custom packages) are passed through, sopkgsis imported modularly with config and overlays applied.home-manager.useGlobalPkgsdefaults to true when the system and home-manager channels match; a warning is emitted when they deliberately differ.home-manager.sharedModulesincludes every module inhome-manager.modulesplus an inline module. The inline module passespkgsPath/pkgs', disables the release check, and pinshome.stateVersionthroughhomeStateVersion(22.11for stable-flavoured channels,23.05otherwise).
- Finally
applyAssertionsthrows with all failed assertion messages (and shows warnings) when the merged configuration is forced.
The four nixpkgs channels
flake.nix builds pkgsFlakes (nixpkgs) and hmFlakes (home-manager):
| Channel | nixpkgs input | home-manager input |
|---|---|---|
unstable |
nixpkgs/nixos-unstable |
home-manager (master) |
stable |
nixpkgs/nixos-26.05 |
home-manager/release-26.05 |
mine |
github:devplayer0/nixpkgs/devplayer0 (personal fork) |
alias of unstable (no fork exists) |
mine-stable |
github:devplayer0/nixpkgs/devplayer0-stable |
alias of stable |
Each channel's lib is extended with the libOverlay (lib.my + flake-utils). Two package
sets are built per channel:
pkgs'— with the devshell/ragenix/deploy-rs/home-manager overlays; used for the dev shell andpackages, and exposed as the flake'snixpkgsoutput.configPkgs'— with just the lib + custom-packages overlays and anallowUnfreePredicate(Widevine / Chromium); this is thepkgs'threaded into the top-level evaluation, from which each box'spkgsand per-channelpkgs'module args (and home-manager's basepkgs) are taken.
A box picks its channel with nixpkgs = "mine" (most boxes), "mine-stable" (e.g. colony),
etc. Inside a module, pkgs is the selected channel and pkgs' is the attrset of all four
(pkgs'.<channel>.<attr>).
lib.my and the my.* namespace
lib/default.nix extends nixpkgs lib with a my attrset. The
flake-level lib (pkgsFlakes.unstable.lib so extended) is for platform-independent flake
use only; each box gets its own channel's lib extended the same way. Contents:
- Option helpers —
mkOpt',mkBoolOpt',nullOrOpt',mkDefault'(slightly stronger thanmkDefault),mkVMOverride',inlineModule'/inlineModule(attach_fileprovenance),commonOpts(the sharedsystem/nixpkgs/home-manageroptions and themoduleTypeused for exported modules),applyAssertions,duplicates. lib.my.net— CIDR/IP math (net.cidr.host,net.cidr.subnet,net.types.ipv4, …) from thelibnetRepoinput (oddlama/nixos-extra-modules'netu.nix). Used for nearly all address arithmetic; addresses are almost never written literally.lib.my.c— shared constants fromlib/constants.nix: static UID/GID assignments, kernel package selection (kernel.lts/kernel.latest), nginx config snippets, networkd snippets (networkd.noL3), the binary-cache settings (nix.cache), and the per-site domains/prefixes/VIPs described in networking.md.lib.my.dns— zone-generation helpers fromlib/dns.nix:fwdRecords/ptrRecords/ptr6Recordsrendered fromallAssignments, plus the LUA-record helpers (ifaceA,lookupIP) used by the home routers.- networkd helpers —
networkdAssignment(assignment →systemd.networknetwork, see networking.md),mkVLAN,dockerNetAssignment.
Misc
The remaining helpers are mkDefaultSystemsPkgs, flakePackageOverlay (wrap another flake's
package as an overlay), isIPv6 / parseIPPort / netBroadcast, nft chain-name helpers,
systemdAwaitPostgres, vm.* LVM disk descriptors for the vms module, the typed deploy-rs
option definitions (lib.my.deploy-rs), netbootKeaClientClasses (iPXE/EFI DHCP client classes),
and homeStateVersion.
Custom NixOS / home-manager modules declare their options under the my.* namespace (the root
options.my is declared in nixos/modules/common.nix / home-manager/modules/common.nix) —
e.g. my.secrets, my.build, my.tmproot, my.firewall, my.server, my.deploy,
my.vms, my.containers.
Shared modules
Registered in nixos/modules/_list.nix and applied to every
system (box files opt in per-feature via my.* options). The table below is the overview — what
each module is for; for the exhaustive, CI-generated per-option reference (types, defaults,
descriptions) see reference/nixos-options.md.
| Module | Provides |
|---|---|
common |
Baseline for all boxes: imports the impermanence, ragenix (age), copyparty and harmonia NixOS modules; pins system.stateVersion; doas instead of sudo; immutable users; nix settings (flakes, ca-derivations, the nix-cache.nul.ie substituter); declares the my option root. |
user |
my.user — the primary user: users.users + matching home-manager.users entry, wheel/doas, SSH authorized key from .keys/me.pub, shell taken from the home config, home persistence under tmproot. |
build |
my.build — alternate build targets via extendModules: my.buildAs.devVM (QEMU dev VM), iso, container, kexecTree, netbootTree/netbootArchive; my.build.isDevVM marker; allHardware profile toggle. |
dynamic-motd |
my.dynamic-motd — runs a script via pam_exec to generate the MOTD on login/ssh. |
tmproot |
my.tmproot — tmpfs / plus impermanence persistence (persistence.dir), with a tmproot-unsaved helper that walks the root tmpfs and lists files not covered by persistence. |
firewall |
my.firewall — nftables firewall: tcp.allowed/udp.allowed port lists, trustedInterfaces, NAT with forwardPorts, extraRules escape hatch; sane ICMP/ICMPv6/PMTUD rules baked in. |
server |
my.server.enable — server commonalities: getty autologin, LLMNR off, tightened fstrim timers, GUI and NixOS documentation off. |
deploy-rs |
my.deploy — per-box deploy-rs node/profile generation and the deploy user; see deployment.md. |
secrets |
my.secrets — ragenix/agenix wiring: files to decrypt from secrets/, host key to encrypt for, identity paths derived from the OpenSSH host keys (persistence-aware), dev-key identity inside dev VMs. |
containers |
my.containers.instances — systemd-nspawn NixOS containers whose systems come from nixos.systems rendered asContainer, with bridge/macvlan networking, bind mounts, hotReload (reload instead of reboot) and a placeholder "dummy" init before first deploy. |
vms |
my.vms.instances — QEMU/KVM VMs as systemd units: TAP/bridge networking, LVM-backed disks, VFIO host-device passthrough (with udev tagging), UEFI, SPICE/TTY/QMP unix sockets under /run/vms/, clean shutdown via QMP system_powerdown. |
network |
Baseline networking: networkd only (useDHCP = false), IPv6 on, resolved domain/negative-cache settings; dev VMs get DHCP on eth0 and an SSH port forward. |
pdns |
my.pdns — PowerDNS: authoritative server driven by BIND-style zone files (with templating and serial management) and recursor extra-settings wiring. |
nginx-sso |
my.nginx-sso — runs nginx-sso (instead of the stock NixOS module) and generates per-instance nginx auth_request include files. |
gui |
my.gui.enable (default on) — desktop baseline: graphics, polkit, swaylock PAM entry, Android udev rules, screenshot tmpdir. |
l2mesh |
Consumes nixos.vpns.l2 — builds the VXLAN + IPsec layer-2 meshes between edge routers; see networking.md. |
borgthin |
my.borgthin.jobs — borg backups of thin-LVM snapshots to local or SSH repos on a systemd timer, with pruning. |
nvme |
my.nvme — sets the NVMe host NQN/hostid and, optionally, NVMe-oF-over-RDMA boot in the initrd. |
spdk |
my.spdk — SPDK target configuration (JSON RPC-driven) plus spdk-rpc/spdk-setup/spdk-debug helper tools. |
librespeed |
my.librespeed — a LibreSpeed speedtest: generated frontend (from the librespeed-go package in pkgs/) plus backend settings. |
netboot |
my.netboot — iPXE netboot server (TFTP/HTTP, menu) and the client-side loader that installs boot entries. |
Home-manager modules, registered in
home-manager/modules/_list.nix and applied to every
home (including the per-user homes attached to systems via my.user.homeConfig):
| Module | Provides |
|---|---|
common |
Home baseline: my.shell, my.ssh.authKeys, my.isStandalone (home-manager running standalone vs inside NixOS), fish setup and completions generation, common programs. |
gui |
my.gui — the sway-based desktop: waybar, notifications, lock/saver plumbing (including the "doomsaver"), terminal and fonts. |
deploy-rs |
my.deploy for standalone homes — generates a home profile (home-manager activation) and deploy node; auto-disabled for NixOS-attached homes. |
swaync |
my.swaync — typed configuration module for Sway Notification Center. |
Adding a box
- Create a file (or directory with a
default.nix) undernixos/boxes/that setsnixos.systems.<name> = { system = "x86_64-linux"; nixpkgs = "mine"; assignments = { … }; configuration = { … }: { … }; };. Nested boxes (VMs, containers) live under their host's directory (e.g.nixos/boxes/colony/vms/estuary/). - Add the path to the
configslist inflake.nix. - Give the box an
internalassignment (name/domain) if it gets one —hostName/domaindefault from it — and declaremy.secrets.keyif it has secrets. - Evaluate it with
check-system <name>(cheap) beforebuild-system <name>.
Adding a shared module
- Drop the file in
nixos/modules/(orhome-manager/modules/) with options undermy.*, declared via thelib.myhelpers (mkOpt',mkBoolOpt'). - Register it in the corresponding
_list.nix(name → path). It is then applied to every box and exported asnixosModules.<name>/homeModules.<name>.
Home-manager
Home-manager follows the same option-definition and evaluation split as NixOS.
homeOpts
home-manager/default.nix defines each entry with these options:
| Option | Meaning |
|---|---|
system |
Target platform. |
nixpkgs |
nixpkgs channel used for the home packages. |
home-manager |
home-manager channel. |
homeDirectory / username |
User identity and home path. |
configuration |
The home-manager module definitions evaluated by mkHome. |
mkHome
- Calls the selected channel's
lib.homeManagerConfiguration. - Supplies that channel's
pkgs'withconfigemptied, allowing home-manager to apply package configuration and overlays through its module system. - Passes
inputs,pkgsFlakesand the selectedpkgsFlakethroughextraSpecialArgs. - Loads every module in
home-manager.modulesplus an inline module that setshome.homeDirectory/home.usernameand exposes every channel through thepkgs'module argument. - Pins
home.stateVersionthroughhomeStateVersion.
Standalone homes
Standalone homes live in home-manager/configs/ and are named
<user>@<host> (deploy-rs mangles the @ to -at-). macsimum is a home-manager-only
config — an x86_64-darwin macOS box with no NixOS side.
No standalone homes are currently wired into the flake: home-manager/configs/macsimum.nix is
commented out of configs, while home-manager/configs/castle.nix is not listed. Consequently,
nixfiles.config.home-manager.homes evaluates to {}. Most user configuration instead accompanies
NixOS boxes through my.user.homeConfig.