New `local.hyprland.workspaceRules` option binds workspaces to monitor connectors so each has a home screen; a consumer sets it from its own host config (empty by default). Soft binding — an absent monitor's workspaces fall back to an active one, so a laptop-only session still works. `$mod+o` / `$mod SHIFT+o` focus and move the current workspace to the other monitor. When rules are set, an `exec-once` nudges a single-monitor session to workspace 1 rather than a support monitor's high default. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
NixOS + home-manager flake
A flake-based NixOS and home-manager configuration: a set of reusable modules plus a ready-to-run example host that assembles them. Use it either way:
- as a starting template — clone, swap in your hardware, rebuild; or
- as modules — import them into your own (private) flake.
Quick start (template)
nix flake init -t github:<owner>/<repo> # or: git clone …
# generate hardware config for THIS machine (the one file you must replace):
sudo nixos-generate-config --show-hardware-config > hosts/example/hardware-configuration.nix
# set your hostName + username in hosts/example/default.nix, then:
sudo nixos-rebuild switch --flake .#example
nixosConfigurations.example is a real, buildable machine assembled from the modules in
modules/. It doubles as living documentation: it shows exactly how the modules wire
together, so there's nothing to reverse-engineer. The only genuinely machine-specific file
is hardware-configuration.nix (NixOS generates it); everything else works from defaults
you can tweak.
Import the modules into your own flake
Add this repo as a flake input and import its modules from your own configuration:
{
inputs.config.url = "github:<owner>/<repo>";
# …
outputs = { nixpkgs, config, home-manager, ... }: {
nixosConfigurations.myhost = nixpkgs.lib.nixosSystem {
modules = [
config.nixosModules.default
./hosts/myhost # your hardware + hostname
home-manager.nixosModules.home-manager
{ home-manager.users.me.imports = [ config.homeModules.default ]; }
];
};
};
}
Your machine list, hostnames, and any private specifics stay in your flake — you pull only the generic modules from here.
Architecture: three layers
Kept apart on purpose. When adding config, decide which layer it belongs to:
- Modules — generic, public (this repo). Reusable building blocks under
modules/, exposed asnixosModules.*/homeModules.*. Anything machine- or user-specific is a module option with a sane default — never hard-code personal values into a module. - Inventory — topology, private (your flake). The actual machines:
nixosConfigurations.<host>, per-hosthosts/<host>/(hardware, hostname), and topology-revealing config (SSH hosts, Syncthing peers, internal IPs). This is what you deploy from; it imports the modules above. Publish the modules, keep the inventory in a private repo. Theexamplehost here is a placeholder-filled stand-in for it. - Secrets — neither repo. Private keys, tokens, passwords never enter any repo.
Provide them as runtime files (
0600, out-of-band) or via a secrets manager that decrypts to a runtime path; nix references only the path.
Layout
flake.nix # inputs + outputs (nixosModules, homeModules, example host, devShells)
modules/ # the reusable library
hosts/example/ # the template host (placeholder hardware-configuration.nix)
Shared *.nix / *.lock live at the top level; per-host files under hosts/<host>/.
Chasing a shutdown/boot hang? modules/shutdown-debug.nix exposes local.shutdownDebug.*
(verbose systemd logging to kmsg, a tty9 debug shell, a shortened stop-timeout) — see its
header comment for how to read the evidence.