Full reference for the wagounix flake — repo structure, module wiring, adding packages/hosts/settings, dev workflow, and Nix language patterns
wagounix/
├── flake.nix # All inputs, darwinConfigurations, nixosConfigurations, checks, devShell
├── flake.lock # Pinned dependency versions
├── .mise.toml # Auto-activates nix develop on cd (installs git hooks)
│
├── hosts/
│ ├── common/ # Cross-platform modules
│ │ ├── default.nix # Imports packages, fonts, users
│ │ ├── packages.nix # Cross-platform CLI packages (all machines)
│ │ ├── fonts.nix # Cross-platform fonts (all machines)
│ │ └── users.nix # Cross-platform user config (all machines)
│ ├── darwin/ # macOS platform base
│ │ ├── default.nix # Imports configuration, homebrew, icons, packages, settings
│ │ ├── configuration.nix # nix-darwin system config (stateVersion, PAM Touch ID)
│ │ ├── homebrew.nix # Common Homebrew brews, casks, taps
│ │ ├── icons.nix # Custom macOS app icons
│ │ ├── packages.nix # Darwin-only nix packages (cocoapods, pinentry_mac, etc.)
│ │ ├── icons/ # .icns icon files
│ │ ├── settings/ # macOS system defaults
│ │ │ ├── default.nix # Imports all settings modules
│ │ │ ├── dock.nix
│ │ │ ├── finder.nix
│ │ │ ├── keyboard.nix
│ │ │ └── ...
│ │ ├── personal/ # Personal Mac layer
│ │ │ ├── default.nix # Imports dock, packages, homebrew
│ │ │ ├── dock.nix # Personal dock apps
│ │ │ ├── packages.nix # Personal nix packages (android-tools, mas)
│ │ │ ├── homebrew.nix # Personal casks (Steam, Ankama, etc.) + masApps
│ │ │ ├── wagou/ # New personal Mac (aarch64-darwin)
│ │ │ │ ├── default.nix
│ │ │ │ ├── variables.nix
│ │ │ │ ├── packages.nix # opencode
│ │ │ │ └── homebrew.nix # docker-desktop
│ │ │ └── wagou-old/ # Old Intel Mac (x86_64-darwin)
│ │ │ ├── default.nix
│ │ │ └── variables.nix
│ │ └── work/ # Work Mac layer
│ │ ├── default.nix # Imports dock, packages, homebrew
│ │ ├── dock.nix # Work dock apps (Outlook, Teams, etc.)
│ │ ├── packages.nix # Work nix packages (opencode)
│ │ ├── homebrew.nix # Work casks (docker-desktop)
│ │ ├── sap/ # SAP Mac (legacy — remove when returned)
│ │ │ ├── default.nix
│ │ │ ├── variables.nix
│ │ │ ├── packages.nix # databricks-cli
│ │ │ └── homebrew.nix # hai tap, btp, figma, etc.
│ │ └── pro/ # New work Mac (aarch64-darwin)
│ │ ├── default.nix
│ │ └── variables.nix
│ └── nixos/ # NixOS platform base
│ ├── default.nix # Imports configuration
│ ├── configuration.nix # NixOS system config (bootloader, networking, docker)
│ └── homeserver/ # Home server (x86_64-linux)
│ ├── default.nix
│ ├── variables.nix
│ ├── hardware.nix # Auto-generated (replace with real one from server)
│ └── services.nix # Server services
│
└── .github/workflows/check.yml # CI: lint + build darwin + build NixOS
Each configuration loads modules in order:
hosts/common (packages, fonts, users)hosts/darwin or hosts/nixoshosts/darwin/personal or hosts/darwin/workhosts/<platform>/<layer>/<host>In flake.nix, this is expressed as:
commonModules = [ ./hosts/common ];
# Darwin host
sap = nix-darwin.lib.darwinSystem {
modules = [
./hosts/common # common
./hosts/darwin # platform
./hosts/darwin/work # layer
./hosts/darwin/work/sap # host
];
specialArgs = { inherit inputs; host = import ./hosts/darwin/work/sap/variables.nix; };
};
# NixOS host
homeserver = nixpkgs.lib.nixosSystem {
modules = [
./hosts/common # common
./hosts/nixos # platform
./hosts/nixos/homeserver # host
];
specialArgs = { inherit inputs; host = import ./hosts/nixos/homeserver/variables.nix; };
};
Nix merges lists from all modules automatically — packages from each layer are combined, not replaced.
Each host has a variables.nix that exports a plain attribute set (not a module):
rec {
username = "wagou";
homeDir = "/Users/${username}"; # /home/${username} for NixOS
restricted_app_dir = "/Applications"; # darwin only
enableRosetta = false; # darwin only
hostname = "homeserver"; # NixOS only
}
These are passed via specialArgs and available in all modules as { host, ... }:.
Edit hosts/common/packages.nix:
environment.systemPackages = with pkgs; [ ... new-package ... ];
Edit hosts/darwin/packages.nix.
Edit the appropriate packages.nix under hosts/darwin/<layer>/ or hosts/darwin/<layer>/<host>/.
Edit the appropriate homebrew.nix and add to the casks list.
For custom install path: { name = "app"; args = { appdir = host.restricted_app_dir; }; }
Edit the appropriate homebrew.nix and add to the brews list.
Add to masApps in the appropriate homebrew.nix:
masApps = { "App Name" = 123456789; };
personal or work)hosts/darwin/<layer>/<hostname>/variables.nix:
rec {
username = "myuser";
homeDir = "/Users/${username}";
restricted_app_dir = "/Applications";
enableRosetta = false;
}
hosts/darwin/<layer>/<hostname>/default.nix:
_: { }
darwinConfigurations.<hostname> entry in flake.nix:
<hostname> = nix-darwin.lib.darwinSystem {
system = "aarch64-darwin";
modules = commonModules ++ [
./hosts/darwin
./hosts/darwin/<layer>
./hosts/darwin/<layer>/<hostname>
];
specialArgs = {
inherit inputs;
host = import ./hosts/darwin/<layer>/<hostname>/variables.nix;
};
};
hosts/nixos/<hostname>/variables.nix:
rec {
username = "myuser";
homeDir = "/home/${username}";
hostname = "<hostname>";
}
hosts/nixos/<hostname>/default.nix with imports for hardware and serviceshosts/nixos/<hostname>/hardware.nix (from nixos-generate-config on the target machine)hosts/nixos/<hostname>/services.nix for host-specific servicesnixosConfigurations.<hostname> entry in flake.nixhosts/darwin/settings/<category>.nix:
_: {
system.defaults.<namespace> = {
option = value;
};
}
hosts/darwin/settings/default.nixCommon system.defaults namespaces: dock, finder, NSGlobalDomain, trackpad, CustomUserPreferences, menuExtraClock, screencapture, screensaver, spaces, controlcenter, magicmouse, SoftwareUpdate.
.icns file in hosts/darwin/icons/hosts/darwin/icons.nix:
{ path = "/Applications/AppName.app"; icon = ./icons/appname.icns; }
flake.nix:
homebrew-newtap = { url = "github:owner/homebrew-repo"; flake = false; };
nix-homebrew.taps in the appropriate homebrew.nix:
nix-homebrew.taps = { "owner/homebrew-repo" = inputs.homebrew-newtap; };
# Attribute set
{ key = "value"; nested = { a = 1; }; }
# List
[ "one" "two" "three" ]
# with expression (bring attrs into scope)
environment.systemPackages = with pkgs; [ git vim tmux ];
# String interpolation
home = "${host.homeDir}/Downloads";
# rec — self-referencing attrset
rec { username = "me"; homeDir = "/Users/${username}"; }
# inherit — shorthand for x = x
specialArgs = { inherit inputs; };
# Function with destructured attrset argument
{ pkgs, lib, ... }:
{
# module body
}
# Unused arguments
_: { }
environment.systemPackages)lib.mkForce to override, lib.mkDefault for low-priority defaultslib.mkIf <condition> { ... } for conditional configurationHooks auto-install when entering the dev shell. On every commit:
Full builds are verified by CI after push.
nix develop # manual entry
# or just cd into the repo — mise auto-activates via .mise.toml
nix flake check # runs all checks + builds
| Command | What it does |
|---|---|
darwin-rebuild switch --flake .#<profile> | Build and activate macOS config |
darwin-rebuild build --flake .#<profile> | Build without activating (test) |
sudo nixos-rebuild switch --flake .#<profile> | Build and activate NixOS config |
nix search nixpkgs <name> | Search for a package |
nix flake update | Update all inputs |
nix flake update <input> | Update a single input |
nix develop | Enter dev shell (installs hooks) |
nix flake check | Run all checks |
~/.config/wagounix/ — this is the source of truthbuild first to test, then switch to activatenix search nixpkgs <name>onActivation.cleanup = "uninstall" — removing a cask/brew from config WILL uninstall itmutableTaps = false — add new taps as flake inputsnix.enable = false in darwin config)system.stateVersion must match the version at install time — never change ithardware.nix is auto-generated — replace placeholder with real one from the server