Author SHA1 Message Date
lyrathorpe e5d6b5bc8d chore(secrets): placeholder for the LDAP bind secret
CI / flake (pull_request) Failing after 1m20s
2026-07-06 13:57:30 +01:00
lyrathorpe 5fd42fbdcd docs(secrets): agenix owner workflow 2026-07-06 13:57:30 +01:00
lyrathorpe 2864ef0553 feat(sssd): agenix recipients scaffold 2026-07-06 13:57:29 +01:00
lyrathorpe bac9951995 feat(sssd): SSSD LDAP auth against Authentik outpost 2026-07-06 13:57:28 +01:00
lyrathorpe 8f240c27ba feat(sssd): opt EDaaS out of SSSD 2026-07-06 13:57:28 +01:00
lyrathorpe b1447e6e30 docs: document SSSD/Authentik directory auth and secrets 2026-07-06 13:57:27 +01:00
lyrathorpe 01bda7fe58 feat(sssd): add agenix input and sssd module to baseModules 2026-07-06 13:57:27 +01:00
lyrathorpeandEmma Thorpe c06a57f249 chore: post-refactor cleanups (#50-#53) (#54)
CI / flake (push) Successful in 3m30s
## Summary

Follow-up cleanups from the post-refactor audit (issues #50–#53). All behaviour-preserving except the work-host changes (kube-tmux + Lens removal).

## Changes

- **#51** `refactor(ssh)` — move `services.openssh.enable` + `firewall.allowedTCPPorts = [ 22 ]` into `modules/ssh.nix`; drop the duplicated lines from T400, MacPro31, RPi5.
- **#50** `fix/feat(work)` — load kube-tmux from a pinned `flake = false` input (it is not in nixpkgs) and reference `${inputs.kube-tmux}/kube.tmux` directly, so the status line no longer depends on a manual `$HOME/code/kube-tmux` checkout. (Supersedes the interim file-existence guard.)
- **#52** `chore` — gitignore the untracked `tf-inspect/` scratch project.
- **#53** `chore` — remove the unused Lens package entirely (`pkgs.lens` + its unfree entry; `unfreePackages` is now just `claude-code`), fix the `nil`→`nil_ls` LSP doc, remove the redundant `.editorconfig` block, name the RPi5 Docker subnet in a `let` binding.

## Deferred (from #53, noted in the commit)

- `.gitignore` firmware entry — documented behaviour, low value, left as-is.
- Per-eval `nixpkgs-unstable` overlay import — inherently per-system; no clean single-import hoist.

## Verification

- `nix flake check` passes (treefmt, deadnix, statix, pre-commit, all hosts + Darwin + homeConfigurations).
- Derivation-path diff vs `main`: `lyrathorpe-mbp`, `lyrathorpe-t400`, `lyrathorpe-macpro31`, `lyrathorpe-rpi5` are byte-identical (confirms #51 and the subnet `let` binding change nothing). Only `emmathorpe-edaas` differs — the kube-tmux input (#50) and the Lens removal (#53).

Closes #50, #51, #52, #53.

---------

Co-authored-by: Emma Thorpe <emma.thorpe@citrix.com>
Reviewed-on: #54
2026-06-29 14:09:38 +01:00
lyrathorpeandEmma Thorpe 128deca2e3 refactor(flake): user registry, multi-user hosts, and portable home outputs (#49)
CI / flake (push) Successful in 3m26s
## Summary

Separates user identity (data) from the reusable Nix modules and lets a host declare any number of users, replacing the previous one-user-per-host structure. Also restructures the tree and exposes the home config for use off these hosts.

## Changes

- **User registry** (`users/registry.nix`): per-user identity (name, email, groups, authorized + signing keys) as the single source of truth; no user data hardcoded in modules.
- **Multi-user `mkHost`**: a host declares a `users` set keyed by username; per-user identity is injected into each home config via the `identity` module arg.
- **Restructured layout**: `users/`, `home/`, `modules/`, `hosts/`, `lib/` replace the former `lyrathorpe/` and `system/` trees.
- **Portable outputs**: standalone `homeConfigurations."<user>@<system>"` (the portable subset — shell, git, editor, claude) plus an exported `homeModules` for use on machines not managed by this flake, or as an input to other flakes.
- Docs (`README.md`, `home/README.md`) and `.gitignore` updated for the new paths.

## Fixes

- Closes #46 — shared user module authorized one user's SSH key for every account.
- Closes #47 — git committer identity hardcoded as defaults instead of per-user.
- Closes #48 — EDaaS systemd linger hardcoded to a literal username.

## Verification

- `nix flake check` passes: treefmt, deadnix, statix, pre-commit, and evaluation of all NixOS hosts + Darwin + homeConfigurations.
- Derivation-path comparison vs `main`: `lyrathorpe-mbp` and `emmathorpe-edaas` are byte-identical; `lyrathorpe-t400`, `lyrathorpe-macpro31` and `lyrathorpe-rpi5` differ only by de-duplicating a repeated `authorized_keys` entry (confirmed with nix-diff — no other change).
- Standalone `homeConfigurations."lyrathorpe@x86_64-linux".activationPackage` builds.

## Notes

- `emmathorpe` has no personal authorized key yet (it previously inherited Lyra's key via the bug in #46); the registry entry is intentionally empty — add a real key if SSH login as `emmathorpe` is wanted (moot on the WSL host).
- A two-repo (public dotfiles / private systems) split is deferred by design; this internal restructure is the prerequisite for it.

---------

Co-authored-by: Emma Thorpe <emma.thorpe@citrix.com>
Reviewed-on: #49
2026-06-29 13:06:23 +01:00
lyrathorpe 906fae7e7b Merge pull request 'feat(ssh): add some needed SSH config' (#45) from feat/ssh-updates into main
CI / flake (push) Successful in 3m23s
Reviewed-on: #45
2026-06-29 11:20:36 +01:00
lyrathorpe 1230e39aac feat(ssh): add some needed SSH config
CI / flake (pull_request) Successful in 3m28s
2026-06-29 11:15:40 +01:00
67 changed files with 717 additions and 276 deletions
-6
View File
@@ -8,12 +8,6 @@ indent_size = 2
trim_trailing_whitespace = true trim_trailing_whitespace = true
insert_final_newline = true insert_final_newline = true
[*.{nix,yaml,yml,json,md,sh,toml}]
indent_style = space
indent_size = 2
trim_trailing_whitespace = true
insert_final_newline = true
# Markdown uses trailing whitespace for hard line breaks. # Markdown uses trailing whitespace for hard line breaks.
[*.md] [*.md]
trim_trailing_whitespace = false trim_trailing_whitespace = false
+4 -1
View File
@@ -1,4 +1,7 @@
system/modules/firmware/* modules/firmware/*
# vim swap files # vim swap files
*.swp *.swp
# Local scratch project, not part of this flake.
tf-inspect/
+76 -20
View File
@@ -7,22 +7,78 @@ single flake.
Defined in the host table in [`flake.nix`](./flake.nix): Defined in the host table in [`flake.nix`](./flake.nix):
| Configuration | System | Machine | | Configuration | System | Machine |
| --------------------- | ---------------- | -------------------------------------------------------------------------------------------------------------------- | | --------------------- | ---------------- | ----------------------------------------------------------------------------------------------------------- |
| `lyrathorpe-mbp` | `aarch64-linux` | MacBook Pro (Apple Silicon, Asahi) | | `lyrathorpe-mbp` | `aarch64-linux` | MacBook Pro (Apple Silicon, Asahi) |
| `lyrathorpe-t400` | `x86_64-linux` | ThinkPad T400 — [install notes](./system/machine/T400/README.md) | | `lyrathorpe-t400` | `x86_64-linux` | ThinkPad T400 — [install notes](./hosts/T400/README.md) |
| `lyrathorpe-macpro31` | `x86_64-linux` | Mac Pro 3,1, desktop — [install notes](./system/machine/MacPro31/README.md) | | `lyrathorpe-macpro31` | `x86_64-linux` | Mac Pro 3,1, desktop — [install notes](./hosts/MacPro31/README.md) |
| `emmathorpe-edaas` | `x86_64-linux` | Work WSL box (NixOS-WSL) | | `emmathorpe-edaas` | `x86_64-linux` | Work WSL box (NixOS-WSL) |
| `lyrathorpe-rpi5` | `aarch64-linux` | Raspberry Pi 5 headless server: Docker host + nginx reverse proxy — [install notes](./system/machine/RPi5/README.md) | | `lyrathorpe-rpi5` | `aarch64-linux` | Raspberry Pi 5 headless server: Docker host + nginx reverse proxy — [install notes](./hosts/RPi5/README.md) |
| `lyrathorpe-mac` | `aarch64-darwin` | macOS (nix-darwin) | | `lyrathorpe-mac` | `aarch64-darwin` | macOS (nix-darwin) |
Shared layers: `lyrathorpe/home` (home-manager: shell, git, editor), Shared layers: `home` (home-manager: shell, git, editor),
`system/modules/common-nixos.nix` (all NixOS hosts: fonts, nix-ld, caches), `modules/common-nixos.nix` (all NixOS hosts: fonts, nix-ld, caches),
`system/modules/workstation.nix` (physical graphical hosts: audio, thermald, `modules/workstation.nix` (physical graphical hosts: audio, thermald,
earlyoom, fwupd), `system/modules/laptop.nix` (laptops: Wi-Fi, Bluetooth, power, earlyoom, fwupd), `modules/laptop.nix` (laptops: Wi-Fi, Bluetooth, power,
lid), and `system/modules/ssh.nix` (key-only sshd). The x86 hosts also pull lid), and `modules/ssh.nix` (key-only sshd). The x86 hosts also pull
`nixos-hardware` profiles. `nixos-hardware` profiles.
## Users
Identity is data, kept separate from the reusable modules:
- [`users/registry.nix`](./users/registry.nix) — one entry per user (display
name, email, supplementary groups, authorized + signing keys). This is the
single source of identity; no user data is hardcoded in the modules.
- Each host's table entry declares a `users` set keyed by username; every entry
lists that user's home-module composition (the shared `./home` bundle plus any
per-user modules, e.g. [`users/emmathorpe/work.nix`](./users/emmathorpe/work.nix))
and optional per-host-user system bits such as `linger`.
- `mkHost` builds each account from the registry and injects the matching
identity into that user's home config as the `identity` module arg. A host can
therefore declare any number of users.
### Portable home (off-NixOS / external consumers)
The home config is also exposed for use beyond these hosts:
- `homeConfigurations."<user>@<system>"` — a standalone home-manager profile
(the portable subset: shell + git + editor + claude) that can be activated on a
machine this flake does **not** manage:
`home-manager switch --flake .#"lyrathorpe@x86_64-linux"`. The desktop/sway
modules are intentionally excluded (they rely on a NixOS-provided Sway/Firefox
binary).
- `homeModules` — the reusable modules exported so another flake can import them
(`inputs.<this>.homeModules.default`). Consumers must supply the module args
these expect: `inputs` always, `identity` for git/desktop, `portable` for sway.
## Directory authentication (SSSD → Authentik LDAP)
Every NixOS host authenticates users against the Authentik LDAP outpost via
SSSD, implemented in [`modules/sssd.nix`](./modules/sssd.nix) and enabled by
default through the `services.authentikLdap.enable` option (added to
`baseModules`). The **EDaaS** WSL box opts out
(`services.authentikLdap.enable = false`) as a work-managed environment; the
macOS host is unaffected (SSSD is Linux-only).
- Connects over LDAPS to `ldap.lyrapup.pet:636`, search base
`dc=ldap,dc=goauthentik,dc=io`, binding as
`cn=sssd-bind,ou=users,dc=ldap,dc=goauthentik,dc=io`.
- The schema mappings match Authentik's non-standard object classes
(`goauthentik.io/ldap/user`, `goauthentik.io/ldap/group`) over the POSIX
attributes (`uid`, `uidNumber`, `gidNumber`, `homeDirectory`).
- Home directories are created on first login (`pam_mkhomedir`).
### Secrets (agenix)
The LDAP bind credential is an [agenix](https://github.com/ryantm/agenix)
secret, decrypted at activation with each host's SSH host key. The decrypted
plaintext is a full `sssd.conf` drop-in delivered to
`/etc/sssd/conf.d/01-ldap-authtok.conf`, so the password never enters the Nix
store. Owner setup (host recipient keys, encrypting the bind password, DNS for
`ldap.lyrapup.pet`, rebuild) is documented in
[`secrets/README.md`](./secrets/README.md).
## Applying ## Applying
```sh ```sh
@@ -35,25 +91,25 @@ darwin-rebuild switch --flake .#lyrathorpe-mac
## Shell environment & keybindings ## Shell environment & keybindings
- Interactive shell features (zsh, tmux, git, ssh, CLI tools, auto-tmux): - Interactive shell features (zsh, tmux, git, ssh, CLI tools, auto-tmux):
[`lyrathorpe/home/README.md`](./lyrathorpe/home/README.md). [`home/README.md`](./home/README.md).
- All Sway / tmux / foot / zsh keyboard shortcuts: - All Sway / tmux / foot / zsh keyboard shortcuts:
[`lyrathorpe/home/KEYBINDINGS.md`](./lyrathorpe/home/KEYBINDINGS.md). [`home/KEYBINDINGS.md`](./home/KEYBINDINGS.md).
## Login / greeter ## Login / greeter
Graphical (Sway) hosts log in through a Wayland greeter — `greetd` running Graphical (Sway) hosts log in through a Wayland greeter — `greetd` running
ReGreet inside the `cage` kiosk compositor — implemented in ReGreet inside the `cage` kiosk compositor — implemented in
[`lyrathorpe/swaywm.nix`](./lyrathorpe/swaywm.nix), gated on [`modules/sway.nix`](./modules/sway.nix), gated on
`features.swayDesktop.enable` (the option is declared in `features.swayDesktop.enable` (the option is declared in
[`system/modules/features.nix`](./system/modules/features.nix), so headless hosts [`modules/features.nix`](./modules/features.nix), so headless hosts
can leave it off without importing `swaywm.nix`). The greeter is forced to Dvorak can leave it off without importing `modules/sway.nix`). The greeter is forced to Dvorak
to match the console and Sway session. Headless hosts (the WSL work box and the to match the console and Sway session. Headless hosts (the WSL work box and the
Raspberry Pi server) keep plain TTY login. The target account needs a password Raspberry Pi server) keep plain TTY login. The target account needs a password
(`passwd <user>`) before it can log in. (`passwd <user>`) before it can log in.
## MacBook (Asahi) firmware ## MacBook (Asahi) firmware
The MBP host references `system/modules/firmware/` for Apple peripheral The MBP host references `modules/firmware/` for Apple peripheral
firmware (Wi-Fi/Bluetooth). These blobs are **committed** (tracked) even though firmware (Wi-Fi/Bluetooth). These blobs are **committed** (tracked) even though
`.gitignore` lists the directory: the flake is `git+file`, so it only sees `.gitignore` lists the directory: the flake is `git+file`, so it only sees
tracked files — untracking them breaks `lyrathorpe-mbp` evaluation (and the CI tracked files — untracking them breaks `lyrathorpe-mbp` evaluation (and the CI
@@ -63,7 +119,7 @@ redistributable; the repo is private.
To refresh them, copy the firmware extracted during the Asahi install (from To refresh them, copy the firmware extracted during the Asahi install (from
`/etc/nixos/firmware`, or re-extract per the `/etc/nixos/firmware`, or re-extract per the
[Asahi NixOS docs](https://github.com/tpwrules/nixos-apple-silicon)) into [Asahi NixOS docs](https://github.com/tpwrules/nixos-apple-silicon)) into
`system/modules/firmware/` and commit with `git add -f`. `modules/firmware/` and commit with `git add -f`.
## Development ## Development
Generated
+35 -18
View File
@@ -25,11 +25,11 @@
}, },
"locked": { "locked": {
"dir": "pkgs/firefox-addons", "dir": "pkgs/firefox-addons",
"lastModified": 1782619356, "lastModified": 1782014564,
"narHash": "sha256-sde3f0uM5mEUwl6Bxom69P+9KOdpJ9YnSj0umSB2qdQ=", "narHash": "sha256-F/royQHyJAyKWKrV8AaG4Yf1yjzxa+PFk5xvTdvBrzk=",
"owner": "rycee", "owner": "rycee",
"repo": "nur-expressions", "repo": "nur-expressions",
"rev": "9ad2019bb522c7eeecd9e3e2d18dd681f697f4d0", "rev": "d6668e34bbce788459883a1097bf0ee170f49c61",
"type": "gitlab" "type": "gitlab"
}, },
"original": { "original": {
@@ -191,6 +191,22 @@
"type": "github" "type": "github"
} }
}, },
"kube-tmux": {
"flake": false,
"locked": {
"lastModified": 1779714285,
"narHash": "sha256-l1wjg2ReWKCI7h/K11vvX2ykYTs/mVD+tfz/mQsjn/E=",
"owner": "jonmosco",
"repo": "kube-tmux",
"rev": "8b7e1d127c16b6dc87ff5743f4d775b245198b69",
"type": "github"
},
"original": {
"owner": "jonmosco",
"repo": "kube-tmux",
"type": "github"
}
},
"nix-darwin": { "nix-darwin": {
"inputs": { "inputs": {
"nixpkgs": [ "nixpkgs": [
@@ -237,11 +253,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1782636943, "lastModified": 1782030356,
"narHash": "sha256-ripjZa7BBLwL1uS5VJF3s/VpZpWt5ZIQEvkJ/FJNpQw=", "narHash": "sha256-h4WpMr455AfRub0FXBaon6Vcpe0waUyJ4GivIW6oyd4=",
"owner": "nix-community", "owner": "nix-community",
"repo": "nix-index-database", "repo": "nix-index-database",
"rev": "058b1f9381fa79fcda49982370a750ff92dbba43", "rev": "3017088b49efd404f78e3b104f553b97e4af786b",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -258,11 +274,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1782374867, "lastModified": 1781520503,
"narHash": "sha256-wgU8MdUzSH2ccq85xo80pP1PAFW+e5kzx6rofVO1Jsk=", "narHash": "sha256-XuqQQG1qRyc3o8ld937sDLQNx+QrGV852KJ0dNglJDg=",
"owner": "nix-community", "owner": "nix-community",
"repo": "nixos-apple-silicon", "repo": "nixos-apple-silicon",
"rev": "bf99497876c07bb945d5fc536916cdee4f3b9eb6", "rev": "43043ad207529650f9fa68e1705f7cf9c08bfdeb",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -278,11 +294,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1782562157, "lastModified": 1781622756,
"narHash": "sha256-a7+T6QSeowynwZ1ZJJbP8T8ntAytvrui8kFGJmIZt2c=", "narHash": "sha256-JrPh4M6S7aPsEE9tOENuZrxC6o2szSLlK+t4+nLke9s=",
"owner": "NixOS", "owner": "NixOS",
"repo": "nixos-hardware", "repo": "nixos-hardware",
"rev": "a9cf7546a938c737b079e738de73934a13de9784", "rev": "08018c72174a4df5657f8d94178ac69fb9c243e5",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -314,11 +330,11 @@
}, },
"nixpkgs": { "nixpkgs": {
"locked": { "locked": {
"lastModified": 1782535326, "lastModified": 1781216227,
"narHash": "sha256-ZeRxu4yn6shd3SNF5ZUQb4r7BaVo1zBKMjRhfoNSBmw=", "narHash": "sha256-9mUW6gNwoN2SWc/l0fW4svPNOulXLl8ijqKyeSOGgJE=",
"owner": "nixos", "owner": "nixos",
"repo": "nixpkgs", "repo": "nixpkgs",
"rev": "714a5f8c4ead6b31148d829288440ed033ccc041", "rev": "a0374025a863d007d98e3297f6aa46cc3141c2f0",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -330,11 +346,11 @@
}, },
"nixpkgs-unstable": { "nixpkgs-unstable": {
"locked": { "locked": {
"lastModified": 1782467914, "lastModified": 1781577229,
"narHash": "sha256-pGvFkM8N0xEkIIXDe5YYfbEAvHrk4IxBrjB/x8OomhE=", "narHash": "sha256-lrp67w8AulE9Ks53n27I45ADSzbOCn4H+CNW1Ck8B+8=",
"owner": "nixos", "owner": "nixos",
"repo": "nixpkgs", "repo": "nixpkgs",
"rev": "e73de5be04e0eff4190a1432b946d469c794e7b4", "rev": "567a49d1913ce81ac6e9582e3553dd90a955875f",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -373,6 +389,7 @@
"flake-parts": "flake-parts", "flake-parts": "flake-parts",
"git-hooks": "git-hooks", "git-hooks": "git-hooks",
"home-manager": "home-manager", "home-manager": "home-manager",
"kube-tmux": "kube-tmux",
"nix-darwin": "nix-darwin", "nix-darwin": "nix-darwin",
"nix-homebrew": "nix-homebrew", "nix-homebrew": "nix-homebrew",
"nix-index-database": "nix-index-database", "nix-index-database": "nix-index-database",
+148 -80
View File
@@ -23,7 +23,7 @@
# Provides mkFlake: the systems/perSystem scaffolding used below. # Provides mkFlake: the systems/perSystem scaffolding used below.
flake-parts.url = "github:hercules-ci/flake-parts"; flake-parts.url = "github:hercules-ci/flake-parts";
flake-parts.inputs.nixpkgs-lib.follows = "nixpkgs"; flake-parts.inputs.nixpkgs-lib.follows = "nixpkgs";
# Declarative Firefox add-ons (e.g. the Catppuccin theme); see lyrathorpe/user.nix. # Declarative Firefox add-ons (e.g. the Catppuccin theme); see modules/users.nix.
firefox-addons = { firefox-addons = {
url = "gitlab:rycee/nur-expressions?dir=pkgs/firefox-addons"; url = "gitlab:rycee/nur-expressions?dir=pkgs/firefox-addons";
inputs.nixpkgs.follows = "nixpkgs"; inputs.nixpkgs.follows = "nixpkgs";
@@ -46,7 +46,16 @@
url = "github:cachix/git-hooks.nix"; url = "github:cachix/git-hooks.nix";
inputs.nixpkgs.follows = "nixpkgs"; inputs.nixpkgs.follows = "nixpkgs";
}; };
# Declarative Neovim (the editor; see lyrathorpe/home/editor.nix). Release # agenix: age-encrypted secrets, decrypted at activation with each host's
# SSH host key. Provides the SSSD LDAP bind credential (secrets/, see
# modules/sssd.nix). The darwin module is intentionally unused (SSSD is
# Linux-only).
agenix = {
url = "github:ryantm/agenix";
inputs.nixpkgs.follows = "nixpkgs";
inputs.home-manager.follows = "home-manager";
};
# Declarative Neovim (the editor; see home/editor.nix). Release
# branch matched to the pinned nixpkgs (26.05); follows our nixpkgs to keep a # branch matched to the pinned nixpkgs (26.05); follows our nixpkgs to keep a
# single nixpkgs in the closure. editor.nix sets programs.nixvim.nixpkgs.source # single nixpkgs in the closure. editor.nix sets programs.nixvim.nixpkgs.source
# to this same input so the home module doesn't warn about the pin. # to this same input so the home module doesn't warn about the pin.
@@ -60,6 +69,13 @@
url = "github:NixOS/nixos-hardware"; url = "github:NixOS/nixos-hardware";
inputs.nixpkgs.follows = "nixpkgs"; inputs.nixpkgs.follows = "nixpkgs";
}; };
# kube-tmux: kube context/namespace for the tmux status line on the work
# host. Not in nixpkgs and not a flake -- pinned here as a plain source so
# the script is always in the store (no manual checkout). See work.nix.
kube-tmux = {
url = "github:jonmosco/kube-tmux";
flake = false;
};
}; };
outputs = outputs =
@@ -93,10 +109,11 @@
# Unfree packages permitted to be built (replaces blanket allowUnfree). # Unfree packages permitted to be built (replaces blanket allowUnfree).
unfreePackages = [ unfreePackages = [
"claude-code" "claude-code"
"lens"
"lens-desktop"
]; ];
# Per-user identity, keyed by username. See README "Users".
userRegistry = import ./users/registry.nix;
# nixpkgs + nix-daemon settings shared by NixOS and Darwin hosts. # nixpkgs + nix-daemon settings shared by NixOS and Darwin hosts.
commonModule = { commonModule = {
nixpkgs.overlays = overlays; nixpkgs.overlays = overlays;
@@ -112,10 +129,12 @@
# Shared scaffolding for every NixOS host: common user, settings, home-manager. # Shared scaffolding for every NixOS host: common user, settings, home-manager.
baseModules = [ baseModules = [
./lyrathorpe/user.nix ./modules/users.nix
./system/modules/common-nixos.nix ./modules/common-nixos.nix
./system/modules/features.nix ./modules/features.nix
./modules/sssd.nix
commonModule commonModule
inputs.agenix.nixosModules.default
home-manager.nixosModules.home-manager home-manager.nixosModules.home-manager
{ {
home-manager.useGlobalPkgs = true; home-manager.useGlobalPkgs = true;
@@ -126,18 +145,13 @@
} }
]; ];
# mkHost :: { system, username, fullName, modules, homeModules } -> nixosSystem # Build one NixOS host. `users` is an attrset keyed by username (home
# Builds one machine by appending its host-specific modules to the shared # modules + optional per-user system bits). See README "Users".
# baseModules. The user identity (username/fullName) is threaded through
# specialArgs so user.nix and the home modules stay host-agnostic, and the
# home-manager profile is keyed by the host's username.
mkHost = mkHost =
{ {
system, system,
username,
fullName,
modules, modules,
homeModules, users,
# Host form factor. Laptops inherit the default; a desktop host sets # Host form factor. Laptops inherit the default; a desktop host sets
# `portable = false` to drop mobile components (battery block, # `portable = false` to drop mobile components (battery block,
# brightness keys) from the home-manager Sway config. # brightness keys) from the home-manager Sway config.
@@ -148,8 +162,7 @@
specialArgs = { specialArgs = {
inherit inherit
inputs inputs
username userRegistry
fullName
portable portable
; ;
}; };
@@ -157,16 +170,15 @@
baseModules baseModules
++ modules ++ modules
++ [ ++ [
{ _module.args.hostUsers = users; }
{ {
home-manager.extraSpecialArgs = { home-manager.extraSpecialArgs = { inherit inputs portable; };
inherit home-manager.users = lib.mapAttrs (name: spec: {
inputs imports = spec.homeModules;
username _module.args.identity = userRegistry.${name} // {
fullName username = name;
portable };
; }) users;
};
home-manager.users.${username}.imports = homeModules;
} }
]; ];
}; };
@@ -185,19 +197,17 @@
} }
]; ];
# mkDarwinHost :: { system, username, fullName, modules, homeModules } -> darwinSystem # Darwin counterpart of mkHost: single-user (macOS owns the account),
# Darwin counterpart of mkHost. macOS already owns the login user, so we # identity still from the registry. See README "Users".
# only attach the platform and home-manager; no NixOS user module here.
mkDarwinHost = mkDarwinHost =
{ {
system, system,
username, username,
fullName,
modules, modules,
homeModules, homeModules,
}: }:
nix-darwin.lib.darwinSystem { nix-darwin.lib.darwinSystem {
specialArgs = { inherit inputs username fullName; }; specialArgs = { inherit inputs username; };
modules = modules =
darwinBaseModules darwinBaseModules
++ modules ++ modules
@@ -206,40 +216,41 @@
nixpkgs.hostPlatform = system; nixpkgs.hostPlatform = system;
# macOS owns the account; point home-manager at its home dir. # macOS owns the account; point home-manager at its home dir.
users.users.${username}.home = "/Users/${username}"; users.users.${username}.home = "/Users/${username}";
home-manager.extraSpecialArgs = { inherit inputs username fullName; }; home-manager.extraSpecialArgs = { inherit inputs; };
home-manager.users.${username}.imports = homeModules; home-manager.users.${username} = {
imports = homeModules;
_module.args.identity = userRegistry.${username} // {
inherit username;
};
};
} }
]; ];
}; };
# Host table — declarative registry of every machine. To add a host: # Host table — one entry per machine, realised into a nixosConfiguration
# give it a name, its `system`, the owning user, and the module lists. # of the same name below. See README "Hosts" / "Users".
# mapAttrs below turns each entry into a nixosConfiguration of the same name.
hosts = { hosts = {
lyrathorpe-mbp = { lyrathorpe-mbp = {
system = "aarch64-linux"; system = "aarch64-linux";
username = "lyrathorpe";
fullName = "Lyra Thorpe";
modules = [ modules = [
./system/machine/MBP-Asahi/configuration.nix ./hosts/MBP-Asahi/configuration.nix
./system/modules/laptop.nix ./modules/laptop.nix
nixos-apple-silicon.nixosModules.default nixos-apple-silicon.nixosModules.default
./lyrathorpe/swaywm.nix ./modules/sway.nix
]; ];
homeModules = [ users.lyrathorpe.homeModules = [
./lyrathorpe/home ./home
./lyrathorpe/home/desktop.nix ./users/lyrathorpe/home.nix
./home/desktop.nix
]; ];
}; };
lyrathorpe-t400 = { lyrathorpe-t400 = {
system = "x86_64-linux"; system = "x86_64-linux";
username = "lyrathorpe";
fullName = "Lyra Thorpe";
modules = [ modules = [
./system/machine/T400/configuration.nix ./hosts/T400/configuration.nix
./system/modules/laptop.nix ./modules/laptop.nix
./system/modules/ssh.nix ./modules/ssh.nix
# No t400-specific profile exists; compose the generic ThinkPad + # No t400-specific profile exists; compose the generic ThinkPad +
# laptop/SSD/Intel building blocks (tp_smapi/acpi_call for battery # laptop/SSD/Intel building blocks (tp_smapi/acpi_call for battery
# thresholds, SSD + microcode defaults). # thresholds, SSD + microcode defaults).
@@ -247,78 +258,82 @@
inputs.nixos-hardware.nixosModules.common-pc-laptop inputs.nixos-hardware.nixosModules.common-pc-laptop
inputs.nixos-hardware.nixosModules.common-pc-laptop-ssd inputs.nixos-hardware.nixosModules.common-pc-laptop-ssd
inputs.nixos-hardware.nixosModules.common-cpu-intel inputs.nixos-hardware.nixosModules.common-cpu-intel
./lyrathorpe/swaywm.nix ./modules/sway.nix
]; ];
homeModules = [ users.lyrathorpe.homeModules = [
./lyrathorpe/home ./home
./lyrathorpe/home/desktop.nix ./users/lyrathorpe/home.nix
./home/desktop.nix
]; ];
}; };
lyrathorpe-macpro31 = { lyrathorpe-macpro31 = {
system = "x86_64-linux"; system = "x86_64-linux";
username = "lyrathorpe";
fullName = "Lyra Thorpe";
portable = false; portable = false;
modules = [ modules = [
./system/machine/MacPro31/configuration.nix ./hosts/MacPro31/configuration.nix
./system/modules/desktop.nix ./modules/desktop.nix
./system/modules/ssh.nix ./modules/ssh.nix
inputs.nixos-hardware.nixosModules.common-pc-ssd inputs.nixos-hardware.nixosModules.common-pc-ssd
inputs.nixos-hardware.nixosModules.common-cpu-intel inputs.nixos-hardware.nixosModules.common-cpu-intel
./lyrathorpe/swaywm.nix ./modules/sway.nix
]; ];
homeModules = [ users.lyrathorpe.homeModules = [
./lyrathorpe/home ./home
./lyrathorpe/home/desktop.nix ./users/lyrathorpe/home.nix
./home/desktop.nix
]; ];
}; };
emmathorpe-edaas = { emmathorpe-edaas = {
system = "x86_64-linux"; system = "x86_64-linux";
username = "emmathorpe";
fullName = "Emma Thorpe";
modules = [ modules = [
./system/machine/EDaaS/configuration.nix ./hosts/EDaaS/configuration.nix
nixos-wsl.nixosModules.default nixos-wsl.nixosModules.default
./lyrathorpe/swaywm.nix ./modules/sway.nix
];
homeModules = [
./lyrathorpe/home
./lyrathorpe/home/work.nix
]; ];
users.emmathorpe = {
homeModules = [
./home
./users/emmathorpe/work.nix
];
# Keep the systemd --user instance alive without a login session so
# the renovate-review home timer fires on schedule.
linger = true;
};
}; };
lyrathorpe-rpi5 = { lyrathorpe-rpi5 = {
system = "aarch64-linux"; system = "aarch64-linux";
username = "lyrathorpe";
fullName = "Lyra Thorpe";
portable = false; portable = false;
# Headless server: Docker host + nginx reverse proxy. No swaywm.nix # Headless server: Docker host + nginx reverse proxy. No sway.nix
# (no desktop); the raspberry-pi-5 profile supplies kernel/firmware, # (no desktop); the raspberry-pi-5 profile supplies kernel/firmware,
# ssh.nix adds key-only sshd. # ssh.nix adds key-only sshd.
modules = [ modules = [
./system/machine/RPi5/configuration.nix ./hosts/RPi5/configuration.nix
inputs.nixos-hardware.nixosModules.raspberry-pi-5 inputs.nixos-hardware.nixosModules.raspberry-pi-5
./system/modules/ssh.nix ./modules/ssh.nix
];
users.lyrathorpe.homeModules = [
./home
./users/lyrathorpe/home.nix
]; ];
homeModules = [ ./lyrathorpe/home ];
}; };
}; };
# Darwin host table — macOS machines built via mkDarwinHost. The shared # Darwin host table — macOS machines built via mkDarwinHost. The shared
# ./lyrathorpe/home modules (shell, git, editor) are reused; the Linux-only # ./home bundle (shell, git, editor) is reused directly; the Linux-only
# desktop/sway modules are intentionally left out. # desktop/sway modules are intentionally left out.
darwinHosts = { darwinHosts = {
lyrathorpe-mac = { lyrathorpe-mac = {
system = "aarch64-darwin"; system = "aarch64-darwin";
username = "lyrathorpe"; username = "lyrathorpe";
fullName = "Lyra Thorpe";
modules = [ modules = [
./system/machine/Darwin/configuration.nix ./hosts/Darwin/configuration.nix
]; ];
homeModules = [ homeModules = [
./lyrathorpe/home ./home
./users/lyrathorpe/home.nix
]; ];
}; };
}; };
@@ -409,6 +424,59 @@
# Realise the host tables: each entry becomes a {nixos,darwin}Configuration. # Realise the host tables: each entry becomes a {nixos,darwin}Configuration.
flake.nixosConfigurations = lib.mapAttrs (_name: mkHost) hosts; flake.nixosConfigurations = lib.mapAttrs (_name: mkHost) hosts;
flake.darwinConfigurations = lib.mapAttrs (_name: mkDarwinHost) darwinHosts; flake.darwinConfigurations = lib.mapAttrs (_name: mkDarwinHost) darwinHosts;
# Reusable home modules, exported for use off these hosts. See README
# "Portable home" for the consumer module-arg expectations.
flake.homeModules = {
default = ./home;
shell = ./home/shell.nix;
git = ./home/git.nix;
editor = ./home/editor.nix;
claude = ./home/claude.nix;
desktop = ./home/desktop.nix;
sway = ./home/sway.nix;
};
# Standalone home-manager configs (portable bundle) for machines not
# managed by this flake. See README "Portable home".
flake.homeConfigurations =
let
mkHome =
{
system,
name,
}:
home-manager.lib.homeManagerConfiguration {
pkgs = import nixpkgs {
inherit system overlays;
config.allowUnfreePredicate = pkg: builtins.elem (lib.getName pkg) unfreePackages;
};
extraSpecialArgs = {
inherit inputs;
portable = true;
identity = userRegistry.${name} // {
username = name;
};
};
modules = [
./home
{
home.username = name;
home.homeDirectory = "/home/${name}";
}
];
};
in
{
"lyrathorpe@x86_64-linux" = mkHome {
system = "x86_64-linux";
name = "lyrathorpe";
};
"lyrathorpe@aarch64-linux" = mkHome {
system = "aarch64-linux";
name = "lyrathorpe";
};
};
} }
); );
} }
+33 -31
View File
@@ -15,8 +15,10 @@ Keyboard shortcuts have their own reference: [`KEYBINDINGS.md`](./KEYBINDINGS.md
| GUI apps, GTK/Firefox theming, cursor | [`desktop.nix`](./desktop.nix) (graphical hosts only) | | GUI apps, GTK/Firefox theming, cursor | [`desktop.nix`](./desktop.nix) (graphical hosts only) |
Shared by every host via [`default.nix`](./default.nix); the work box also layers Shared by every host via [`default.nix`](./default.nix); the work box also layers
[`work.nix`](./work.nix) on top (work email, its own ssh config, extra packages, [`work.nix`](../users/emmathorpe/work.nix) on top (its own ssh config, extra
and the C#/Helm language servers). packages, and the C#/Helm language servers). The committer identity (name, email,
signing key) comes from the user registry
([`../users/registry.nix`](../users/registry.nix)), not this module.
--- ---
@@ -55,7 +57,7 @@ and the C#/Helm language servers).
| `hyperfine` / `sd` | command-line benchmarking; saner find-and-replace than sed | | `hyperfine` / `sd` | command-line benchmarking; saner find-and-replace than sed |
**Theming:** `fzf`, `bat`, `btop`, `lazygit` and `git`'s `delta` pager are all **Theming:** `fzf`, `bat`, `btop`, `lazygit` and `git`'s `delta` pager are all
Catppuccin Mocha, driven from the shared `../catppuccin-mocha.nix` palette / the Catppuccin Mocha, driven from the shared `../lib/catppuccin-mocha.nix` palette / the
catppuccin upstream themes. catppuccin upstream themes.
**Env & defaults:** `xdg.enable` on; `PAGER`/`MANPAGER` (bat) set in `default.nix` **Env & defaults:** `xdg.enable` on; `PAGER`/`MANPAGER` (bat) set in `default.nix`
@@ -108,23 +110,23 @@ declaratively with **nixvim**, so the same plugins and config are baked in on
every host. Migrated from plain vim; the practical gain is a real LSP stack in every host. Migrated from plain vim; the practical gain is a real LSP stack in
place of the old (inert) ALE. place of the old (inert) ALE.
| Feature | Notes | | Feature | Notes |
| -------------- | -------------------------------------------------------------------------------------- | | -------------- | ----------------------------------------------------------------------------------------- |
| Colorscheme | Catppuccin Mocha (matches the terminal and the rest of the desktop) | | Colorscheme | Catppuccin Mocha (matches the terminal and the rest of the desktop) |
| File tree | nvim-tree, toggled with `,,` (comma twice; was nerdtree) | | File tree | nvim-tree, toggled with `,,` (comma twice; was nerdtree) |
| Fuzzy finder | telescope (+fzf-native): `<leader>ff` files, `<leader>fg` grep, `<leader>fb` buffers | | Fuzzy finder | telescope (+fzf-native): `<leader>ff` files, `<leader>fg` grep, `<leader>fb` buffers |
| Format on save | conform-nvim (nixfmt, stylua, ruff, shfmt, prettier, gofumpt; LSP fallback otherwise) | | Format on save | conform-nvim (nixfmt, stylua, ruff, shfmt, prettier, gofumpt; LSP fallback otherwise) |
| Git | fugitive (`:Git …`) + gitsigns gutter signs/blame | | Git | fugitive (`:Git …`) + gitsigns gutter signs/blame |
| Diagnostics | inline + trouble list (`<leader>xx`) | | Diagnostics | inline + trouble list (`<leader>xx`) |
| Completion | nvim-cmp (LSP/buffer/path) with luasnip snippet expansion | | Completion | nvim-cmp (LSP/buffer/path) with luasnip snippet expansion |
| Indent guides | indent-blankline, on by default (was vim-indent-guides) | | Indent guides | indent-blankline, on by default (was vim-indent-guides) |
| Statusline | lualine (Catppuccin theme) | | Statusline | lualine (Catppuccin theme) |
| Editing | which-key hints, comment (`gc`/`gcc`), autopairs, treesitter textobjects | | Editing | which-key hints, comment (`gc`/`gcc`), autopairs, treesitter textobjects |
| Pane nav | vim-tmux-navigator — `Ctrl`+`h/j/k/l` moves across vim splits and tmux panes | | Pane nav | vim-tmux-navigator — `Ctrl`+`h/j/k/l` moves across vim splits and tmux panes |
| Syntax | tree-sitter (nix, lua, bash, markdown, groovy, c#, python, terraform, yaml) | | Syntax | tree-sitter (nix, lua, bash, markdown, groovy, c#, python, terraform, yaml) |
| LSP | nvim-cmp completion + servers `nil` (Nix), `lua_ls`, `pyright` (Python), `terraformls` | | LSP | nvim-cmp completion + servers `nil_ls` (Nix), `lua_ls`, `pyright` (Python), `terraformls` |
| Indentation | 2-wide hard tabs (`noexpandtab`, `tabstop`/`shiftwidth` = 2); line numbers on | | Indentation | 2-wide hard tabs (`noexpandtab`, `tabstop`/`shiftwidth` = 2); line numbers on |
| Filetypes | `*Jenkinsfile` → groovy | | Filetypes | `*Jenkinsfile` → groovy |
Leader is `Space`. LSP keymaps (`gd`, `gr`, `K`, `<leader>rn`, `<leader>ca`) and Leader is `Space`. LSP keymaps (`gd`, `gr`, `K`, `<leader>rn`, `<leader>ca`) and
the file-tree toggle are listed in the file-tree toggle are listed in
@@ -147,17 +149,17 @@ current (`gc`/`fetch.writeCommitGraph`) so `lg` stays fast.
| `lg` | graph log, all branches | | `lg` | graph log, all branches |
| `cz` `cc` | `git cz <sub>` (e.g. `git cz c`) and `git cc` → commitizen prompt | | `cz` `cc` | `git cz <sub>` (e.g. `git cz c`) and `git cc` → commitizen prompt |
| Behaviour | | | Behaviour | |
| -------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | -------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Pulls | rebase, with autostash + autosquash | | Pulls | rebase, with autostash + autosquash |
| Fetch | prune deleted remote branches | | Fetch | prune deleted remote branches |
| Conflicts | `zdiff3` (shows the common ancestor) | | Conflicts | `zdiff3` (shows the common ancestor) |
| Diffs | histogram algorithm, colour-moved | | Diffs | histogram algorithm, colour-moved |
| `rerere` | remembers + replays conflict resolutions | | `rerere` | remembers + replays conflict resolutions |
| Commit editor | full diff shown (`commit.verbose`) | | Commit editor | full diff shown (`commit.verbose`) |
| Misc | branches sorted by date, `column.ui = auto`, `help.autocorrect = prompt`, `push.autoSetupRemote` | | Misc | branches sorted by date, `column.ui = auto`, `help.autocorrect = prompt`, `push.autoSetupRemote` |
| Global ignores | `result`, `result-*`, `.direnv`, `*.swp`, `.DS_Store` | | Global ignores | `result`, `result-*`, `.direnv`, `*.swp`, `.DS_Store` |
| Signing | SSH commit + tag signing (`mkDefault`, so a host without the key in its agent can disable it). Personal email `iam@emmathe.dev`; the work box overrides email + signing. | | Signing | SSH commit + tag signing (`mkDefault`, so a host without the key in its agent can disable it). Name, email and signing key all come from the per-user `identity` (the user registry, `../users/registry.nix`). |
## ssh ## ssh
@@ -1,12 +1,13 @@
# Graphical desktop layer: GUI apps, Wayland session env, and cursor theme. # Graphical desktop layer: GUI apps, Wayland session env, and cursor theme.
# Imported only on hosts that run Sway (MBP, T400, Mac Pro); never pulled onto # Imported only on hosts that run Sway (MBP, T400, Mac Pro); never pulled onto
# the headless WSL host. Login (and the Sway session launch) is handled by the # the headless WSL host. Login (and the Sway session launch) is handled by the
# greetd/ReGreet greeter -- see ../swaywm.nix -- so there is no tty1 autostart. # greetd/ReGreet greeter -- see ../modules/sway.nix -- so there is no tty1
# autostart.
{ {
pkgs, pkgs,
config, config,
inputs, inputs,
username, identity,
... ...
}: }:
{ {
@@ -89,7 +90,7 @@
}; };
# Firefox is themed at the browser level (it does not follow the GTK theme). # Firefox is themed at the browser level (it does not follow the GTK theme).
# The system installs the binary (programs.firefox in ../user.nix); here # The system installs the binary (programs.firefox in ../modules/users.nix); here
# home-manager owns only the profile, hence package = null. Apply the # home-manager owns only the profile, hence package = null. Apply the
# Catppuccin Mocha theme add-on (only the mauve accent is packaged upstream; # Catppuccin Mocha theme add-on (only the mauve accent is packaged upstream;
# the rest of the desktop uses blue) and make content + UI dark. # the rest of the desktop uses blue) and make content + UI dark.
@@ -101,7 +102,7 @@
# stateVersion<26.05 default-change warning (the new XDG path depends on # stateVersion<26.05 default-change warning (the new XDG path depends on
# Firefox's own profile support). # Firefox's own profile support).
configPath = ".mozilla/firefox"; configPath = ".mozilla/firefox";
profiles.${username} = { profiles.${identity.username} = {
id = 0; id = 0;
isDefault = true; isDefault = true;
extensions = { extensions = {
+10 -15
View File
@@ -1,13 +1,13 @@
# Version control: git + delta pager + commitizen + lazygit. The work host # Version control: git + delta + commitizen + lazygit. Committer identity comes
# layers commit signing and an email override on top (see work.nix). # from the per-user `identity` arg (the registry). See README "Users".
{ {
pkgs, pkgs,
lib, lib,
fullName, identity,
... ...
}: }:
let let
ctp = import ../catppuccin-mocha.nix; ctp = import ../lib/catppuccin-mocha.nix;
in in
{ {
home.packages = [ home.packages = [
@@ -18,10 +18,9 @@ in
enable = true; enable = true;
package = pkgs.gitFull; package = pkgs.gitFull;
settings = { settings = {
user.name = fullName; user.name = identity.fullName;
# Personal identity. mkDefault so the work module overrides it on the work # mkDefault so a host-specific module can still override it.
# host (and to merge cleanly with that plain definition there). user.email = lib.mkDefault identity.email;
user.email = lib.mkDefault "iam@emmathe.dev";
push.autoSetupRemote = true; push.autoSetupRemote = true;
init.defaultBranch = "main"; init.defaultBranch = "main";
@@ -77,14 +76,10 @@ in
cc = "!cz commit"; cc = "!cz commit";
}; };
# SSH commit signing. This personal key is the default; the work module # SSH signing, key from the registry. mkDefault so a host lacking the key
# (work.nix) overrides it with the work key on the EDaaS host, the same way # in its agent can set gpgsign = false instead of failing every commit.
# user.email is overridden -- so mkDefault here lets that plain definition
# win instead of conflicting. gpgsign is mkDefault too, so a host without
# the key in its ssh-agent can override it to false rather than fail every
# commit.
gpg.format = "ssh"; gpg.format = "ssh";
user.signingkey = lib.mkDefault "key::ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIPDxHvdMTOzpFWUFMtCP7C/4tIOUO3GIO2QPvaifSnWH lyrathorpe@Lyra-MBA"; user.signingkey = lib.mkDefault identity.signingKey;
commit.gpgsign = lib.mkDefault true; commit.gpgsign = lib.mkDefault true;
tag.gpgsign = lib.mkDefault true; tag.gpgsign = lib.mkDefault true;
}; };
+1 -1
View File
@@ -8,7 +8,7 @@
}: }:
let let
# Shared Catppuccin Mocha palette: raw 6-hex strings, no leading "#". # Shared Catppuccin Mocha palette: raw 6-hex strings, no leading "#".
ctp = import ../catppuccin-mocha.nix; ctp = import ../lib/catppuccin-mocha.nix;
in in
{ {
imports = [ imports = [
+5 -6
View File
@@ -2,7 +2,7 @@
# Imported via ./desktop.nix, so only graphical hosts get it. # Imported via ./desktop.nix, so only graphical hosts get it.
# #
# The compositor binary, PAM and the polkit *daemon* come from the system-level # The compositor binary, PAM and the polkit *daemon* come from the system-level
# programs.sway (see ../swaywm.nix); package = null below reuses it instead of # programs.sway (see ../modules/sway.nix); package = null below reuses it instead of
# pulling a second Sway. The polkit authentication *agent* (the thing that draws # pulling a second Sway. The polkit authentication *agent* (the thing that draws
# the GUI auth dialog) is a user service started here. home-manager owns the user # the GUI auth dialog) is a user service started here. home-manager owns the user
# config (~/.config/sway) and wires the systemd user session (sway-session.target), # config (~/.config/sway) and wires the systemd user session (sway-session.target),
@@ -20,7 +20,7 @@ let
# Catppuccin Mocha (shared with the ReGreet greeter). Raw hex; prefix "#" # Catppuccin Mocha (shared with the ReGreet greeter). Raw hex; prefix "#"
# where a consumer needs it -- Sway/i3status/dunst want "#", foot/swaylock do # where a consumer needs it -- Sway/i3status/dunst want "#", foot/swaylock do
# not. # not.
ctp = import ../catppuccin-mocha.nix; ctp = import ../lib/catppuccin-mocha.nix;
# Focused-window screenshot -> swappy editor (the dotfiles' grimshot.sh logic). # Focused-window screenshot -> swappy editor (the dotfiles' grimshot.sh logic).
# Full store paths so it needs nothing on PATH. # Full store paths so it needs nothing on PATH.
@@ -334,13 +334,12 @@ in
]; ];
}; };
# Night light. Manual location (no geoclue dependency); adjust the coordinates # Night light. Manual location (no geoclue dependency); warmer at night,
# to taste. Warmer at night, neutral by day. # neutral by day. Coordinates come from the per-user module (e.g.
# users/lyrathorpe/home.nix), not this shared module.
services.gammastep = { services.gammastep = {
enable = true; enable = true;
provider = "manual"; provider = "manual";
latitude = 51.5;
longitude = -0.13; # London-ish; set to your actual location
temperature = { temperature = {
day = 6500; day = 6500;
night = 3700; night = 3700;
@@ -1,5 +1,5 @@
# Default nix-darwin host. Minimal macOS baseline; the user environment # Default nix-darwin host. Minimal macOS baseline; the user environment
# (shell, git, editor) is carried by the shared ./lyrathorpe/home modules, # (shell, git, editor) is carried by the shared ./home modules,
# the same ones used by the Linux hosts. nixpkgs.hostPlatform is set by # the same ones used by the Linux hosts. nixpkgs.hostPlatform is set by
# mkDarwinHost in flake.nix. # mkDarwinHost in flake.nix.
{ pkgs, username, ... }: { pkgs, username, ... }:
@@ -62,12 +62,16 @@
features.swayDesktop.enable = false; features.swayDesktop.enable = false;
# Keep this user's systemd --user instance running without an open login # Opt out of fleet-wide SSSD/Authentik LDAP auth: this is a work-managed WSL
# session, so the home-manager user timer (renovate-review.nix) fires on # box, not part of the personal directory. Every other NixOS host inherits the
# schedule even when no terminal is attached. On WSL the timer still only runs # default-true from modules/sssd.nix.
# while the distro itself is up; Persistent=true catches up a missed run at services.authentikLdap.enable = false;
# next start.
users.users.emmathorpe.linger = true; # NOTE: this user's systemd --user lingering -- so the home-manager renovate
# timer fires without an open login session -- is enabled from the host table
# in flake.nix (users.emmathorpe.linger = true) and applied by
# modules/users.nix.
# programs.nix-ld is enabled for all NixOS hosts in common-nixos.nix. # programs.nix-ld is enabled for all NixOS hosts in common-nixos.nix.
# This value determines the NixOS release from which the default # This value determines the NixOS release from which the default
# settings for stateful data, like file locations and database versions # settings for stateful data, like file locations and database versions
@@ -26,10 +26,8 @@
# workstation.nix is the backstop). # workstation.nix is the backstop).
zramSwap.enable = true; zramSwap.enable = true;
# This host accepts SSH, so open 22 (the firewall itself is enabled in # sshd (daemon, port 22, key-only policy) comes from ../../modules/ssh.nix;
# workstation.nix with a default-deny policy). # the firewall itself is enabled in workstation.nix with a default-deny policy.
services.openssh.enable = true;
networking.firewall.allowedTCPPorts = [ 22 ];
# Dual Harpertown Xeon microcode. Redistributable firmware (GPU/NIC blobs) is # Dual Harpertown Xeon microcode. Redistributable firmware (GPU/NIC blobs) is
# enabled in workstation.nix. # enabled in workstation.nix.
@@ -42,7 +40,7 @@
# - ATI Radeon HD 2600 XT -> "radeon" (older) or "amdgpu" KMS # - ATI Radeon HD 2600 XT -> "radeon" (older) or "amdgpu" KMS
# - NVIDIA GeForce 8800 GT -> "nouveau" KMS # - NVIDIA GeForce 8800 GT -> "nouveau" KMS
# These come up automatically via the in-tree drivers + KMS, and the graphics # These come up automatically via the in-tree drivers + KMS, and the graphics
# stack itself is enabled by swaywm.nix. If a card needs to be forced, add it # stack itself is enabled by modules/sway.nix. If a card needs to be forced, add it
# here, e.g. `services.xserver.videoDrivers = [ "radeon" ];` (or "nouveau"), # here, e.g. `services.xserver.videoDrivers = [ "radeon" ];` (or "nouveau"),
# and/or `boot.initrd.kernelModules = [ "radeon" ];` in # and/or `boot.initrd.kernelModules = [ "radeon" ];` in
# hardware-configuration.nix for early KMS. # hardware-configuration.nix for early KMS.
@@ -15,7 +15,7 @@
# (which selects by the local hostname) resolves without an explicit -H flag. # (which selects by the local hostname) resolves without an explicit -H flag.
networking.hostName = "lyrathorpe-rpi5"; networking.hostName = "lyrathorpe-rpi5";
# Headless server: the Sway desktop is intentionally not set up. swaywm.nix is # Headless server: the Sway desktop is intentionally not set up. modules/sway.nix is
# not imported and features.swayDesktop.enable defaults to false (declared in # not imported and features.swayDesktop.enable defaults to false (declared in
# system/modules/features.nix), so this host keeps plain TTY/SSH login. # system/modules/features.nix), so this host keeps plain TTY/SSH login.
@@ -25,15 +25,12 @@
boot.loader.grub.enable = false; boot.loader.grub.enable = false;
boot.loader.generic-extlinux-compatible.enable = true; boot.loader.generic-extlinux-compatible.enable = true;
# Remote administration. Key-only policy and the authorized key come from # Remote administration: the daemon, port 22 and key-only policy all come from
# ../../modules/ssh.nix; here we just enable the daemon and open the port. # ../../modules/ssh.nix.
services.openssh.enable = true;
# Default-deny inbound. Open only SSH here; the Docker and nginx submodules # Default-deny inbound; the Docker and nginx submodules open their own ports
# open their own ports (Docker via a source-restricted nftables rule, nginx # (Docker via a source-restricted nftables rule, nginx via 80/443).
# via 80/443). List-valued, so these merge with the submodule definitions.
networking.firewall.enable = true; networking.firewall.enable = true;
networking.firewall.allowedTCPPorts = [ 22 ];
# See `man configuration.nix` / the stateVersion docs before changing. # See `man configuration.nix` / the stateVersion docs before changing.
system.stateVersion = "26.05"; system.stateVersion = "26.05";
@@ -8,6 +8,10 @@
# secure upgrade path is mutual TLS on 2376 (--tlsverify with client certs); # secure upgrade path is mutual TLS on 2376 (--tlsverify with client certs);
# that needs out-of-band cert provisioning and is intentionally not wired here. # that needs out-of-band cert provisioning and is intentionally not wired here.
{ ... }: { ... }:
let
# LAN allowed to reach the unauthenticated Docker TCP socket (see SECURITY above).
trustedSubnet = "10.187.1.0/24";
in
{ {
virtualisation.docker.enable = true; virtualisation.docker.enable = true;
@@ -29,6 +33,6 @@
# CIDR to match the LAN that should reach the Docker API. # CIDR to match the LAN that should reach the Docker API.
networking.nftables.enable = true; networking.nftables.enable = true;
networking.firewall.extraInputRules = '' networking.firewall.extraInputRules = ''
ip saddr 10.187.1.0/24 tcp dport 2375 accept ip saddr ${trustedSubnet} tcp dport 2375 accept
''; '';
} }
@@ -21,10 +21,8 @@
# Low-RAM host (4 GiB max): a compressed RAM swap reduces disk paging. # Low-RAM host (4 GiB max): a compressed RAM swap reduces disk paging.
zramSwap.enable = true; zramSwap.enable = true;
# This host accepts SSH, so open 22 (the firewall itself is enabled in # sshd (daemon, port 22, key-only policy) comes from ../../modules/ssh.nix;
# laptop.nix with a default-deny policy). # the firewall itself is enabled in laptop.nix with a default-deny policy.
services.openssh.enable = true;
networking.firewall.allowedTCPPorts = [ 22 ];
# Intel Core 2 (Penryn) microcode. Redistributable firmware (enabled in # Intel Core 2 (Penryn) microcode. Redistributable firmware (enabled in
# workstation.nix) supplies the iwlwifi blobs (Intel WiFi Link 5100/5300) and # workstation.nix) supplies the iwlwifi blobs (Intel WiFi Link 5100/5300) and
@@ -1,6 +1,6 @@
# Catppuccin Mocha palette. Raw 6-digit hex (no leading "#"); consumers add a # Catppuccin Mocha palette. Raw 6-digit hex (no leading "#"); consumers add a
# "#" where their format needs it. Shared by the Sway desktop theming # "#" where their format needs it. Shared by the Sway desktop theming
# (home/sway.nix) and the ReGreet greeter (swaywm.nix) so the two stay in sync. # (home/sway.nix) and the ReGreet greeter (modules/sway.nix) so the two stay in sync.
{ {
base = "1e1e2e"; base = "1e1e2e";
mantle = "181825"; mantle = "181825";
-28
View File
@@ -1,28 +0,0 @@
{
config,
pkgs,
lib,
username,
fullName,
...
}:
{
programs.zsh.enable = true;
users.users.${username} = {
isNormalUser = true;
home = "/home/${username}";
description = fullName;
extraGroups = [
"wheel"
"docker"
];
shell = pkgs.zsh;
};
programs.firefox = lib.mkIf (config.features.swayDesktop.enable == true) {
enable = true;
};
programs.thunderbird = lib.mkIf (config.features.swayDesktop.enable == true) {
enable = true;
};
}
@@ -2,7 +2,7 @@
# shared ./workstation.nix base and swaps the mobile Wi-Fi backend for wired # shared ./workstation.nix base and swaps the mobile Wi-Fi backend for wired
# NetworkManager. A desktop host also sets `portable = false` in its host-table # NetworkManager. A desktop host also sets `portable = false` in its host-table
# entry (flake.nix), which drops the battery block and brightness keybindings # entry (flake.nix), which drops the battery block and brightness keybindings
# from the Sway bar -- see lyrathorpe/home/sway.nix. # from the Sway bar -- see home/sway.nix.
{ ... }: { ... }:
{ {
imports = [ ./workstation.nix ]; imports = [ ./workstation.nix ];
@@ -2,9 +2,9 @@
# baseModules in flake.nix). Declaring the flags here -- rather than inside the # baseModules in flake.nix). Declaring the flags here -- rather than inside the
# module that implements them -- means a host can read or set a flag without # module that implements them -- means a host can read or set a flag without
# importing the (often large) implementation module. In particular, # importing the (often large) implementation module. In particular,
# features.swayDesktop.enable is read by lyrathorpe/user.nix on every host, but a # features.swayDesktop.enable is read by modules/users.nix on every host, but a
# headless host (e.g. the Pi) must be able to leave it at its default without # headless host (e.g. the Pi) must be able to leave it at its default without
# pulling in lyrathorpe/swaywm.nix. The implementation lives in swaywm.nix, # pulling in modules/sway.nix. The implementation lives in modules/sway.nix,
# gated on this flag. # gated on this flag.
{ lib, ... }: { lib, ... }:
{ {
@@ -2,7 +2,7 @@
# flake.nix. Shared graphical-workstation settings live in ./workstation.nix; # flake.nix. Shared graphical-workstation settings live in ./workstation.nix;
# the only laptop-specific bit is the Wi-Fi backend. Mobile home-manager # the only laptop-specific bit is the Wi-Fi backend. Mobile home-manager
# components (battery block, brightness keys) are gated by the `portable` flag # components (battery block, brightness keys) are gated by the `portable` flag
# threaded through mkHost -- see lyrathorpe/home/sway.nix. # threaded through mkHost -- see home/sway.nix.
{ ... }: { ... }:
{ {
imports = [ ./workstation.nix ]; imports = [ ./workstation.nix ];
+14
View File
@@ -0,0 +1,14 @@
# sshd for the hosts that run it (T400, Mac Pro, RPi5): enable the daemon, open
# port 22, and apply a key-only policy. Authorized keys are owned per-user by the
# registry (modules/users.nix), not here.
{ ... }:
{
services.openssh.enable = true;
networking.firewall.allowedTCPPorts = [ 22 ];
services.openssh.settings = {
PasswordAuthentication = false; # keys only
KbdInteractiveAuthentication = false; # no keyboard-interactive fallback
PermitRootLogin = "no";
};
}
+130
View File
@@ -0,0 +1,130 @@
# Authentik LDAP authentication for NixOS hosts.
#
# Wires SSSD (System Security Services Daemon) to the Authentik LDAP outpost so
# every Linux host authenticates users against the same directory that backs the
# SSO stack. Enabled by default on every NixOS host via baseModules; the EDaaS
# WSL box opts out (services.authentikLdap.enable = false) because it is a
# work-managed Windows-hosted environment.
#
# The Authentik LDAP provider exposes NON-standard object classes/attributes
# (goauthentik.io/ldap/user, goauthentik.io/ldap/group) alongside the POSIX
# attributes (uid, uidNumber, gidNumber, homeDirectory), so the schema mappings
# below are explicit rather than relying on an RFC2307 default.
#
# The bind password is NOT inlined: services.sssd.config renders to the world-
# readable Nix store, so the credential is delivered out-of-band by agenix as an
# sssd.conf drop-in under /etc/sssd/conf.d/ (SSSD merges conf.d/*.conf after the
# main file). See secrets/README.md.
{
config,
lib,
...
}:
let
cfg = config.services.authentikLdap;
# Directory coordinates for the Authentik LDAP provider.
ldapUri = "ldaps://ldap.lyrapup.pet:636";
searchBase = "dc=ldap,dc=goauthentik,dc=io";
bindDn = "cn=sssd-bind,ou=users,dc=ldap,dc=goauthentik,dc=io";
in
{
options.services.authentikLdap.enable =
lib.mkEnableOption "SSSD authentication against the Authentik LDAP outpost"
// {
default = true;
};
config = lib.mkIf cfg.enable {
services.sssd = {
enable = true;
# Non-secret sssd.conf. The bind password is injected separately via the
# agenix conf.d drop-in (ldap_default_authtok lives there, not here) to
# keep it out of the Nix store.
config = ''
[sssd]
config_file_version = 2
services = nss, pam
domains = default
[nss]
# Do not walk the whole directory for `getent passwd` etc.
filter_users = root
filter_groups = root
[pam]
[domain/default]
# --- Providers --------------------------------------------------------
id_provider = ldap
auth_provider = ldap
chpass_provider = none
access_provider = permit
# --- Connection -------------------------------------------------------
ldap_uri = ${ldapUri}
ldap_search_base = ${searchBase}
ldap_default_bind_dn = ${bindDn}
ldap_default_authtok_type = password
# ldap_default_authtok is supplied by the agenix drop-in in conf.d.
# --- TLS (LDAPS on 636; no StartTLS) ---------------------------------
ldap_id_use_start_tls = false
ldap_tls_reqcert = demand
# --- Schema: Authentik LDAP provider ---------------------------------
# Authentik returns DN-valued group membership (member/memberOf), so
# rfc2307bis (not rfc2307) is the correct base schema.
ldap_schema = rfc2307bis
# Users: goauthentik.io/ldap/user, keyed by uid; POSIX attrs are
# standard names (uidNumber/gidNumber/homeDirectory).
ldap_user_object_class = goauthentik.io/ldap/user
ldap_user_name = uid
ldap_user_uid_number = uidNumber
ldap_user_gid_number = gidNumber
ldap_user_home_directory = homeDirectory
ldap_user_gecos = displayName
ldap_user_shell = loginShell
# Groups: goauthentik.io/ldap/group, keyed by cn.
ldap_group_object_class = goauthentik.io/ldap/group
ldap_group_name = cn
ldap_group_gid_number = gidNumber
ldap_group_member = member
# --- Behaviour --------------------------------------------------------
cache_credentials = true
enumerate = false
'';
};
# agenix delivers the bind password as an sssd.conf drop-in. The decrypted
# plaintext IS a valid conf.d snippet:
#
# [domain/default]
# ldap_default_authtok = <the bind password>
#
# SSSD requires conf.d files to be root-owned and 0600 or it ignores them.
age.secrets.ldap-bind = {
file = ../secrets/ldap-bind.age;
path = "/etc/sssd/conf.d/01-ldap-authtok.conf";
owner = "root";
group = "root";
mode = "0600";
};
# Restart SSSD when the credential drop-in changes. agenix writes secrets in
# a system activation script that runs before systemd (re)starts services on
# a `switch`, so the file is present by the time sssd starts; the trigger
# picks up rotations of the bind password.
systemd.services.sssd.restartTriggers = [ config.age.secrets.ldap-bind.path ];
# Create home directories on first login for LDAP users (they have no
# locally-provisioned home). NixOS wires nss + the SSSD PAM stack when
# services.sssd.enable is true; mkHomeDir adds pam_mkhomedir to it.
security.pam.services.login.makeHomeDir = true;
security.pam.services.sshd.makeHomeDir = true;
};
}
+2 -2
View File
@@ -7,8 +7,8 @@
let let
cfg = config.features.swayDesktop; cfg = config.features.swayDesktop;
# Catppuccin Mocha (shared with the Sway desktop, see lyrathorpe/home/sway.nix). # Catppuccin Mocha (shared with the Sway desktop, see home/sway.nix).
ctp = import ./catppuccin-mocha.nix; ctp = import ../lib/catppuccin-mocha.nix;
in in
{ {
# The features.swayDesktop.enable option is declared in # The features.swayDesktop.enable option is declared in
+38
View File
@@ -0,0 +1,38 @@
# System user accounts, built from the registry (users/registry.nix) for the
# host's `hostUsers` set. See README "Users".
{
config,
pkgs,
lib,
hostUsers,
userRegistry,
...
}:
{
programs.zsh.enable = true;
users.users = lib.mapAttrs (
name: spec:
let
id = userRegistry.${name};
in
{
isNormalUser = true;
home = "/home/${name}";
description = id.fullName;
inherit (id) extraGroups;
openssh.authorizedKeys.keys = id.sshAuthorizedKeys;
shell = pkgs.zsh;
}
# linger opt-in (host table); left unmanaged when unset.
// lib.optionalAttrs (spec ? linger) { inherit (spec) linger; }
) hostUsers;
programs.firefox = lib.mkIf (config.features.swayDesktop.enable == true) {
enable = true;
};
programs.thunderbird = lib.mkIf (config.features.swayDesktop.enable == true) {
enable = true;
};
}
+92
View File
@@ -0,0 +1,92 @@
# Secrets (agenix)
Encrypted secrets for the fleet, managed with [agenix](https://github.com/ryantm/agenix).
Each secret is an age-encrypted file (`*.age`) encrypted to a set of recipient
public keys declared in [`secrets.nix`](./secrets.nix). A host decrypts its
secrets at activation using its SSH **host** key
(`/etc/ssh/ssh_host_ed25519_key`), so every host that must read a secret has to
be listed as a recipient for it.
`secrets.nix` is read only by the `agenix` CLI. It is never imported into the
NixOS evaluation.
## Secrets in this repo
| File | Purpose | Recipients |
| --------------- | ----------------------------------------------------------------------- | ----------------------------------- |
| `ldap-bind.age` | SSSD → Authentik LDAP bind credential, as an `sssd.conf` drop-in snippet | all SSSD-enabled hosts (not EDaaS) |
Consumed by [`modules/sssd.nix`](../modules/sssd.nix) via
`age.secrets.ldap-bind.path`, which places the decrypted snippet at
`/etc/sssd/conf.d/01-ldap-authtok.conf`.
> **`ldap-bind.age` is not committed yet.** Only `ldap-bind.age.PLACEHOLDER`
> ships in this change (real host recipient keys and the real password were not
> available when it was written). Follow the steps below to create the real
> secret, then delete the `.PLACEHOLDER`.
## Owner setup checklist
Run these once (per new host or when the bind password rotates):
### 1. Collect host recipient keys
On each SSSD-enabled host (all Linux hosts **except** EDaaS):
```sh
cat /etc/ssh/ssh_host_ed25519_key.pub
```
Paste each value into the matching placeholder in `secrets.nix`, replacing the
`AAAA_PLACEHOLDER_REPLACE_ME_*` strings. (Optionally uncomment and set `admin`
to an operator user key so the secret can be edited off-host.)
### 2. Encrypt the bind password
The plaintext must be a **full sssd.conf drop-in snippet**, because SSSD cannot
read `ldap_default_authtok` from a separate file — it only merges `conf.d/*.conf`.
The content is exactly:
```ini
[domain/default]
ldap_default_authtok = <the sssd-bind service-account password>
```
Use the password of the `sssd-bind` (Terraform: `sssd-bind`) Authentik LDAP
service account. Then, from the repo root:
```sh
# Requires the agenix CLI: `nix run github:ryantm/agenix -- -e secrets/ldap-bind.age`
cd secrets
agenix -e ldap-bind.age
```
An `$EDITOR` opens; paste the two-line snippet above, save, quit. agenix writes
the encrypted `ldap-bind.age`. Commit it and delete `ldap-bind.age.PLACEHOLDER`.
### 3. Rekey after changing recipients
If you add/remove hosts in `secrets.nix`, re-encrypt every secret to the new
recipient set:
```sh
cd secrets
agenix -r
```
### 4. DNS
`ldap.lyrapup.pet` must resolve to the Authentik LDAP outpost and serve LDAPS on
port 636 with a certificate the hosts trust (`ldap_tls_reqcert = demand`). If the
cert is not from a system-trusted CA, add it to the hosts' trust store
(`security.pki.certificateFiles`) or relax `ldap_tls_reqcert` in
`modules/sssd.nix`.
### 5. Rebuild
```sh
sudo nixos-rebuild switch --flake .#<host>
```
Verify with `getent passwd <ldap-user>` and `id <ldap-user>`.
+21
View File
@@ -0,0 +1,21 @@
THIS IS A PLACEHOLDER, NOT A REAL AGE SECRET.
The real secrets/ldap-bind.age is produced by the repo owner with `agenix -e`
(see secrets/README.md) and is a binary age-encrypted blob. It is intentionally
NOT committed here because:
* the real host age recipients are not available to the author of this change
(they are each host's /etc/ssh/ssh_host_ed25519_key.pub), and
* fabricating an encrypted blob or fake host keys would be misleading.
Committing this file as `ldap-bind.age` would let modules/sssd.nix reference
`../secrets/ldap-bind.age` and evaluate, but SSSD would fail to decrypt it at
runtime. Do ONE of the following before deploying:
1. Preferred: generate the real secret (secrets/README.md), commit it as
secrets/ldap-bind.age, and delete this .PLACEHOLDER file.
The decrypted plaintext must be a valid sssd.conf drop-in (NOT the bare
password):
[domain/default]
ldap_default_authtok = <the sssd-bind service-account password>
+15
View File
@@ -0,0 +1,15 @@
let
lyrathorpe-mbp = "ssh-ed25519 AAAA_PLACEHOLDER_REPLACE_ME_mbp";
lyrathorpe-t400 = "ssh-ed25519 AAAA_PLACEHOLDER_REPLACE_ME_t400";
lyrathorpe-macpro31 = "ssh-ed25519 AAAA_PLACEHOLDER_REPLACE_ME_macpro31";
lyrathorpe-rpi5 = "ssh-ed25519 AAAA_PLACEHOLDER_REPLACE_ME_rpi5";
sssdHosts = [
lyrathorpe-mbp
lyrathorpe-t400
lyrathorpe-macpro31
lyrathorpe-rpi5
];
in
{
"ldap-bind.age".publicKeys = sssdHosts;
}
-19
View File
@@ -1,19 +0,0 @@
# Key-only SSH hardening, imported by the hosts that run sshd (T400, Mac Pro).
# The host config still does `services.openssh.enable = true` and opens port 22
# next to where it documents the listening service; this module only tightens
# the policy and installs the authorized key, so a host opting into sshd cannot
# accidentally ship password/root login.
{ username, ... }:
{
services.openssh.settings = {
PasswordAuthentication = false; # keys only
KbdInteractiveAuthentication = false; # no keyboard-interactive fallback
PermitRootLogin = "no";
};
# The key permitted to log in as the primary user. Add more entries here as
# new client machines are provisioned.
users.users.${username}.openssh.authorizedKeys.keys = [
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIPDxHvdMTOzpFWUFMtCP7C/4tIOUO3GIO2QPvaifSnWH lyrathorpe@Lyra-MBA"
];
}
@@ -1,6 +1,11 @@
# Home-manager module for the work (EDaaS/WSL) profile: corporate git signing, # Work (EDaaS/WSL) home profile: corporate toolchain + tmux tweaks. Git identity
# work toolchain packages and tmux tweaks. Imported only by the work host. # comes from the registry (users/registry.nix), not here.
{ pkgs, lib, ... }: {
pkgs,
lib,
inputs,
...
}:
{ {
# Host-scoped extras for this machine only (the EDaaS/WSL host). # Host-scoped extras for this machine only (the EDaaS/WSL host).
@@ -12,15 +17,6 @@
# programs.ssh (shell.nix) take it over. The ssh-agent below still runs. # programs.ssh (shell.nix) take it over. The ssh-agent below still runs.
programs.ssh.enable = lib.mkForce false; programs.ssh.enable = lib.mkForce false;
programs.git = {
settings = {
commit.gpgsign = true;
tag.gpgsign = true;
gpg.format = "ssh";
user.signingkey = "key::ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIAJMVgeRKnfX1G8coU3nAobI485aeUpGTMqH7+zbKI8o emma.thorpe@cloud.com";
user.email = "emma.thorpe@citrix.com";
};
};
home.packages = [ home.packages = [
pkgs.kubectl pkgs.kubectl
pkgs.argo-rollouts pkgs.argo-rollouts
@@ -33,7 +29,6 @@
pkgs.powershell pkgs.powershell
pkgs.nuget pkgs.nuget
pkgs.gedit pkgs.gedit
pkgs.lens
pkgs.python3 pkgs.python3
pkgs.gnumake pkgs.gnumake
pkgs.gcc pkgs.gcc
@@ -57,8 +52,10 @@
docker = "/run/current-system/sw/bin/docker"; docker = "/run/current-system/sw/bin/docker";
}; };
programs.tmux = { programs.tmux = {
# kube context/namespace in the status line. kube-tmux is pinned as a flake
# input (it is not in nixpkgs), so the script is always present in the store.
extraConfig = '' extraConfig = ''
set -g status-right "#(/run/current-system/sw/bin/bash $HOME/code/kube-tmux/kube.tmux 250 red black)" set -g status-right "#(${pkgs.bash}/bin/bash ${inputs.kube-tmux}/kube.tmux 250 red black)"
''; '';
}; };
programs.go = { programs.go = {
@@ -66,7 +63,7 @@
}; };
# LSP servers only relevant to work: C# (omnisharp) and Helm charts (helm_ls). # LSP servers only relevant to work: C# (omnisharp) and Helm charts (helm_ls).
# The shared editor (lyrathorpe/home/editor.nix) carries the universal ones; # The shared editor (home/editor.nix) carries the universal ones;
# these are gated to this host so the heavy omnisharp closure stays off the # these are gated to this host so the heavy omnisharp closure stays off the
# personal machines. Tree-sitter grammars (highlighting) remain global there. # personal machines. Tree-sitter grammars (highlighting) remain global there.
programs.nixvim.plugins.lsp.servers = { programs.nixvim.plugins.lsp.servers = {
+17
View File
@@ -0,0 +1,17 @@
# Lyra's personal home extras, imported on her hosts (not the work box). Keeps
# personal data out of the shared home/ modules. See README "Users".
{ pkgs, lib, ... }:
{
# Personal ssh host shortcut.
programs.ssh.settings."dockerpi.inf.cbg.emmaisvery.gay" = {
User = "emmathorpe";
};
# Night-light location for gammastep (the service itself is enabled by
# home/sway.nix on graphical hosts). Linux-guarded so Darwin, which imports
# this module but has no gammastep, skips it.
services.gammastep = lib.mkIf pkgs.stdenv.hostPlatform.isLinux {
latitude = 51.5;
longitude = -0.13;
};
}
+28
View File
@@ -0,0 +1,28 @@
# User identity registry -- pure data, keyed by username. See README "Users".
# (`identity.username` is injected by mkHost, so it is not repeated here.)
{
lyrathorpe = {
fullName = "Lyra Thorpe";
email = "iam@emmathe.dev";
extraGroups = [
"wheel"
"docker"
];
sshAuthorizedKeys = [
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIPDxHvdMTOzpFWUFMtCP7C/4tIOUO3GIO2QPvaifSnWH lyrathorpe@Lyra-MBA"
];
signingKey = "key::ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIPDxHvdMTOzpFWUFMtCP7C/4tIOUO3GIO2QPvaifSnWH lyrathorpe@Lyra-MBA";
};
emmathorpe = {
fullName = "Emma Thorpe";
email = "emma.thorpe@citrix.com";
extraGroups = [
"wheel"
"docker"
];
# No personal key on file yet; add one if SSH login as emmathorpe is wanted.
sshAuthorizedKeys = [ ];
signingKey = "key::ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIAJMVgeRKnfX1G8coU3nAobI485aeUpGTMqH7+zbKI8o emma.thorpe@cloud.com";
};
}