NixOS Module & Options Design Prompt
Design a clean NixOS module with typed options, sensible defaults, and assertions so a service is configured declaratively and consumers can't set it into an invalid state.
- Target user
- Engineers packaging services as reusable NixOS modules
- Difficulty
- Advanced
- Tools
- Claude, ChatGPT, Cursor
The prompt
You are a senior Nix engineer who writes NixOS modules that other people configure through clean, typed options instead of copy-pasting raw config. I will provide: - The service or capability I want to expose as a module (e.g. [a daemon, a backup job, a reverse proxy]). - The settings consumers should be able to tune. - The target: NixOS system module (and whether it should also work as a Home Manager module). Your job: 1. **Design the options tree** — define `options.services.<name>` with proper `mkOption` types (`types.bool`, `types.port`, `types.submodule`, `types.listOf`, etc.), each with a `description`, a `default`, and an `example`. 2. **Set safe defaults** — choose defaults that are secure and non-surprising (service disabled until `enable = true`, no open firewall unless asked, least-privilege user). 3. **Implement `config` with `mkIf`** — gate everything behind `cfg.enable` so the module is inert when unused, and use `mkDefault`/`mkForce` deliberately where override precedence matters. 4. **Add assertions** — write `assertions` and `warnings` that catch invalid combinations at eval time (e.g. TLS enabled but no cert path) with actionable messages. 5. **Wire systemd correctly** — define the `systemd.services` unit with hardening options (`DynamicUser`, `ProtectSystem`, `NoNewPrivileges`) where appropriate. 6. **Show consumer usage** — give the minimal `configuration.nix` snippet that enables the module and one fuller example. Output as: (a) the module source with comments, (b) the options reference table (name, type, default, description), (c) consumer usage examples, (d) the assertions and what invalid state each prevents. Do not run a rebuild. Provide the `nixos-rebuild build` (not `switch`) command so the config can be evaluated and built without activating it, and note that `switch` should follow human review.
Why this prompt works
A NixOS module is an API. The difference between a module people enjoy using and one they dread is entirely in the options design: typed mkOption declarations with descriptions, defaults, and examples turn an opaque blob of config into something self-documenting and discoverable through nixos-option. This prompt makes the options tree the first deliverable precisely because most hand-written modules skip the types and descriptions, leaving consumers to read the source to understand what they can set — which defeats the entire point of a declarative module system.
The mkIf cfg.enable and assertions requirements encode the two disciplines that separate a robust module from a fragile one. Gating all config behind enable keeps the module inert until explicitly turned on, so importing it costs nothing — essential for modules shipped in a shared flake. Assertions and warnings move whole classes of misconfiguration from runtime to eval time: “TLS enabled but no certificate path” should fail when you build, with a message that tells you what to fix, not when the daemon crashes on boot. That eval-time validation is one of Nix’s genuine advantages over imperative config management, and this prompt makes the model actually use it.
The build-not-switch guardrail matters because Nix’s reputation for safety can lull you into skipping review. nixos-rebuild build evaluates and builds the configuration without activating it, surfacing type errors and failed assertions without touching the running system; only after human review should switch activate it. The systemd hardening options (DynamicUser, ProtectSystem) tie the module to least-privilege defaults so security is structural, not bolted on. Pair this with the Nix flakes prompt and the Devbox prompt, and browse the IaC category for more reproducible-infrastructure tooling.
Related prompts
-
Devbox Reproducible Dev Environments Prompt
Stand up reproducible, isolated developer environments with Devbox (Nix under the hood) — pinned toolchains, per-project shells, init scripts, and CI parity — without forcing the team to learn Nix.
-
Nix Flakes Reproducible Infrastructure Prompt
Use Nix flakes to pin reproducible build/dev environments and declarative server config (NixOS / nixos-rebuild / deploy-rs) so 'works on my machine' and drift both disappear.