My nix-darwin and NixOS config
3
fork

Configure Feed

Select the types of activity you want to include in your feed.

refactor: migrate to native module system, replace ragenix with sops-nix, expand server stack

- Move all configuration defaults to `modules/options.nix`
- Remove custom `cfgLib` abstraction; use `config.myConfig.*` / `osConfig.myConfig.*`
- Update README and docs to reflect new architecture and workflows
- Replace ragenix with sops-nix (age via host SSH key, .sops.yaml rules)
- Add server modules: matrix, forgejo, cloudflare-tunnel, cockpit
- Expand Caddy routing for PDS, Matrix, and Forgejo
- Declare static cloudflared user/group for sops-nix compatibility
- Simplify repo structure (remove settings/config, streamline home/)
- Update documentation references and maintenance instructions

BREAKING CHANGE: configuration is no longer imported via `settings/config/` or `cfgLib`; all options now live in `modules/options.nix` and are accessed through the standard NixOS module system.

+139 -260
+62 -121
README.md
··· 4 4 5 5 > **Note:** This is a personal configuration repository. While you're welcome to use it as reference, it's specifically tailored to my needs and setup. 6 6 7 - > **๐ŸŽฏ Quick Start for Forkers:** Edit `settings/config/` files to customise everything โ€” username, email, git settings, desktop theme, packages, and more. 7 + > **๐ŸŽฏ Quick Start for Forkers:** Edit `modules/options.nix` to customise everything โ€” username, email, git settings, desktop theme, packages, and more. Per-host overrides go in `hosts/<hostname>/default.nix`. 8 8 9 9 ## Key Features 10 10 11 - โœจ **Centralized Configuration** - All settings in `settings/config/` (single source of truth) 12 - ๐Ÿ”„ **DRY Principles** - Zero duplication, config imported once via `lib/` 13 - ๐ŸŽฏ **Easy Customization** - Change any setting in one file, applies everywhere 11 + โœจ **Centralized Configuration** - All option defaults in `modules/options.nix` (single source of truth) 12 + ๐Ÿ”„ **DRY Principles** - Zero duplication; the NixOS module system handles everything 13 + ๐ŸŽฏ **Easy Customization** - Change any default in one file, applies everywhere 14 14 ๐Ÿ“ฆ **Multi-System** - Unified config for NixOS and macOS 15 15 ๐Ÿ  **Unified Home Manager** - Same shell, git, SSH config across all systems 16 - ๐Ÿ” **Secrets Management** - Encrypted secrets with ragenix 17 - ๐Ÿ› ๏ธ **Reusable Helpers** - Custom library with common functions 16 + ๐Ÿ” **Secrets Management** - Encrypted secrets with sops-nix 17 + ๐Ÿ› ๏ธ **Rust Tools** - `health-check`, `flake-bump`, `gen-diff` maintenance utilities 18 18 19 19 ## Managed Systems 20 20 ··· 25 25 ### Linux (NixOS) - SECONDARY 26 26 27 27 - **laptop** - Dell Inspiron 3501 with KDE Plasma 6 โ€” Secondary workstation 28 - - **server** - Minimal headless server โ€” Bluesky PDS + hardened security (configuration complete, pending hardware deployment) 28 + - **server** - Minimal headless server โ€” Bluesky PDS, Matrix, Forgejo, Cloudflare tunnel + hardened security 29 29 30 30 ## Repository Structure 31 31 ··· 33 33 . 34 34 โ”œโ”€โ”€ flake.nix # Main flake โ€” defines all hosts 35 35 โ”œโ”€โ”€ flake.lock # Locked dependency versions 36 - โ”‚ 37 - โ”œโ”€โ”€ lib/ # โญ Custom library (DRY helpers) 38 - โ”‚ โ”œโ”€โ”€ default.nix # cfgLib: reusable functions and config singleton 39 - โ”‚ โ””โ”€โ”€ USAGE.md # Developer guide 40 36 โ”‚ 41 37 โ”œโ”€โ”€ hosts/ # Host-specific configurations 42 38 โ”‚ โ”œโ”€โ”€ laptop/ # Dell Inspiron 3501 (NixOS + KDE Plasma 6) ··· 44 40 โ”‚ โ””โ”€โ”€ macmini/ # Mac Mini M2 (nix-darwin) 45 41 โ”‚ 46 42 โ”œโ”€โ”€ modules/ # Reusable system modules 47 - โ”‚ โ”œโ”€โ”€ common.nix # Base NixOS settings 43 + โ”‚ โ”œโ”€โ”€ options.nix # โญ All option declarations + defaults 44 + โ”‚ โ”œโ”€โ”€ common.nix # Base NixOS settings (gc, auto-upgrade, etc.) 48 45 โ”‚ โ”œโ”€โ”€ desktop.nix # KDE Plasma 6 + SDDM 49 46 โ”‚ โ”œโ”€โ”€ gaming.nix # Steam + Gamemode 50 47 โ”‚ โ”œโ”€โ”€ packages.nix # Desktop system packages ··· 52 49 โ”‚ โ”œโ”€โ”€ users.nix # User account configuration 53 50 โ”‚ โ”œโ”€โ”€ caddy.nix # Caddy web server 54 51 โ”‚ โ”œโ”€โ”€ pds.nix # Bluesky ATProto PDS 52 + โ”‚ โ”œโ”€โ”€ matrix.nix # Matrix Synapse 53 + โ”‚ โ”œโ”€โ”€ forgejo.nix # Forgejo git forge 54 + โ”‚ โ”œโ”€โ”€ cloudflare-tunnel.nix # Cloudflare tunnel (outbound-only) 55 + โ”‚ โ”œโ”€โ”€ cockpit.nix # Cockpit web console 55 56 โ”‚ โ”œโ”€โ”€ ssh-keys.nix # Public key registry for all hosts 56 57 โ”‚ โ”œโ”€โ”€ server/ # Headless server sub-modules 57 - โ”‚ โ”‚ โ”œโ”€โ”€ default.nix # Imports all server sub-modules 58 58 โ”‚ โ”‚ โ”œโ”€โ”€ firewall.nix 59 59 โ”‚ โ”‚ โ”œโ”€โ”€ intrusion.nix # fail2ban 60 60 โ”‚ โ”‚ โ”œโ”€โ”€ ssh.nix # sshd hardening ··· 74 74 โ”‚ โ””โ”€โ”€ server-hardened.nix # Security hardening 75 75 โ”‚ 76 76 โ”œโ”€โ”€ home/ # Home Manager (unified across all hosts) 77 - โ”‚ โ”œโ”€โ”€ home.nix # Main entry point 78 - โ”‚ โ”œโ”€โ”€ configs/ # Raw config files (fastfetch, starship) 79 - โ”‚ โ”œโ”€โ”€ programs/ # Per-program config (git, zsh, ssh, vscode, kde, ...) 80 - โ”‚ โ””โ”€โ”€ scripts/ # Shell scripts on PATH 81 - โ”‚ โ”œโ”€โ”€ verify-tailscale-ssh 82 - โ”‚ โ”œโ”€โ”€ update-all 83 - โ”‚ โ”œโ”€โ”€ update-everything 84 - โ”‚ โ””โ”€โ”€ relts 77 + โ”‚ โ”œโ”€โ”€ default.nix # Main entry point 78 + โ”‚ โ””โ”€โ”€ programs/ # Per-program config (git, zsh, ssh, vscode, kde, ...) 85 79 โ”‚ 86 - โ”œโ”€โ”€ settings/ # โญ Centralized configuration โ€” edit here 87 - โ”‚ โ”œโ”€โ”€ config.nix # Entry point (imports config/) 88 - โ”‚ โ”œโ”€โ”€ config/ # All configurable values (one file per domain) 89 - โ”‚ โ”œโ”€โ”€ plasma/ # KDE Plasma declarative settings 90 - โ”‚ โ””โ”€โ”€ darwin/ # macOS system defaults 80 + โ”œโ”€โ”€ settings/ # Platform-specific declarative settings 81 + โ”‚ โ”œโ”€โ”€ darwin/ # macOS system.defaults (Dock, Finder, trackpad, etc.) 82 + โ”‚ โ””โ”€โ”€ plasma/ # KDE Plasma declarative settings 91 83 โ”‚ 92 - โ”œโ”€โ”€ secrets/ # Encrypted secrets (ragenix / age) 93 - โ”‚ โ”œโ”€โ”€ secrets.nix # Public key mappings (users + systems) 84 + โ”œโ”€โ”€ secrets/ # sops-encrypted secrets (safe to commit) 94 85 โ”‚ โ”œโ”€โ”€ setup.sh # Key management helper 95 - โ”‚ โ””โ”€โ”€ age/*.age # Encrypted secret files 86 + โ”‚ โ””โ”€โ”€ *.env / *.json / ... # Encrypted secret files 96 87 โ”‚ 97 88 โ”œโ”€โ”€ tools/ # Rust maintenance tools 98 89 โ”‚ โ””โ”€โ”€ src/bin/ # health-check, flake-bump, gen-diff 99 - โ”œโ”€โ”€ wallpapers/ 100 - โ””โ”€โ”€ docs/ 90 + โ””โ”€โ”€ wallpapers/ 101 91 ``` 102 92 103 - ## DRY Architecture 93 + ## Configuration Architecture 104 94 105 - This config uses a custom library (`lib/default.nix`) to eliminate repetition: 95 + All options are declared with typed defaults in `modules/options.nix`. Every system module reads values via `config.myConfig.*`; home-manager modules use `osConfig.myConfig.*`. No custom abstraction layer โ€” it's plain NixOS module system. 106 96 107 - - **Single config import**: Config is imported once in `lib/`, not 20+ times across modules 108 - - **Reusable helpers**: Common functions like `resolvePackages` and `mkAuthorizedKeys` 109 - - **Zero boilerplate**: Every module automatically gets `cfgLib` via `specialArgs` 110 - 111 - **Before (every module):** 97 + **To change a value for all hosts:** 112 98 ```nix 113 - { config, pkgs, lib, ... }: 114 - let 115 - cfg = import ../settings/config.nix; 116 - # Duplicate package resolution logic... 117 - in 118 - { ... } 99 + # modules/options.nix 100 + timeZone = mkOption { 101 + type = str; 102 + default = "Europe/London"; # โ† change here 103 + }; 119 104 ``` 120 105 121 - **After (using cfgLib):** 106 + **To override for one host:** 122 107 ```nix 123 - { config, pkgs, lib, cfgLib, ... }: 124 - let 125 - cfg = cfgLib.cfg; # Config already imported! 126 - resolve = cfgLib.resolvePackages pkgs; # Reusable helper 127 - in 128 - { ... } 108 + # hosts/laptop/default.nix 109 + myConfig.gaming.enable = true; 110 + myConfig.isDesktop = true; 129 111 ``` 130 112 131 - See [`lib/USAGE.md`](lib/USAGE.md) for details on using `cfgLib` helpers. 132 - 133 - ## Customization 134 - 135 - **All settings live in `settings/config/`** โ€” one file per domain, each small and focused. 136 - 137 - ```bash 138 - # Examples 139 - nano settings/config/user.nix # Username, email, shell 140 - nano settings/config/packages.nix # Add/remove packages 141 - nano settings/config/desktop.nix # Theme, fonts, KDE settings 142 - nano settings/config/darwin.nix # macOS packages, Homebrew, keyboard 143 - ``` 144 - 145 - See [`settings/config/README.md`](settings/config/README.md) for the full map. 113 + See [`lib/USAGE.md`](lib/USAGE.md) for patterns used in modules. 146 114 147 115 ## Quick Start 148 116 ··· 178 146 sudo darwin-rebuild switch --flake .#macmini 179 147 ``` 180 148 181 - ## Settings Management 182 - 183 - ### KDE Plasma (Linux) 149 + ## Customization 184 150 185 - KDE Plasma settings are managed declaratively via `plasma-manager` in: 186 - - `home/programs/kde.nix` - User-level Plasma configuration 187 - - `settings/plasma/default.nix` - Desktop layout and behavior preferences 188 - 189 - Changes are applied automatically on every Home Manager activation. To customize Plasma settings, edit these files directly rather than using the GUI. 190 - 191 - ### macOS 192 - 193 - Export your current macOS defaults: 151 + **All defaults live in `modules/options.nix`** โ€” one option block per domain. 194 152 195 153 ```bash 196 - ./settings/darwin-export.sh 154 + # Examples of what to edit 155 + nano modules/options.nix # Username, timezone, packages, themes, etc. 156 + nano hosts/laptop/default.nix # Enable gaming, desktop mode, etc. 157 + nano hosts/server/default.nix # Enable server services 158 + nano settings/darwin/default.nix # macOS Dock, Finder, trackpad 159 + nano settings/plasma/default.nix # KDE Plasma layout and behaviour 197 160 ``` 198 161 162 + See [`docs/settings.md`](docs/settings.md) for the full guide and [`docs/settings-config.md`](docs/settings-config.md) for the complete option reference. 163 + 199 164 ## Maintenance 200 165 201 166 ### Health Check (Recommended Before Building) 202 - 203 - Run the health check script to validate your config before rebuilding: 204 167 205 168 ```bash 206 169 # Compile the tools (one-time) ··· 213 176 health-check 214 177 ``` 215 178 216 - The health check validates: 217 - - Nix daemon is responding 218 - - flake.lock is valid 219 - - Config evaluates cleanly 220 - - Age keys are present 221 - - SSH keys are configured 222 - - Disk space is sufficient 223 - - Git tree status 224 - 225 179 ### Update Flake Inputs 226 180 227 181 ```bash 228 - # Update all inputs 229 182 nix flake update 230 - 231 - # Or use the helper 232 - flake-bump 233 - 234 183 # Then rebuild 235 - sudo nixos-rebuild switch --flake .#laptop # or darwin-rebuild 184 + sudo nixos-rebuild switch --flake .#laptop 185 + # or 186 + nix run .#tools -- flake-bump 236 187 ``` 237 188 238 189 ### Garbage Collection 239 190 240 191 ```bash 241 - # NixOS (auto-runs weekly โ€” see settings/config/nix.nix) 242 - sudo nix-collect-garbage -d 243 - 244 - # macOS 192 + # Runs automatically weekly on NixOS (configured in modules/common.nix) 245 193 sudo nix-collect-garbage -d 246 - sudo darwin-rebuild switch --flake .#macmini 247 194 248 - # Or use the shell alias 195 + # Or use the alias 249 196 cleanup 250 197 ``` 251 198 252 - ### Compare Generations 253 - 254 - ```bash 255 - # See what changed between generations 256 - gen-diff 257 - ``` 258 - 259 199 ## Secrets Management 260 200 261 - Uses [ragenix](https://github.com/yaxitech/ragenix) for encrypted secrets. 201 + Uses [sops-nix](https://github.com/Mic92/sops-nix) with age encryption. 262 202 263 - - Secrets are encrypted with age using SSH keys 264 - - Run `bash ./secrets/setup.sh` to initialise keys 265 - - Master key stored at `~/.config/age/keys.txt` โ€” **never commit this** 266 - - Encrypted `.age` files are safe to commit 267 - - Add new secrets to `settings/config/secrets.nix` โ†’ `files` list 203 + - Secrets are encrypted with age using the host's SSH ed25519 host key 204 + - Encrypted files in `secrets/` are safe to commit 205 + - The key inventory and creation rules are in `.sops.yaml` 206 + - Decrypted at activation via `/etc/ssh/ssh_host_ed25519_key` 268 207 269 208 See [docs/secrets.md](docs/secrets.md) for full details. 270 209 ··· 284 223 | [nixpkgs](https://github.com/NixOS/nixpkgs) | nixos-25.11 | 285 224 | [home-manager](https://github.com/nix-community/home-manager) | release-25.11 | 286 225 | [nix-darwin](https://github.com/LnL7/nix-darwin) | nix-darwin-25.11 | 287 - | [ragenix](https://github.com/yaxitech/ragenix) | latest | 226 + | [sops-nix](https://github.com/Mic92/sops-nix) | latest | 227 + | [plasma-manager](https://github.com/nix-community/plasma-manager) | latest | 288 228 289 229 ## Unified Configuration Benefits 290 230 ··· 304 244 ## Documentation 305 245 306 246 ### Core Documentation 307 - - [`lib/USAGE.md`](lib/USAGE.md) โ€” using the cfgLib helpers *(for developers)* 308 - - [`docs/settings-config.md`](docs/settings-config.md) โ€” full settings reference *(start here)* 309 - - [`docs/REFERENCE.md`](docs/REFERENCE.md) โ€” quick-reference card 247 + - [`lib/USAGE.md`](lib/USAGE.md) โ€” module patterns for developers 248 + - [`docs/settings.md`](docs/settings.md) โ€” how configuration works *(start here)* 249 + - [`docs/settings-config.md`](docs/settings-config.md) โ€” full option reference 250 + - [`docs/REFERENCE.md`](docs/REFERENCE.md) โ€” quick-reference command card 310 251 311 252 ### Host Management 312 - - [`docs/hosts.md`](docs/hosts.md) โ€” hosts documentation index *(start here)* 253 + - [`docs/hosts.md`](docs/hosts.md) โ€” hosts documentation index 313 254 - [`docs/hosts-overview.md`](docs/hosts-overview.md) โ€” complete comparison of all three hosts 314 255 - [`docs/hosts-modification.md`](docs/hosts-modification.md) โ€” how to modify and add hosts 315 256 - [`docs/hosts-laptop.md`](docs/hosts-laptop.md) โ€” Dell Inspiron 3501 (NixOS + KDE Plasma 6) 316 - - [`docs/hosts-server.md`](docs/hosts-server.md) โ€” headless server + Bluesky PDS setup 257 + - [`docs/hosts-server.md`](docs/hosts-server.md) โ€” headless server setup 317 258 - [`docs/hosts-macmini.md`](docs/hosts-macmini.md) โ€” macOS with nix-darwin 318 259 - [`docs/TAILSCALE-SSH.md`](docs/TAILSCALE-SSH.md) โ€” inter-host SSH over Tailscale 319 260
+2
docs/hosts-laptop.md
··· 264 264 # Edit fonts, theme, Konsole profile, etc. 265 265 ``` 266 266 267 + Changes are applied on the next `nixos-rebuild switch`. 268 + 267 269 **GUI settings**: 268 270 While Plasma settings are declarative, you can still use the GUI to preview changes. However, to make them permanent, you must translate them to Nix configuration. The `plasma-manager` module ensures reproducibility. 269 271
+6 -2
docs/hosts-overview.md
··· 90 90 - โœ… Auto-upgrades (daily) 91 91 - โœ… SMART disk monitoring 92 92 - โœ… Minimal package set 93 - - โœ… Bluesky PDS + Caddy + cloudflared 93 + - โœ… Bluesky PDS + Matrix Synapse + Forgejo + Caddy + cloudflared 94 94 - โŒ No GUI, no gaming, no multimedia 95 95 96 96 **Status**: Configuration complete, hardware not yet provisioned. See [hosts-server.md](hosts-server.md) for the deploy runbook. ··· 148 148 | `gaming.nix` | โœ… | โŒ | โŒ | Steam, Gamemode | 149 149 | `caddy.nix` | โŒ | โœ… | โŒ | Caddy web server | 150 150 | `pds.nix` | โŒ | โœ… | โŒ | Bluesky PDS | 151 + | `matrix.nix` | โŒ | โœ… | โŒ | Matrix Synapse | 152 + | `forgejo.nix` | โŒ | โœ… | โŒ | Forgejo git forge | 153 + | `cloudflare-tunnel.nix` | โŒ | โœ… | โŒ | Cloudflare tunnel | 154 + | `cockpit.nix` | โŒ | โœ… | โŒ | Cockpit web console | 151 155 | `server/default.nix` | โŒ | โœ… | โŒ | Server sub-modules (firewall, fail2ban, sshd, ...) | 152 156 | `profiles/server-hardened.nix` | โŒ | โœ… | โŒ | Security hardening | 153 157 | `darwin/common.nix` | โŒ | โŒ | โœ… | macOS Nix settings | ··· 206 210 config.age.secrets.<name>.path (decrypted at runtime) 207 211 ``` 208 212 209 - Available on hosts that import `modules/secrets.nix`. 213 + The host's `/etc/ssh/ssh_host_ed25519_key` is used as the age decryption key. Recipients and creation rules are declared in `.sops.yaml`. 210 214 211 215 ## Unified Home Manager 212 216
+11 -8
docs/hosts-server.md
··· 10 10 Internet โ†’ Cloudflare edge (TLS) 11 11 โ†“ encrypted tunnel (outbound from server) 12 12 cloudflared daemon 13 - โ†“ HTTP 14 - Caddy (127.0.0.1:2020) 15 - โ†“ age-assurance static responses (UK OSA) 16 - โ†“ reverse proxy 17 - bluesky-pds (127.0.0.1:3000) 13 + โ†“ HTTP (hostname-based routing) 14 + Caddy 15 + โ”œโ”€โ”€ pds.ewancroft.uk โ†’ bluesky-pds (127.0.0.1:3000) 16 + โ”œโ”€โ”€ matrix.ewancroft.uk โ†’ matrix-synapse (127.0.0.1:8008) 17 + โ””โ”€โ”€ git.ewancroft.uk โ†’ forgejo (127.0.0.1:3001) 18 18 ``` 19 19 20 20 No ports 80/443 need to be open in the firewall. SSH is the only public port. ··· 71 71 72 72 ### 3. Update the tunnel UUID in settings 73 73 74 - Edit `settings/config/pds.nix` and replace the placeholder UUID: 74 + Edit `modules/options.nix` and replace the placeholder UUID in the `cloudflare` block: 75 75 76 76 ```nix 77 77 cloudflare = { 78 - tunnelId = "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"; # โ† paste real UUID here 78 + tunnelId = mkOption { 79 + type = str; 80 + default = "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"; # โ† paste real UUID here 81 + }; 79 82 }; 80 83 ``` 81 84 ··· 200 203 | Handle domains | `.ewancroft.uk` | 201 204 | PDS port | `3000` (internal only) | 202 205 | Caddy port | `2020` (internal only) | 203 - | Tunnel ID | set in `settings/config/pds.nix` | 206 + | Tunnel ID | set in `modules/options.nix` โ†’ `myConfig.cloudflare.tunnelId` | 204 207 205 208 --- 206 209
-3
docs/secrets.md
··· 122 122 123 123 | File | Purpose | Accessible by | 124 124 |---|---|---| 125 - | `secrets/wifi-home` | Home WiFi passphrase | all hosts | 126 - | `secrets/ssh-passphrase` | SSH private key passphrase | all hosts | 127 125 | `secrets/docker-config.json` | Docker Hub credentials | all hosts | 128 126 | `secrets/claude.json` | Claude API / config | all hosts | 129 127 | `secrets/duckdns.tar.gz` | DuckDNS config bundle | all hosts | 130 128 | `secrets/pds.env` | Bluesky PDS runtime secrets | ewan + server | 131 129 | `secrets/matrix.env` | Matrix Synapse secrets | ewan + server | 132 130 | `secrets/forgejo.env` | Forgejo `SECRET_KEY` etc. | ewan + server | 133 - | `secrets/cloudflare.token` | Cloudflare API token | ewan + server | 134 131 | `secrets/cf-tunnel.json` | Cloudflare tunnel credentials | ewan + server | 135 132 136 133 ## Security rules
+45 -126
lib/USAGE.md
··· 1 - # Using cfgLib - Developer Guide 1 + # Module System โ€” Developer Guide 2 2 3 - ## Overview 3 + > **Note**: The `cfgLib` helper library has been removed. All configuration is now accessed directly through the standard NixOS module system via `config.myConfig.*` (system modules) or `osConfig.myConfig.*` (home-manager modules). No custom abstraction or manual wiring is needed. 4 4 5 - The `cfgLib` library is automatically available in all modules through `specialArgs`. You no longer need to manually import `settings/config.nix` in each module. 6 - 7 - ## Basic Usage 8 - 9 - ### Standard System Module 5 + ## Accessing config in system modules 10 6 11 7 ```nix 12 - { config, pkgs, lib, cfgLib, ... }: 13 - 8 + # modules/my-module.nix 9 + { config, pkgs, lib, ... }: 14 10 let 15 - cfg = cfgLib.cfg; # Get the central config 11 + cfg = config.myConfig; 16 12 in 17 13 { 18 - # Your module code here 19 - services.myservice.enable = cfg.myoption; 14 + time.timeZone = cfg.timeZone; 15 + users.users.${cfg.user.username} = { ... }; 20 16 } 21 17 ``` 22 18 23 - ### Home Manager Program Module 19 + ## Accessing config in home-manager modules 24 20 25 21 ```nix 26 - { config, pkgs, lib, cfgLib, ... }: 27 - 22 + # home/programs/my-program.nix 23 + { osConfig, ... }: 28 24 let 29 - cfg = cfgLib.cfg; 25 + cfg = osConfig.myConfig; 30 26 in 31 27 { 32 - programs.myprogram = { 33 - enable = true; 34 - setting = cfg.mysetting; 35 - }; 28 + programs.git.userEmail = cfg.user.email; 36 29 } 37 30 ``` 38 31 39 - ### Home Manager Program with Platform Detection 32 + ## Resolving packages from a list of names 40 33 41 - ```nix 42 - { isDarwin }: 43 - { config, pkgs, lib, cfgLib, ... }: 34 + The old `cfgLib.resolvePackages` helper is replaced by a simple inline expression using `builtins.filter` and `pkgs ? name`: 44 35 36 + ```nix 37 + { config, pkgs, lib, ... }: 45 38 let 46 - cfg = cfgLib.cfg; 39 + cfg = config.myConfig; 40 + resolve = names: 41 + map (n: pkgs.${n}) (builtins.filter (n: pkgs ? ${n}) names); 47 42 in 48 43 { 49 - programs.myprogram = { 50 - enable = true; 51 - # macOS-specific option 52 - option = lib.mkIf isDarwin cfg.macos.option; 53 - }; 44 + environment.systemPackages = resolve cfg.packages.common; 54 45 } 55 46 ``` 56 47 57 - ## Helper Functions 58 - 59 - ### 1. resolvePackages 48 + ## Authorized SSH keys 60 49 61 - Safely resolve package names, skipping any that don't exist: 50 + The `mkAuthorizedKeys` helper is replaced by the inline logic in `modules/users.nix`: 62 51 63 52 ```nix 64 - { config, pkgs, cfgLib, ... }: 65 - 66 53 let 67 - resolve = cfgLib.resolvePackages pkgs; 54 + allKeys = import ./ssh-keys.nix; 55 + authorizedKeys = lib.attrValues ( 56 + lib.filterAttrs (name: _: name != config.networking.hostName) allKeys 57 + ); 68 58 in 69 59 { 70 - environment.systemPackages = resolve [ 71 - "firefox" 72 - "vscode" 73 - "nonexistent-package" # Will be skipped with warning 74 - ]; 60 + users.users.ewan.openssh.authorizedKeys.keys = authorizedKeys; 75 61 } 76 62 ``` 77 63 78 - ### 2. mkAuthorizedKeys 64 + ## All option declarations 65 + 66 + All options and their defaults live in `modules/options.nix`. See [`docs/settings-config.md`](../docs/settings-config.md) for a full reference table. 79 67 80 - Get SSH authorized keys excluding the current host: 68 + ## Adding a new option 81 69 82 70 ```nix 83 - { config, cfgLib, ... }: 84 - 85 - { 86 - users.users.myuser = { 87 - openssh.authorizedKeys.keys = 88 - cfgLib.mkAuthorizedKeys config.networking.hostName; 71 + # 1. Declare it in modules/options.nix 72 + myNewThing = { 73 + enable = lib.mkOption { 74 + type = lib.types.bool; 75 + default = false; 76 + description = "Enable the new thing."; 89 77 }; 90 - } 91 - ``` 78 + }; 92 79 93 - ### 3. cfg (Central Config) 94 - 95 - Access any config value without importing: 96 - 97 - ```nix 98 - let 99 - cfg = cfgLib.cfg; 100 - in 101 - { 102 - # Instead of: import ../settings/config.nix 103 - # Just use: 104 - time.timeZone = cfg.system.timeZone; 105 - users.users.${cfg.user.username} = { ... }; 106 - programs.firefox.enable = cfg.packages.firefox.enable; 80 + # 2. Use it in a module 81 + lib.mkIf config.myConfig.myNewThing.enable { 82 + # ... 107 83 } 108 - ``` 109 - 110 - ## Complete Example 111 84 112 - Here's a complete module using cfgLib: 113 - 114 - ```nix 115 - { config, pkgs, lib, cfgLib, ... }: 116 - 117 - let 118 - cfg = cfgLib.cfg; 119 - resolve = cfgLib.resolvePackages pkgs; 120 - in 121 - { 122 - # Use config values 123 - services.myservice = { 124 - enable = cfg.myservice.enable; 125 - port = cfg.myservice.port; 126 - }; 127 - 128 - # Resolve packages safely 129 - environment.systemPackages = 130 - resolve cfg.myservice.packages 131 - ++ [ pkgs.myapp ]; 132 - 133 - # Access user config 134 - users.users.${cfg.user.username} = { 135 - extraGroups = [ "mygroup" ]; 136 - }; 137 - } 85 + # 3. Override per-host if needed 86 + # hosts/server/default.nix 87 + myConfig.myNewThing.enable = true; 138 88 ``` 139 - 140 - ## Migration Checklist 141 - 142 - When updating an old module to use cfgLib: 143 - 144 - 1. Add `cfgLib` to the module arguments: 145 - ```nix 146 - { config, pkgs, lib, cfgLib, ... }: # Add cfgLib here 147 - ``` 148 - 149 - 2. Replace config import: 150 - ```nix 151 - # Old: 152 - let cfg = import ../settings/config.nix; 153 - 154 - # New: 155 - let cfg = cfgLib.cfg; 156 - ``` 157 - 158 - 3. Use helpers where applicable: 159 - ```nix 160 - # Old: 161 - let 162 - toPkg = name: if pkgs ? ${name} then pkgs.${name} else null; 163 - resolve = names: filter (x: x != null) (map toPkg names); 164 - 165 - # New: 166 - let resolve = cfgLib.resolvePackages pkgs; 167 - ``` 168 - 169 - 4. Test with `nix flake check`
+13
modules/cloudflare-tunnel.nix
··· 44 44 in 45 45 lib.mkIf cfg.services.cloudflare.enable { 46 46 47 + # โ”€โ”€ User / group โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ 48 + # The cloudflared nixpkgs service uses DynamicUser at the systemd level and 49 + # does not create a static entry in config.users.users. We declare it here 50 + # so that sops-nix can resolve the owner/group at evaluation time and so 51 + # that the credentials file has a stable owner on disk. 52 + users.users.cloudflared = { 53 + isSystemUser = true; 54 + group = "cloudflared"; 55 + }; 56 + users.groups.cloudflared = { }; 57 + 47 58 # โ”€โ”€ Secret โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ 48 59 # JSON credentials file created by `cloudflared tunnel create server`. 49 60 # Encrypt with: sops --encrypt --age <age-pubkey> cf-tunnel.json > secrets/cf-tunnel.json ··· 51 62 sopsFile = ../secrets/cf-tunnel.json; 52 63 format = "binary"; 53 64 owner = "cloudflared"; 65 + group = "cloudflared"; # set explicitly โ€” cloudflared uses DynamicUser so the 66 + # user isn't in config.users.users without the block above 54 67 mode = "0400"; 55 68 }; 56 69