Files
nixos-config/README.md
T
daniil-berg 5e1b9332a4 docs(readme): show a realistic private-inventory layout and overrides
The consumer section had only a bare-bones flake snippet. Add an example
private layout (`system/` + `home/` split, `hosts/<host>/`), a fuller
`flake.nix` matching it, and an "Overriding the baseline" section covering
the three mechanisms (neutral default → real value, `local.*` options,
extra modules). Note that structurally only `flake.nix` is required.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-24 16:42:53 +02:00

146 lines
6.5 KiB
Markdown

# 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)
```sh
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 an input and assemble your machines in a private flake. Below is a
**realistic example layout**. Structurally only `flake.nix` is required — every other path
is just one way to organize your config; rename, merge, inline, or drop them freely. The one
bit of *content* a bootable machine can't skip is its `hardware-configuration.nix`
(`nixos-generate-config` output); the `hosts/<host>/` directory is only where this example
keeps it.
```
your-inventory/
├── flake.nix # inputs (pub + follows) + nixosConfigurations.<host>
├── flake.lock
├── system/ # system-level modules
│ ├── regional.nix # time zone / keymap / locale (see Overriding)
│ ├── packages.nix # extra system packages
│ └── tailscale.nix # VPN / network topology
├── home/ # home-manager modules, one file per concern
│ ├── identity.nix # git identity, name/email
│ ├── ssh.nix # SSH hosts (topology — stays private)
│ ├── syncthing.nix # Syncthing peers
│ └── … # personal apps: browser, editor, chat, …
└── hosts/
└── myhost/
├── default.nix # hostname, user account, host-specific system bits
└── hardware-configuration.nix # `nixos-generate-config` output
```
The `flake.nix` that wires it together:
```nix
{
inputs = {
pub.url = "github:<owner>/<repo>";
# Reuse the public flake's pins so versions never drift between the two.
nixpkgs.follows = "pub/nixpkgs";
home-manager.follows = "pub/home-manager";
};
outputs = inputs@{ self, nixpkgs, pub, home-manager, ... }: {
nixosConfigurations.myhost = nixpkgs.lib.nixosSystem {
system = "x86_64-linux";
modules = [
pub.nixosModules.default # generic system baseline
./system/regional.nix # your regional values (see below)
./hosts/myhost # hardware + hostname
home-manager.nixosModules.home-manager
{
home-manager.useGlobalPkgs = true;
home-manager.useUserPackages = true;
# Inject your own inputs into your home modules; the public ones ignore them.
home-manager.extraSpecialArgs = { inherit inputs; };
home-manager.users.me.imports = [
pub.homeModules.default # generic home baseline
./home/identity.nix # your git identity, name/email, …
./home/ssh.nix # your SSH hosts (topology stays private)
# … more personal home modules
];
}
];
};
};
}
```
Your machine list, hostnames, and any private specifics stay in *your* flake — you pull
only the generic modules from here.
## Overriding the baseline
The public modules are a baseline you extend without forking. Three ways to shape them
from your private flake, in rough order of how often you reach for them:
1. **Neutral default → your real value.** Region-agnostic settings ship as `mkDefault`
placeholders (`console.keyMap = "us"`, `time.timeZone = "UTC"`, `en_US` locale). Set the
real ones in a private module — no `mkForce` needed:
```nix
# system/regional.nix
{ time.timeZone = "Europe/Berlin"; console.keyMap = "de"; }
```
2. **`local.*` options.** A module that exposes a knob puts it under the `local.*`
namespace with a default. Override in one line, e.g. a fuller TeX Live:
```nix
local.texlive.package = pkgs.texlive.withPackages (ps: [ ps.scheme-full ]);
```
3. **Extra modules.** Anything with no public counterpart is just another module in the
import lists above — personal apps, SSH/Syncthing topology, secrets wiring.
## Architecture: three layers
Kept apart on purpose. When adding config, decide which layer it belongs to:
1. **Modules — generic, public (this repo).** Reusable building blocks under `modules/`,
exposed as `nixosModules.*` / `homeModules.*`. Anything machine- or user-specific is a
module **option with a sane default** — never hard-code personal values into a module.
2. **Inventory — topology, private (your flake).** The actual machines:
`nixosConfigurations.<host>`, per-host `hosts/<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. The `example` host here is a placeholder-filled stand-in for it.
3. **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.