feat(lib): mksystem builder and nixpkgs overlays
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
d37ac719d3
commit
87bfc4cc31
2 changed files with 198 additions and 0 deletions
154
lib/mksystem.nix
Normal file
154
lib/mksystem.nix
Normal file
|
|
@ -0,0 +1,154 @@
|
|||
# mksystem — uniform NixOS host constructor.
|
||||
#
|
||||
# Inspired by mitchellh/nixos-config's lib/mksystem.nix, adapted for our
|
||||
# context. Replaces the boilerplate of repeated `nixpkgs.lib.nixosSystem`
|
||||
# calls in flake.nix with a single function that:
|
||||
#
|
||||
# - dispatches to nixpkgs.lib.nixosSystem
|
||||
# - applies overlays uniformly
|
||||
# - imports `hosts/<name>.nix` (or `hosts/<name>/default.nix`) by convention
|
||||
# - imports `users/<user>/nixos.nix` if it exists
|
||||
# - wires home-manager and imports `users/<user>/home-manager.nix`
|
||||
# - opt-in dev-env via `devEnv = true` (imports modules/dev-env)
|
||||
# - exposes `currentSystemName`, `currentSystemUser`, `inputs` to every
|
||||
# module via specialArgs so downstream code can introspect host context
|
||||
#
|
||||
# Usage in flake.nix:
|
||||
#
|
||||
# let
|
||||
# overlays = import ./lib/overlays.nix { inherit inputs; };
|
||||
# mkSystem = import ./lib/mksystem.nix { inherit nixpkgs overlays inputs; };
|
||||
# in
|
||||
# {
|
||||
# nixosConfigurations = {
|
||||
# my-laptop = mkSystem "my-laptop" {
|
||||
# user = "padreug";
|
||||
# devEnv = true;
|
||||
# };
|
||||
#
|
||||
# # Multiple users on the same machine, no dev-env:
|
||||
# lab-shared = mkSystem "lab-shared" {
|
||||
# user = "padreug";
|
||||
# };
|
||||
# };
|
||||
# }
|
||||
#
|
||||
# Differences from mitchellh's version:
|
||||
#
|
||||
# - NixOS only (no darwin, no WSL — we don't need those right now and
|
||||
# the dispatch is easy to add later if we do).
|
||||
# - dev-env module is opt-in; not every host wants it.
|
||||
# - `modules` parameter lets a host inject extra modules without
|
||||
# creating a wrapper file.
|
||||
# - Uses specialArgs (not _module.args inside a module) so the values
|
||||
# are visible to imported file paths, which is required for things
|
||||
# like `(let path = currentSystemName; in ./hosts/${path})`.
|
||||
|
||||
{
|
||||
nixpkgs,
|
||||
overlays ? [ ],
|
||||
inputs,
|
||||
}:
|
||||
|
||||
name:
|
||||
{
|
||||
system ? "x86_64-linux",
|
||||
user,
|
||||
devEnv ? false,
|
||||
modules ? [ ],
|
||||
# Extra args merged into the system-level specialArgs. Used by hosts
|
||||
# whose configuration.nix expects values beyond the defaults (e.g.
|
||||
# omni's configuration.nix takes `settings` from settings.nix).
|
||||
extraSpecialArgs ? { },
|
||||
# Same, for home-manager.extraSpecialArgs.
|
||||
extraHmArgs ? { },
|
||||
}:
|
||||
|
||||
let
|
||||
# Resolve the host's config file. Prefer `hosts/<name>/default.nix`
|
||||
# (lets a host have its own subdirectory for hardware files etc.),
|
||||
# fall back to a flat `hosts/<name>.nix`.
|
||||
hostDir = ../hosts/${name};
|
||||
hostFile = ../hosts + "/${name}.nix";
|
||||
hostConfig =
|
||||
if builtins.pathExists hostDir then
|
||||
hostDir
|
||||
else if builtins.pathExists hostFile then
|
||||
hostFile
|
||||
else
|
||||
throw "mksystem: no host config for '${name}' (looked at ${toString hostDir} and ${toString hostFile})";
|
||||
|
||||
userNixosConfig = ../users/${user}/nixos.nix;
|
||||
userHMConfig = ../users/${user}/home-manager.nix;
|
||||
|
||||
hasUserNixosConfig = builtins.pathExists userNixosConfig;
|
||||
hasUserHMConfig = builtins.pathExists userHMConfig;
|
||||
in
|
||||
|
||||
nixpkgs.lib.nixosSystem {
|
||||
# specialArgs flow into every module's function signature AND can be
|
||||
# used in `imports = [ ... ]` paths. _module.args cannot, which is
|
||||
# why we don't use it for these.
|
||||
specialArgs = {
|
||||
inherit inputs;
|
||||
currentSystemName = name;
|
||||
currentSystemUser = user;
|
||||
}
|
||||
// extraSpecialArgs;
|
||||
|
||||
modules = [
|
||||
# Apply overlays first so subsequent modules see our pinned packages.
|
||||
{ nixpkgs.hostPlatform = system; }
|
||||
{ nixpkgs.overlays = overlays; }
|
||||
{ nixpkgs.config.allowUnfree = true; }
|
||||
|
||||
# Per-host configuration.
|
||||
hostConfig
|
||||
]
|
||||
# Per-user system-level config (account, shell, sudo) — only if the
|
||||
# user file exists. Skipping silently is fine; some hosts share users
|
||||
# defined elsewhere (e.g. omni's users.nix).
|
||||
++ nixpkgs.lib.optional hasUserNixosConfig userNixosConfig
|
||||
++ [
|
||||
# sops-nix — declarative age-encrypted secrets, decrypted at
|
||||
# activation. Module always included; host modules opt in by
|
||||
# declaring `sops.secrets.<name>`. Per-host wiring (defaultSopsFile,
|
||||
# age.keyFile) lives in modules/secrets.nix.
|
||||
inputs.sops-nix.nixosModules.sops
|
||||
]
|
||||
++ [
|
||||
# Opt-in packs — always imported (so the omni.packs.<name>.* option
|
||||
# namespace exists) but inert until `omni.packs.<name>.enable = true`.
|
||||
# Single wire-in point; the ISO bypasses mksystem and so stays
|
||||
# pack-free. See modules/packs/default.nix.
|
||||
../modules/packs
|
||||
]
|
||||
++ [
|
||||
# Home-manager wiring.
|
||||
inputs.home-manager.nixosModules.home-manager
|
||||
{
|
||||
home-manager.useGlobalPkgs = true;
|
||||
home-manager.useUserPackages = true;
|
||||
home-manager.extraSpecialArgs = {
|
||||
inherit inputs;
|
||||
currentSystemName = name;
|
||||
currentSystemUser = user;
|
||||
}
|
||||
// extraHmArgs;
|
||||
}
|
||||
# Pre-create the home-manager activation script's expected
|
||||
# directory tree. See modules/home-manager-bootstrap.nix for
|
||||
# the full rationale and the bugs it fixes. Imported here
|
||||
# rather than inlined so the live ISO (which bypasses
|
||||
# mksystem) can import the same module and get the same
|
||||
# bootstrap.
|
||||
../modules/home-manager-bootstrap.nix
|
||||
]
|
||||
++ nixpkgs.lib.optional hasUserHMConfig {
|
||||
home-manager.users.${user} = import userHMConfig;
|
||||
}
|
||||
# dev-env is opt-in.
|
||||
++ nixpkgs.lib.optional devEnv ../modules/dev-env
|
||||
# Caller-supplied extras.
|
||||
++ modules;
|
||||
}
|
||||
44
lib/overlays.nix
Normal file
44
lib/overlays.nix
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
# Overlays applied uniformly across every host built by mksystem.
|
||||
#
|
||||
# Pin select fast-moving packages to nixpkgs-unstable while keeping
|
||||
# everything else on the stable channel. This is the mitchellh pattern:
|
||||
# stable for stability, unstable for the handful of things that move
|
||||
# faster than we want to wait.
|
||||
#
|
||||
# To use, the flake.nix needs both inputs:
|
||||
#
|
||||
# inputs.nixpkgs.url = "github:nixos/nixpkgs/nixos-25.11";
|
||||
# inputs.nixpkgs-unstable.url = "github:nixos/nixpkgs/nixpkgs-unstable";
|
||||
#
|
||||
# Then:
|
||||
#
|
||||
# overlays = import ./lib/overlays.nix { inherit inputs; };
|
||||
# mkSystem = import ./lib/mksystem.nix { inherit nixpkgs overlays inputs; };
|
||||
|
||||
{ inputs }:
|
||||
|
||||
[
|
||||
# Pinned-to-unstable packages.
|
||||
#
|
||||
# Add a package here when stable is too slow for your needs (claude-code
|
||||
# ships weekly, gh fixes are frequent, direnv has churn). Remove when
|
||||
# stable catches up. Keep the list small — every entry is a divergence
|
||||
# from the rest of the stable closure.
|
||||
(
|
||||
final: prev:
|
||||
let
|
||||
unstable = import inputs.nixpkgs-unstable {
|
||||
system = prev.stdenv.hostPlatform.system;
|
||||
config.allowUnfree = true;
|
||||
};
|
||||
in
|
||||
{
|
||||
claude-code = unstable.claude-code;
|
||||
pi-coding-agent = unstable.pi-coding-agent;
|
||||
gh = unstable.gh;
|
||||
direnv = unstable.direnv;
|
||||
nix-direnv = unstable.nix-direnv;
|
||||
}
|
||||
)
|
||||
|
||||
]
|
||||
Loading…
Add table
Add a link
Reference in a new issue