Files
chiasson-nix/docs/conventions.md
T

6.8 KiB

Conventions

How the flake is wired

flake.nix runs import-tree on ./modules with a few extra filters: skip /package/, /packages/, and dms/home-manager/ (callPackage noise + DMS HM colocation). Don't add a global /home-manager/ filter — modules/ssh/home-manager/ needs to load.

Every scanned .nix should be a flake fragment:

{ self, inputs, ... }: {
  flake.nixosModules.systemFoo = { config, lib, pkgs, ... }: { /* … */ };
}

Don't define the same flake.nixosModules.foo in two files — merge order isn't something to bet on.

Outputs I actually use: nixosConfigurations.*, nixosModules.*, homeManagerModules.*, lib.*, packages.*, navi / naviHive. modules/parts.nix declares supported systems and the flake.lib / flake.homeManagerModules option slots.

Option namespaces

Project options live under chiasson.* only:

Prefix For
chiasson.system.* Machine policy — docker, flatpak, audio, gaming, deploy builder, …
chiasson.desktop.* GUI — compositors, DMS, wallpapers, display manager
chiasson.home.* Home Manager toggles (module exports are still wisdom*)
chiasson.users.* Catalog, enabled, hostOverrides, extraModules
chiasson.ssh.* SSH inventory

Leave upstream services.*, networking.*, home.*, etc. alone.

Module shape

NixOS leaf — camelCase export, usually prefixed (systemDocker, desktopNiri):

{ ... }: {
  flake.nixosModules.systemSomething = { config, lib, pkgs, ... }:
  let cfg = config.chiasson.system.something;
  in {
    options.chiasson.system.something.enable = lib.mkEnableOption "…";
    config = lib.mkIf cfg.enable { /* … */ };
  };
}

Aggregates: nixosModules.system and nixosModules.desktop import their leaves. Host configs import those stacks and set options — they shouldn't reimplement whole subsystems.

Home — files under modules/wisdom/. Baseline is homeManagerModules.wisdom (chiasson.home.enable, wired via chiasson.desktop.homeManager.bundleWisdom). Other wisdom* slices auto-wire once per user via lib.wisdomCatalogExtraModules self (modules/lib/wisdom-catalog.nix); hosts only set matching chiasson.home.*.enable toggles — no re-import in home.nix.

User apps / dotfiles → wisdom. Daemons, firewall, kernel → NixOS. Sometimes both (LocalSend: HM installs, systemLocalsend opens the firewall).

Odd exports

  • "client-services" — shared setup for laptops/tablets/desktops (not the VMs). Turns on Bluetooth, lets Navi log in as builder to update the machine, enables printing and mounting USB drives, and sets SSH to password. Used on t2mbp, 14900k, ideapad, uConsole. Skipped on nix-server and r5500.
  • systemUconsoleKernelBuilder — cross-build the uConsole kernel on x86_64, not for running on the Pi.
  • systemFlatpak — allowlist sync; skips heavy flatpak update when lists unchanged (runHeavyMaintenanceEverySwitch).

Desktop notes

  • chiasson.desktop.displayManager.variant: sddm vs dankgreeter (DMS + Hyprland/Niri tends toward DankGreeter).
  • desktopWallpapers copies inputs.wallpapers into the store; override chiasson.desktop.wallpapers.source if needed.

Users

User definitions live in usersCatalogDefaults (modules/system/users/catalog-default.nix) — olivier, server, builder, etc. Pick who exists on a host with chiasson.users.enabled.

Passwords aren't in the repo. They're in secrets/secrets.yaml (encrypted with sops). Each host that has olivier must declare that secret and set neededForUsers = true; sops-nix decrypts it at boot, and the catalog points hashedPasswordFile at that file. That's why the catalog is a proper module instead of a static list — it needs config.sops.secrets.… at eval time.

On a host:

# configuration.nix — machine policy
chiasson.users.enabled = [ "olivier" ];
chiasson.users.hostOverrides.<name> = { /* optional */ };

Desktop hosts also have home.nix exporting flake.nixosModules.<host>Home, wired from default.nix alongside *Configuration:

# default.nix
modules = [
  self.nixosModules."14900kConfiguration"
  self.nixosModules."14900kHome"
];

# home.nix — flake fragment, per-host `chiasson.home.*` toggles
{ self, inputs, ... }: {
  flake.nixosModules."14900kHome" = { self, pkgs, ... }: {
    imports = [ self.nixosModules.desktopHomeBase ];
    chiasson.users.extraModules.olivier = [
      {
        chiasson.home.browsers.edge.enable = true;
        # …
      }
    ];
  };
}

flake.nixosModules.desktopHomeBase expands lib.wisdomCatalogExtraModules plus shared desktop toggles. Host *Home modules append per-host chiasson.home overrides (and rare inline home.packages blocks). chiasson.users.extraModules concatenates lists from multiple modules (base + host), so both can set the same user key.

usersHomeIntegration turns that into users.users + HM. Don't hand-roll catalog users unless you're changing the users module itself.

SSH: sshInbound on NixOS, outbound/rbw under modules/ssh/home-manager/.

Adding things

New NixOS leaf: export flake.nixosModules.whatever, wire from system/default.nix or desktop/default.nix if it's global, or only from a host configuration.nix if it's not. nix flake check. Git-add new paths if eval uses the git tree.

New HM slice: add modules/wisdom/.../foo.nix exporting flake.homeManagerModules.wisdomFoo (import-tree picks it up; wisdomCatalogExtraModules includes every wisdom* export except wisdom / wisdomShellBash). Gate packages on chiasson.home.*.enable, set mkDefault true in desktop-home-base.nix if shared, or enable = true in a host home.nix. Upstream HM deps stay imported unconditionally — use mkIf on cfg.enable for config (never config-dependent imports; that recurses).

Derivations: let inside a fragment, or flake.packages / flake.lib — not a bare mkDerivation file import-tree will try to load.

New host: hosts/<name>/default.nix with nixosSystem listing *Configuration (+ *Home for desktops), configuration.nix exporting *Configuration, hardware + _private/ as needed. Desktop/laptop hosts also get home.nix exporting *Home (import self.nixosModules.desktopHomeBase unless it's a special case). Register in modules/deploy/navi.nix if it should be in the fleet.

When editing

  • nix flake check after touching modules/.
  • Stage/commit new files if the flake is read from git.
  • Small diffs; mkEnableOption + mkIf for toggles.
  • Cross-module deps: assertions or mkDefault, mention it in the option description.
  • New flake inputs in flake.nix with follows where versions should track nixpkgs.
  • client-services SSH defaults are for my LAN — don't copy to anything internet-facing without tightening.
  • If I'll forget the behavior in six months, update these docs in the same change.