Skip to content
Ota edited this page Oct 11, 2026 · 3 revisions

The Directories

  • You'll be shown directories within the project to give you a small but valuable/usable information to get started on where you should actually make your changes.
    alice
    ├── flake.nix
    ├── modules
    │   ├── systems
    │   ├── common
    │   │   └── home
    │   ├── gaming
    │   ├── hardware
    │   │   ├── drivers
    │   │   │   └── framework
    │   │   ├── profiles
    │   │   └── settings
    │   │       └── host-predetermined
    │   ├── home
    │   │   ├── alice
    │   │   │   ├── configurations
    │   │   │   ├── desktop
    │   │   │   └── programs
    │   │   └── konoe
    │   │       ├── desktop
    │   │       └── programs
    │   ├── hosts
    │   │   ├── serpentine
    │   │   │   └── settings
    │   │   └── tanuki
    │   │       └── settings
    │   ├── cursor-themes.nix
    │   └── parts.nix
    ├── scripts
    ├── .githooks
    └── .github
        └── workflows
Path What goes there
modules/systems Modules for systems that do not run NixOS. import-tree skips this directory.
modules/common NixOS modules that many hosts share: boot, fonts, nix settings, services, virtualisation.
modules/common/home Home Manager modules that many hosts share (fastfetch).
modules/gaming Gaming settings and packages.
modules/hardware/drivers Generic driver modules with options. They know nothing about a host.
modules/hardware/profiles Hardware profiles made from hardware-configuration.nix: asustuf, noctHardware, qemuHardware.
modules/hardware/settings Presets that set values on a driver. host-predetermined holds presets for one machine model.
modules/home/alice Home Manager modules for user alice. Niri, DankMaterialShell and mango are configured here.
modules/home/konoe Home Manager modules for user konoe. Niri and Noctalia are configured here.
modules/hosts One directory for each host, plus default.nix (host registration) and dev-shell.nix (VM testing).
scripts Settings sync scripts and the git hook installer.
  • Most important files of this config are none other than parts.nix and flake.nix.
  • flake.nix only holds the inputs and one call: mkFlake with import-tree ./modules. Every .nix file under modules becomes a flake-parts module.
  • import-tree ignores any path that contains an underscore as the first character of that name.
  • parts.nix declares the namespaces. Here is the shape of it:
    {lib, ...}: {
      options = {
        flake.homeModules = lib.mkOption {
          type = lib.types.lazyAttrsOf lib.types.unspecified;
          default = {};
        };
    
        flake.custom = {
          tanuki = lib.mkOption {
            type = lib.types.lazyAttrsOf lib.types.unspecified;
            default = {};
            description = "System-level namespace for Tanuki.";
          };
        };
      };
    }
  • flake.homeModules is a real option, and it is not custom. Everything under flake.custom is a custom namespace. You can make more custom namespaces like this as much as you'd like.
  • parts.nix also sets the supported systems: x86_64-linux, x86_64-darwin, aarch64-linux and aarch64-darwin.
Namespace Source Description
flake.custom.serpentine modules/hosts/serpentine System-level config for Serpentine.
flake.custom.tanuki modules/hosts/tanuki System-level config for Tanuki.
flake.custom.aux-mini none yet Reserved for a future host.
flake.custom.alice modules/home/alice Home Manager modules for user alice.
flake.custom.konoe modules/home/konoe Home Manager modules for user konoe.
flake.custom.commonModules modules/common Shared NixOS modules.
flake.custom.home-common modules/common/home Shared Home Manager modules.
flake.custom.hardwareModules modules/hardware Hardware, driver and preset modules.
flake.custom.system-modules modules/_systems Systems that do not run NixOS.
  • Some older modules still use flake.nixosModules.*: games, gamingSettings, dgreet, mangoWC, lumina-browser-settings, zsh-sys-level and hardwareFramework. New modules go into a flake.custom.* namespace.

Standards - First Part, Reasoning

The way everything is organized could be broken down in these 4 simple questions:

  • Is this a system configuration or a home module?
    • Which host uses this module? (if system: <host>/settings/, or if it's a home module: home/<user>/...)
  • What is this part of?
  • What is it made for? You then decide where the module should be placed, could be in hardware, gaming, common, or anywhere, so as long as your reason is rational. Then it can be easily found or used within the codebase.

Standards - Second Part, Organizing

At some point, you'll come across a conflict in organizing your files, whether if intel-related packages are meant for sharing it between hosts or sending it straight into intel.nix, anything like that.

In that case, there will always be priorities. For example, hardware/drivers/intel.nix holds the generic and reusable logic: option declarations and the actual implementation. It knows nothing about any specific host. Meanwhile hardware/settings/intel.nix imports that driver module and sets the concrete values a host actually needs (generation = "legacy", openclLegacy = true, etc).

Priority order when deciding where something goes:

  1. Reusability: If the module's logic could apply to more than one host, or could vary per host, it belongs in drivers (or the equivalent generic module) as options.
  2. Specificity: Once something is host or use case specific (a fixed value and/or a toggle you're certain about), it goes in settings (or a host's own directory) as a thin config on top of the generic module.
  3. Do not duplicate the same option/value in multiple modules, prefer making a shared/common module instead.
  4. It costs nothing to keep a module generic and unused by only one host today, but it costs a rewrite later if you hardcode and then need it elsewhere. Though, I'm assuming you're pretty aware of what you want to do.

This keeps drivers a stable library of hardware capability, and settings a disposable, per-host decision layer that's cheap to change without touching the underlying module.

Hardware modules today

Module File Options Preset
hardwareModules.hardwareIntel drivers/intel.nix hardware.alice.intel intelSettings (Serpentine)
hardwareModules.hardwareAmd drivers/amd.nix hardware.alice.amd amdSettings (no host uses it yet)
hardwareModules.hardwareNvidia drivers/nvidia.nix hardware.alice.nvidia none yet
hardwareModules.vulkan drivers/vulkan.nix hardware.alice.vulkan imported by intelSettings, amdSettings, asusSettings
nixosModules.hardwareFramework drivers/framework/default.nix hardware.alice.framework none yet
hardwareModules.asusSettings settings/host-predetermined/asus-tuf.nix none Tanuki
hardwareModules.otdSettings settings/otd.nix none Serpentine

See Intel, AMD and Nvidia for the options.

How a host is wired

Each host file modules/hosts/<name>/configuration.nix defines flake.custom.<name>.hostConfig. It has two parts:

  • imports: grouped by section: Inputs, Self, Common, Gaming and Hardware.
  • home-manager.users.<user>.imports: the Home Manager modules of the user. Home Manager runs as a NixOS module.

Every host and user imports the Lumina signature modules (mkHostSignature, mkUserSignature).

Rules for modules

The CodeRabbit review config (.coderabbit.yaml) checks pull requests to test-den against these rules:

  • Every module file exposes its output under a unique key in a flake.custom.* namespace. It does not write to flake.homeModules directly.
  • A NixOS module does not import a Home Manager module, and the reverse. configuration.nix files in a host directory are the exception.
  • lib.mkIf does not go in an imports list.
  • A module closes over self from the outer flake-parts scope.
  • A wrapped package is referenced as self.packages.${pkgs.stdenv.hostPlatform.system}.<name>.
  • flake.nix stays minimal: inputs and mkFlake only.
  • A module does not read Noctalia or DMS files from the Nix store. It refers to them by name or output.
  • scripts/** follow POSIX where possible.

Scripts and automation

File What it does
scripts/sync-dms-settings This dumps the DMS session's current configuration to modules/home/alice/desktop/dms-settings.json, though, this action could be replaced by Lumina CLI commands.
scripts/sync-dms-kdl Copies the DMS Niri color file from ~/.config/niri/dms into the repo. Though... this isn't used much as serpentine mains Mango now as its WM, but it'll soon be replaced by Lumina CLI commands.
scripts/sync-noctalia-kdl Copies ~/.config/niri/noctalia.kdl to modules/home/konoe/desktop/noctalia.kdl. This one is also going to be replaced by Lumina CLI commands soon.
scripts/setup-hooks.sh Sets core.hooksPath to .githooks.
.githooks/pre-commit Runs sync-noctalia-kdl.sh and stages noctalia.kdl before each commit.
.github/workflows/weekly-flake-update.yml Runs nix flake update every Monday at 05:00 UTC. It opens a pull request to test-den from ci/weekly-flake-update.

Clone this wiki locally