notfiles

NixOS dotfiles

My declarative NixOS configuration. ## Structure ``` notfiles/ ├── flake.nix # Flake inputs and host definitions ├── hosts/ # Host-specific config (hardware, hostname, etc.) │ ... ├── modules/ # NixOS system-level modules (shared across hosts) │ ... └── home/ # User-level entry point and user-specific config ├── alex/ │ ... └── modules/ # Reusable Home Manager modules ... ``` ## Flake inputs | Input | Purpose | | :---- | :------ | | [`nixpkgs`][nixpkgs] | NixOS 26.05 | | [`home-manager`][home-manager] | User environment management | | [`plasma-manager`][plasma-manager] | Declarative KDE Plasma configuration | | [`nix4vscode`][nix4vscode] | VSCode/VSCodium extension management | | [`globalprotect-openconnect`][globalprotect-openconnect] | VPN client | ## Tasks [`just`][just] runs the routine tasks in this repo. Run it with no arguments to list every recipe: ``` just ``` Most recipes act on a single host. The `host` variable resolves on its own: macOS reads `scutil --get LocalHostName`, Linux uses `hostname`. That value has to match a key under `nixosConfigurations` or `darwinConfigurations` in `flake.nix`. To act on a different machine, override it: ``` just host=whitegrizzly rebuild ``` `rebuild`, `clean`, and `diff` choose `darwin-rebuild` or `nixos-rebuild` from the current OS, so one command covers every machine. Three recipes (`fmt`, `lint`, `diff`) use tools that live in the flake's dev shell rather than a host profile. With direnv the shell loads on entry to the repo (see [Dev shell](#dev-shell)); without it, prefix the command, for example `nix develop -c just lint`. | Recipe | What it does | | :----- | :----------- | | `rebuild` | Build the current host's config and switch to it now | | `diff` | Build the current host's config and show what would change, without switching | | `update` | Update `flake.lock` to the latest inputs | | `clean` | Delete generations older than 7 days, optimize the store, stage the result for next boot | | `fmt` | Format every `.nix` file with `nixfmt` | | `lint` | Run `statix` and `deadnix` over the tree | | `gen-keys` | Generate Ed25519 SSH keys for the named services | | `fetch-iso` | Download the latest NixOS installer ISO into `iso/` | | `make-usb` | Write a bootable installer USB | | `register-host` | Scaffold `hosts//` and add a `flake.nix` entry | | `capture-hardware` | Write the current machine's `hardware.nix` | | `hosts` | List the hosts registered in `flake.nix` | | `docker-creds` | Seed `~/.docker/config.json` and set up a credential store | ## Dev shell Editing the repo (as opposed to running it) calls for a formatter, two linters, and a pair of inspectors: `nixfmt`, `statix`, `deadnix`, `nvd`, and `nix-tree`. They live in `devShells.default` in `flake.nix`, deliberately outside every host's system profile, so they show up only while you work on this repo. A repo-root `.envrc` containing `use flake` loads the shell through [direnv] on entry and drops it on exit. Run `direnv allow` once after cloning. Without direnv, enter it by hand: ``` nix develop ``` Either path puts `just fmt`, `just lint`, and `just diff` in reach. ## Common workflows ### The edit loop Change a module, preview the effect, then switch: ``` $EDITOR home/modules/helix.nix just diff just rebuild ``` `just diff` builds the target system to `/tmp/notfiles-next` and runs `nvd diff` against the running one, so the added, removed, and upgraded packages are visible before anything changes. The switch happens only at `just rebuild`. Before committing, format and lint: ``` just fmt just lint ``` `lint` exits nonzero when `statix` or `deadnix` find something, which makes it a usable pre-commit or CI gate. The first run on an established config tends to surface unused bindings and a few anti-patterns; clear them once and later runs go quiet. ### Staying current ``` just update just diff just rebuild ``` `just update` refreshes every flake input. Read the changes with `just diff` before switching. Reclaim disk now and then: ``` just clean ``` `clean` drops generations older than a week, deduplicates the store, and stages the rebuilt system for the next boot (a plain `switch` on macOS). ### Adding a machine Register the host from any checkout, then capture hardware on the machine itself: ``` just register-host blackbear # scaffolds hosts/blackbear/, edits flake.nix # then, on blackbear: just capture-hardware blackbear # writes hosts/blackbear/hardware.nix just host=blackbear rebuild ``` `just hosts` shows what is already registered. ### Building install media For a fresh NixOS box, fetch an installer image and write it to a USB stick: ``` just fetch-iso just make-usb --iso iso/latest-nixos-graphical-x86_64-linux.iso ``` `fetch-iso` accepts channel and edition overrides, for example `just fetch-iso --channel nixos-unstable --edition minimal`. `make-usb` self-elevates with sudo when it needs to. ### Keys and credentials Generate signing and auth keys, then seed Docker's credential store: ``` just gen-keys just docker-creds ``` `gen-keys` writes one Ed25519 key per service and defaults to the set this repo expects (GitHub, Gradescope, the HPC clusters, and the two Git signing keys). `docker-creds` defaults to a `pass`-backed store and sets up the GPG key behind it; pass `secretservice` to use the desktop keyring instead. [just]: https://github.com/casey/just [direnv]: https://direnv.net/ [nixpkgs]: https://github.com/NixOS/nixpkgs [home-manager]: https://github.com/nix-community/home-manager [plasma-manager]: https://github.com/nix-community/plasma-manager [nix4vscode]: https://github.com/nix-community/nix4vscode [globalprotect-openconnect]: https://github.com/yuezk/GlobalProtect-openconnect