daniil-bergandClaude Opus 5 24b940810e feat(nvim): prompt to save on <leader>Q instead of aborting
`:qa` fails with E37 when any buffer is modified, leaving the quit dead-ended.
`:confirm qa` asks Save/Discard/Cancel per modified buffer, which neither
strands the user nor writes unintended edits the way `:wqa` would.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015D4NsszUG7hy9ghKZ4nfhm
2026-09-15 12:56:55 +02:00
2026-07-05 15:40:35 +02:00

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 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 (baseline + your nixpkgs) + 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:

{
  inputs = {
    # You own nixpkgs, so your update cadence is yours — the baseline modules
    # build against the versions you pin here.
    nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
    home-manager.url = "github:nix-community/home-manager";
    home-manager.inputs.nixpkgs.follows = "nixpkgs";

    baseline.url = "github:<owner>/<repo>";
    baseline.inputs.nixpkgs.follows = "nixpkgs";        # baseline builds against YOUR nixpkgs
    baseline.inputs.home-manager.follows = "home-manager";
  };

  outputs = inputs@{ self, nixpkgs, baseline, home-manager, ... }: {
    nixosConfigurations.myhost = nixpkgs.lib.nixosSystem {
      system = "x86_64-linux";
      modules = [
        baseline.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 = [
            baseline.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
          ];
        }
      ];
    };
  };
}

This repo ships modules, not pinned packages: they build against the nixpkgs you declare above, so you decide when packages move. Quickstart alternative: drop your own nixpkgs and write nixpkgs.follows = "baseline/nixpkgs" to pin to this repo's tested versions instead — one less thing to think about, but then your update cadence is whatever this repo pins, not the reverse.

Your machine list, hostnames, and any private specifics stay in your flake — you pull only the generic modules from here.

Updating (day-to-day)

Every package version comes from the nixpkgs you declare — including the packages this repo's own modules install, since they build against your nixpkgs via follows, not against anything this repo pins. So the whole upgrade happens in your flake; you never touch this repo to move packages, even the ones it declares:

nix flake update                                 # bump every input to newest
sudo nixos-rebuild switch --flake .#myhost       # build + activate

nix flake update advances nixpkgs to the newest commit on the branch you pinned (e.g. nixos-unstable or nixos-25.11) — that is what upgrades your packages. home-manager and baseline follow your nixpkgs, so they move in lockstep with no version skew. To move one input at a time, name it: nix flake update nixpkgs bumps only packages; nix flake update baseline pulls the latest modules from this repo (new features/fixes) without changing any package version. These are independent knobs — routine upgrades need only the nixpkgs bump.

A release jump (e.g. nixos-25.11nixos-26.05) is not a plain update: edit the branch in the nixpkgs and home-manager URLs in your flake.nix, then update and rebuild.

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:

    # 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:

    local.texlive.package = pkgs.texlive.withPackages (ps: [ ps.scheme-full ]);
    

    A few local.* options exist precisely because a module pins a package to a nixpkgs other than the one you declare (a deliberate freeze that would otherwise reach you regardless of your own pin); the option is how you pull it back onto your nixpkgs.

  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.

S
Description
No description provided
Readme
893 KiB
Languages
Nix 99.4%
Python 0.6%