Skip to content
stubbedevPublic

About

No description, website, or topics provided.

Resources

Stars

5 stars

Watchers

1 watching

Forks

Repository files navigation

STUBBEDEV DOTFILES

Personal Linux dotfiles and utilities, bundled as a Nix flake with an installer and a maintenance front-end. Works on both NixOS and non-NixOS hosts via home-manager.

STRUCTURE

The config is kept self-contained: the repo is symlinked to ~/.stubbe, so removing the repo removes the settings with it.

One file per aspect, and each aspect owns everything about itself — its packages, its config files, its systemd units, its activation steps, and both its NixOS and its home-manager half. There is no packages/ bag, no files/ bag and no activation/ bag to keep in sync: to change how mail works you edit modules/mail.nix, and that is the whole story.

.stubbe/
├── flake.nix              # inputs; outputs are `import-tree ./modules`
├── modules/
│   ├── core/              # the foundation (see CONVENTIONS below)
│   ├── hosts/             # host definitions, one file each
│   ├── dev/               # flake checks, lint, `nix fmt`
│   ├── scripts/           # the `hm` front-end, launchers, clip, ISO burner
│   ├── ai/, browsers/     # aspects big enough to want a directory
│   └── <aspect>.nix       # mail, shell, lys-wm, lys-shell, power, storage, …
├── bin/                   # ONLY the pre-Nix bootstraps (stb-install*)
├── src/                   # the few real files: the nvim live-edit
│                          # tree, aerc stylesets, wallpapers
├── certs/                 # the srv root CA (public cert); seeded into the
│                          # system trust store at build time
└── secrets/               # sops-encrypted, keyed per machine in .sops.yaml

Every config file and script is inline Nix inside its aspect module. Scripts become PATH bins through pkgs.stubbe.bashApp (build-time shell-lsp check), pkgs.stubbe.zshApp (build-time zsh -n), or pkgs.stubbe.shellScript / shellScriptBin for scripts that must keep plain (non-set -euo pipefail) semantics. bin/stb-install runs from the checkout — it bootstraps Nix and home-manager on a fresh host.

CONVENTIONS

  1. One file, one aspect, both classes. Every file under modules/ registers under flake.modules.homeManager.<aspect> and/or flake.modules.nixos.<aspect>. Values shared between the two halves are let-bound at the top of the file, which is what stops a NixOS module and its non-NixOS activation from drifting apart. Hosts import a whole class with builtins.attrValues; nothing references a module by name.

  2. No opt-outs. Every .nix file under modules/ is auto-loaded by import-tree and must be a flake-parts module. There are no underscore-prefixed exceptions.

  3. Three layers of shared code, and no fourth.

    • stubbe.lib.* (modules/core/lib/) — pure data and pure functions: colors, theme, newtabUrl, cache, the hm command catalogue, managedBy. Needs nothing; mirrored as flake.lib.
    • pkgs.stubbe.* (modules/core/pkgs/) — every builder that needs pkgs: secret, bashApp, zshApp, shellScript, gen, gl, check, and the setup.* script fragments. Re-exports all of stubbe.lib, and is reachable from any module of any class because it rides on pkgs.
    • config.stubbe.* — options for anything derived from the evaluated configuration: paths, gfx, setup, mutable, userFeatures.

    There is no specialArgs and no extraSpecialArgs anywhere. A module that needs a flake input resolves it at flake-parts level, where inputs is already in scope. This is what makes every aspect movable between the two targets without rewiring.

  4. Feature gates and the platform split. Behaviour toggles are features.* options (modules/core/features.nix), gated with lib.mkIf config.features.<x>. NixOS aspects gate on config.stubbe.userFeatures.<x>, the same flags resolved once from the primary user. On NixOS the declarative half owns system state; on any other distro the same aspect's stubbe.setup.<name>.privileged activation writes the equivalent files into /etc, and gates itself off on NixOS.

  5. Activation steps. stubbe.setup.<name> (modules/core/setup.nix) is the one way to run imperative work at switch time. The attribute name is the DAG node name; privileged = true adds the shared sudo-prompt scaffolding, a content-hash lock so an unchanged step costs nothing, and the NixOS gate.

  6. Mutable files. xdg.configFile / home.file — read-only store symlinks — are the default. stubbe.mutable.<path> (modules/core/mutable.nix) is for the two cases that cannot be: link (point at the live checkout so an edit needs no rebuild) and copy (the app rewrites the file, so re-assert ours each switch).

  7. Everything is Nix. Config is structured Nix data rendered through lib.generators / pkgs.formats where a format exists (INI, TOML, YAML, JSON), and inline strings where none does — so the Catppuccin palette exists once, in modules/core/lib/palette.nix, and flows into every themed surface by interpolation. The only real files left under src/ are the ones that must be files: the nvim live-edit tree (stubbe.mutable link), binary wallpapers, and the sops secrets.

INSTALLATION

git clone --depth 1 https://github.com/stubbedev/dotfiles.git
cd dotfiles && ./bin/stb-install

The installer asks once for confirmation, then does everything. Day-to-day rebuilds then run through hm.

APPLYING THE CONFIG

The flake lives at the repo root. Apply with:

hm switch --flake "path:$HOME/.stubbe"

Or directly with home-manager:

home-manager switch --flake .#stubbe

NIXOS HOSTS

modules/hosts/ holds one file per machine, each a handful of host facts:

Host Hardware Disk
desktop NVIDIA btrfs, persistent root
laptop ThinkPad X1 Carbon (battery) LUKS2 + btrfs, root rolled back on every boot

The attribute name doubles as the machine's LAN name (desktop.local, laptop.local), and the facts a host sets (host.battery, host.graphicsNvidia, …) reach its home-manager half unchanged.

The disk layout is derived from the host flags in config.stubbe.storage (modules/storage.nix), which both the mounts and the installer read:

  • host.luks puts the btrfs volume in a LUKS2 container, unlocked by passphrase in the initrd. TPM2 unlock can be added later without reinstalling: turn on Secure Boot, then systemd-cryptenroll --tpm2-device=auto the data partition.
  • host.impermanent rolls the root subvolume back to an empty snapshot on every boot. /var lives on the root then, so only what modules/impermanence.nix persists under /persist survives: the flake checkout, logs, network, bluetooth, fingerprints, docker, … /home and /nix are their own subvolumes and unaffected. Users are immutable on such a host; change the password by writing a new hash to /persist/passwords/<user>.
  • host.secureBoot swaps systemd-boot for lanzaboote; enroll keys with sbctl first.

INSTALLING NIXOS

Build a bootable installer ISO:

nix build .#installer-iso --impure
# Output: ./result/iso/*.iso — flash to a USB stick.

Boot the live USB on the target, log in as root, and run:

stb-install-nixos

It asks which host to install, lays the disk out from that host's configuration, runs nixos-install, and clones the repo to /etc/nixos/dotfiles. After first boot, trust the new host key so system secrets decrypt: the installer prints the exact hm trust command.

MOVING A MACHINE

Your repositories move across a reinstall without re-cloning, mirrored to another machine over ssh (or to a local ext4/btrfs drive):

stb-migrate backup desktop.local:migrate    # before wiping; rerun to send only changes
stb-migrate restore desktop.local:migrate   # after the reinstall

backup mirrors ~/git, ~/.ssh and ~/.gnupg, everything included, into <dest>/<hostname>/. restore copies it back and never overwrites a file that already exists. The srv proxies and redirects are declared in modules/srv.nix, and its CA key is held in sops, so srv rebuilds itself on the first hm switch.

Wallpaper preview

About

No description, website, or topics provided.

Resources

Stars

5 stars

Watchers

1 watching

Forks

Releases

Packages

Used by

Contributors

Languages