refactor: caddy extensions seperation from main module.#597
Conversation
…odular vhost Caddy config generation
…date migration plans
…ve option merging
|
Warning Review limit reached
More reviews will be available in 45 minutes and 54 seconds. Learn how PR review limits work. Your organization has used up its prepaid credits, and credit purchases are no longer available. Enable the review add-on in the billing tab to keep reviews running — you're only billed for reviews past your plan's rate limits ($0.25/file). ⌛ How to resolve this issue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based credits. 🚦 How do rate limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please see our Fair Usage Limits Policy for further information. ℹ️ Review info⚙️ Run configurationConfiguration used: Organization UI Review profile: ASSERTIVE Plan: Pro Run ID: 📒 Files selected for processing (2)
📝 WalkthroughWalkthroughAdds a proxy extension registry, migrates L4, Kanidm, dashboard, and Cloudflared behaviour into dedicated modules, and rewires proxy config generation to select and render extensions through new helper functions. Related docs and Caddy plugin pins are updated. ChangesProxy extension registry refactor
Sequence Diagram(s)sequenceDiagram
participant NixOS as NixOS evaluation
participant Options as options.nix
participant ProxyLib as default.nix
participant Config as config.nix
participant Extensions as extension modules
NixOS->>Options: evaluate server.proxy.extensions and virtualHosts options
NixOS->>ProxyLib: load getExtensionsForVhost and getGlobalConfigFromExtensions
NixOS->>Extensions: evaluate l4, kanidm, dashboard, cloudflared modules
Config->>ProxyLib: getGlobalConfigFromExtensions config
ProxyLib->>Extensions: call each extension globalConfig
ProxyLib-->>Config: concatenated global config
Config->>ProxyLib: getExtensionsForVhost vhostAttr
ProxyLib->>Extensions: filter, whitelist, and sort enabled extensions
ProxyLib-->>Config: ordered per-vhost extension list
Config->>NixOS: render services.caddy.globalConfig and per-vhost extraConfig
Estimated code review effort🎯 5 (Critical) | ⏱️ ~120 minutes Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 inconclusive)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
✨ Simplify code
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
RacciDev-Bot
left a comment
There was a problem hiding this comment.
Hermes Code Review: PR #597
refactor: caddy extensions separation from main module
Reviewed 8 source files across 20 changed files. The PR extracts L4, Kanidm, Dashboard, and Cloudflared logic from config.nix into self-contained extension modules under modules/nixos/server/proxy/extensions/, with a clean extension registry system (server.proxy.extensions). Architecture is sound - NixOS module system submodule merging is the right pattern for this.
Verdict: COMMENT - all findings are minor or trivial. No blocking issues.
Summary of findings
| # | Severity | File | Issue |
|---|---|---|---|
| 1 | 🟡 Minor | options.nix:71-75 | vhostModule defined but never consumed |
| 2 | 🟡 Minor | config.nix:53-131 | Assertion logic duplicated 2x per block |
| 3 | 🟡 Minor | extensions/kanidm.nix:227 | Always enabled - doesn't match spec |
| 4 | 🔹 Trivial | extensions/l4.nix | 3 independent cross-host traversals |
There was a problem hiding this comment.
Actionable comments posted: 7
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@modules/nixos/server/proxy/config.nix`:
- Around line 82-88: The extension selection logic in config.nix is filtering
over values from builtins.attrValues, which strips the attribute names and can
make ext._name unavailable when vh.extensions is set. Update the extension
collection in the proxy config to preserve names before filtering, then apply
the same change in the duplicated let block so both places use named extension
records when matching against vh.extensions and ext.enable.
- Around line 115-130: The current assertion in config.nix only rejects vhosts
with kanidm enabled and extensions = [ ], so it misses protected vhosts whose
extensions list does not include kanidm. Update the assertion around
config.server.proxy.virtualHosts to check vh.kanidm != null and require "kanidm"
to be present in vh.extensions, and keep the failure message listing the
affected vhosts by _name.
In `@modules/nixos/server/proxy/extensions/kanidm.nix`:
- Around line 224-232: The Kanidm extension’s default branch in the config
function is swallowing non-Kanidm vhost configuration because `enable =
mkDefault true` makes it selected for default vhosts while `consumesExtraConfig
= true` means the `vh.kanidm == null` case must not return an empty string.
Update the `server.proxy.extensions.kanidm` config logic so the `vh.kanidm ==
null` path preserves and forwards `vh._resolvedExtraConfig` instead of
discarding it, keeping non-Kanidm vhosts’ Caddy config intact.
- Around line 149-176: The kanidmContextsWithVirtualHosts mapping in kanidm.nix
eagerly calls builtins.head on vhList, which breaks evaluation for contexts that
have no matching virtual hosts. Update the context transformation to handle
empty vhList safely in the builtins.mapAttrs block by guarding originLanding
(and any other head-based access) so unused shared contexts are skipped or
emitted without originLanding rather than failing during evaluation.
- Around line 273-283: The Kanidm secret definition in sops.secrets sets owner
and group but is missing the restrictive file mode and a rotation hook. Update
the secret entries created in the kanidm.nix sops.secrets mapping to include
mode = "0400" and add the appropriate Kanidm provision/service restartUnits or
reloadUnits so changes to the secret refresh the basicSecretFile consumer.
In `@modules/nixos/server/proxy/extensions/l4.nix`:
- Around line 41-43: The L4 firewall configuration is opening UDP for every
listener even though the L4 option only exposes listenPort, so tighten this to
the minimal protocol set. Update the l4.nix logic around the L4 listener
definitions and firewall port derivation to default to TCP-only, or add an
explicit protocol option in the relevant vhost/listener config and only include
UDP when that option is enabled. Make sure the change is applied consistently in
the L4 listener processing and firewall port aggregation code, including the
related block used for the other L4 listeners.
- Around line 76-86: The L4 proxy config generation in allL4Entries is rewriting
loopback targets with hostCfg.host.name, which is the primary IO host and makes
replaceLocalHost a no-op for non-primary hosts. Update the mapping so
replaceLocalHost uses the owning virtual host’s host name from the current
vh/virtualHosts entry instead of the global host, ensuring localhost and
127.0.0.1 targets are rewritten to the correct host for each collected L4 entry.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro
Run ID: 6bc0ab64-8954-4e7c-a4d7-480529d9b35a
⛔ Files ignored due to path filters (8)
openspec/changes/proxy-extension-registry/.openspec.yamlis excluded by!openspec/**openspec/changes/proxy-extension-registry/design.mdis excluded by!openspec/**openspec/changes/proxy-extension-registry/proposal.mdis excluded by!openspec/**openspec/changes/proxy-extension-registry/specs/proxy-extension-authoring/spec.mdis excluded by!openspec/**openspec/changes/proxy-extension-registry/specs/proxy-extension-registry/spec.mdis excluded by!openspec/**openspec/changes/proxy-extension-registry/specs/proxy-l4-extension/spec.mdis excluded by!openspec/**openspec/changes/proxy-extension-registry/specs/proxy-vhost-extension-selection/spec.mdis excluded by!openspec/**openspec/changes/proxy-extension-registry/tasks.mdis excluded by!openspec/**
📒 Files selected for processing (12)
.opencode/skills/modules/SKILL.mddocs/src/modules/nixos/server/proxy.mdhosts/server/nixio/proxy.nixmodules/nixos/server/proxy/config.nixmodules/nixos/server/proxy/default.nixmodules/nixos/server/proxy/extensions.nixmodules/nixos/server/proxy/extensions/cloudflared.nixmodules/nixos/server/proxy/extensions/dashboard.nixmodules/nixos/server/proxy/extensions/kanidm.nixmodules/nixos/server/proxy/extensions/l4.nixmodules/nixos/server/proxy/kanidm.nixmodules/nixos/server/proxy/options.nix
💤 Files with no reviewable changes (2)
- modules/nixos/server/proxy/kanidm.nix
- modules/nixos/server/proxy/extensions.nix
📜 Review details
⏰ Context from checks skipped due to timeout. (9)
- GitHub Check: Build homeConfigurations.racci.activationPackage on x86_64-linux
- GitHub Check: Build nixosConfigurations.nixio.config.system.build.toplevel on x86_64-linux
- GitHub Check: Build nixosConfigurations.nixarr.config.system.build.toplevel on x86_64-linux
- GitHub Check: Build nixosConfigurations.nixmi.config.system.build.toplevel on x86_64-linux
- GitHub Check: Build nixosConfigurations.nixai.config.system.build.toplevel on x86_64-linux
- GitHub Check: Build nixosConfigurations.nixmon.config.system.build.toplevel on x86_64-linux
- GitHub Check: Build nixosConfigurations.nixserv.config.system.build.toplevel on x86_64-linux
- GitHub Check: Build nixosConfigurations.nixcloud.config.system.build.toplevel on x86_64-linux
- GitHub Check: Build nixosConfigurations.nixdev.config.system.build.toplevel on x86_64-linux
🧰 Additional context used
📓 Path-based instructions (11)
**/*.nix
📄 CodeRabbit inference engine (.opencode/skills/code-style-nix)
**/*.nix: Follow Nix code style conventions and best practices
Use consistent indentation and formatting in Nix configuration files
Follow established patterns for module organization in home-manager configurations
**/*.nix: Format code and check syntax usingnix fmt
Evaluate Nix expressions without building usingnix evalwith the target configuration path
Format specific Nix files or directories usingnix fmtfollowed by the file or directory path
Use--show-traceflag withnix buildornix evalcommands to diagnose evaluation errors
For infinite recursion errors in Nix builds, check for circular imports or conflicting option definitions
**/*.nix: Usebuiltins.traceto add trace statements and inspect values during Nix evaluation (format:builtins.trace "message: ${toString var}" var)
Usebuiltins.toJSONto convert complex Nix attribute sets to JSON for easier inspection during evaluation
Check for circular imports between modules and option definitions that depend on themselves to resolve infinite recursion errors
Verify attribute names are correct and imports are complete when debugging 'attribute not found' errors in Nix
Check option type definitions and ensure provided values match the expected type to resolve type mismatch errors
Read assertion messages and provide required configuration values when assertion failures occur in NixOS modules
**/*.nix: Store sensitive data insecrets.yamlencrypted with sops instead of hardcoding passwords, API keys, or tokens in plain text
Declare sops secrets with properowner,group, andmodeattributes; use restrictive modes like0400for secrets files
SetrestartUnitsorreloadUnitsfor sops secrets declarations so services that depend on secrets are restarted when secrets change
Useconfig.sops.placeholderin sops templates instead of directly interpolating secret paths in multi-secret templates
Do not pass secrets as environment variables in plain Nix; useenvironmentFileor...
Files:
modules/nixos/server/proxy/extensions/cloudflared.nixhosts/server/nixio/proxy.nixmodules/nixos/server/proxy/extensions/dashboard.nixmodules/nixos/server/proxy/extensions/l4.nixmodules/nixos/server/proxy/extensions/kanidm.nixmodules/nixos/server/proxy/default.nixmodules/nixos/server/proxy/config.nixmodules/nixos/server/proxy/options.nix
modules/nixos/**/*.nix
📄 CodeRabbit inference engine (.opencode/skills/project-structure/SKILL.md)
Reusable NixOS module fragments should be placed in
modules/nixos/Create new NixOS modules as files under
modules/nixos/<category>/<name>.nix.
Files:
modules/nixos/server/proxy/extensions/cloudflared.nixmodules/nixos/server/proxy/extensions/dashboard.nixmodules/nixos/server/proxy/extensions/l4.nixmodules/nixos/server/proxy/extensions/kanidm.nixmodules/nixos/server/proxy/default.nixmodules/nixos/server/proxy/config.nixmodules/nixos/server/proxy/options.nix
modules/**/*.nix
📄 CodeRabbit inference engine (.opencode/skills/modules/SKILL.md)
modules/**/*.nix: Use the standard Nix module structure: accept{ config, lib, pkgs, ... }, definecfgfromconfig.<namespace>.<name>, declare options underoptions, and gate configuration withconfig = lib.mkIf cfg.enable { ... }(or the equivalentmkIf/mkEnableOptionpattern).
When modifying existing Nix modules, runnix fmton the changed.nixfiles.
When extending a submodule declared in another Nix module, declare the sameoptions.<path>again with the same outer wrapper (for exampleattrsOf (submodule ...)) so the inneroptionsmerge additively.
Do not build submoduleimportsdynamically fromconfiginside the submodule type; that creates infinite recursion.
Use static submoduleimportsonly when they do not depend onconfig, and usemkIfinsideconfigfor conditional behavior instead of conditioning the submodule type.
When adding options to an existing submodule, keep them always declared in the submodule type; do not gate the option declaration withenable.
Files:
modules/nixos/server/proxy/extensions/cloudflared.nixmodules/nixos/server/proxy/extensions/dashboard.nixmodules/nixos/server/proxy/extensions/l4.nixmodules/nixos/server/proxy/extensions/kanidm.nixmodules/nixos/server/proxy/default.nixmodules/nixos/server/proxy/config.nixmodules/nixos/server/proxy/options.nix
hosts/server/**/*.nix
📄 CodeRabbit inference engine (.opencode/skills/project-structure/SKILL.md)
Server machine-specific NixOS configs should be placed in
hosts/server/<machine>/
Files:
hosts/server/nixio/proxy.nix
.opencode/skills/**
⚙️ CodeRabbit configuration file
../../modules/home-manager/purpose/development/editors/ai/skills/code-style-nix
../../modules/home-manager/purpose/development/editors/ai/skills/conventional-commits
../../modules/home-manager/purpose/development/editors/ai/skills/jujutsu
../../modules/home-manager/purpose/development/editors/ai/skills/nushell
../../modules/home-manager/purpose/development/editors/ai/skills/systemd-hardening
../../modules/home-manager/purpose/development/editors/ai/skills/tmux
../../modules/home-manager/purpose/development/editors/ai/skills/vhs
Files:
.opencode/skills/modules/SKILL.md
.opencode/skills/modules/**
⚙️ CodeRabbit configuration file
.opencode/skills/modules/**: ---
name: modules
description: Create and modify NixOS and Home-Manager modulesModules
Module Structure
Standard module pattern:
{ config, lib, pkgs, ... }: let inherit (lib) mkEnableOption mkOption mkIf types; cfg = config.services.myService; in { options.services.myService = { enable = mkEnableOption "my service"; port = mkOption { type = types.port; default = 8080; description = "Port to listen on."; }; }; config = mkIf cfg.enable { # Configuration applied when enabled }; }Creating a NixOS Module
Create file at
modules/nixos/<category>/<name>.nixDefine options and config:
{ config, lib, pkgs, ... }: let cfg = config.services.myService; in { options.services.myService = { enable = lib.mkEnableOption "my service"; }; config = lib.mkIf cfg.enable { systemd.services.my-service = { wantedBy = [ "multi-user.target" ]; serviceConfig.ExecStart = "${pkgs.myPackage}/bin/my-service"; }; }; }Register in parent
default.nix:# modules/nixos/services/default.nix _: { imports = [ ./existing-service.nix ./my-service.nix # Add this ]; }Enable in host config:
# hosts/server/myhost/default.nix { services.myService.enable = true; }Creating a Home-Manager Module
Create file at
modules/home-manager/<category>/<name>.nixDefine with optional
osConfigaccess:{ osConfig ? null, config, lib, pkgs, ... }: let cfg = config.purpose.myFeature; in { options.purpose.myFeature = { enable = lib.mkEnableOption "my feature"; }; config = lib.mkIf cfg.enable { home.packages = [ pkgs.myPackage ]; }; }Register in parent
default.nixEnable in user...
Files:
.opencode/skills/modules/SKILL.md
docs/**/*
📄 CodeRabbit inference engine (.opencode/skills/project-structure/SKILL.md)
Project documentation should be placed in the
docs/directory
Files:
docs/src/modules/nixos/server/proxy.md
docs/src/**/*.md
📄 CodeRabbit inference engine (.opencode/skills/docs/SKILL.md)
docs/src/**/*.md: Use underscore filenames (e.g.,my_new_feature.md) instead of hyphens for documentation files
Keep documentation prose focused on behavior, architecture, usage examples, and operational notes; let generated fragments provide exhaustive option reference
Files:
docs/src/modules/nixos/server/proxy.md
docs/src/modules/**/*.md
📄 CodeRabbit inference engine (.opencode/skills/docs/SKILL.md)
For documented modules, prefer build-time generated option fragments via
{{#include}}fromdocs/src/generated/*.mdinstead of hand-maintained option tables
Files:
docs/src/modules/nixos/server/proxy.md
docs/**/*.md
📄 CodeRabbit inference engine (AGENTS.md)
Verify documentation accurately reflects new behavior in docs/ directory before proceeding to commit
Files:
docs/src/modules/nixos/server/proxy.md
modules/nixos/**/default.nix
📄 CodeRabbit inference engine (.opencode/skills/modules/SKILL.md)
Register new NixOS modules in the parent
default.nixvia theimportslist or top-level attribute-set export, depending on the directory layout.
Files:
modules/nixos/server/proxy/default.nix
🧠 Learnings (8)
📚 Learning: 2026-04-13T14:02:32.760Z
Learnt from: DaRacci
Repo: DaRacci/nix-config PR: 546
File: hosts/server/nixdev/default.nix:18-18
Timestamp: 2026-04-13T14:02:32.760Z
Learning: When configuring NixOS Docker via `virtualisation.docker.daemon.settings`, it is valid to set `storage-driver = "overlayfs"` (do not flag it as an invalid Docker storage-driver). Use `overlayfs` specifically for Docker Engine 29+ and/or when the containerd snapshotter integration is enabled (`virtualisation.docker.features.containerd-snapshotter = true`). Treat this as the containerd snapshotter name for OverlayFS, distinct from the legacy `overlay2` classic Docker storage driver.
Applied to files:
modules/nixos/server/proxy/extensions/cloudflared.nixhosts/server/nixio/proxy.nixmodules/nixos/server/proxy/extensions/dashboard.nixmodules/nixos/server/proxy/extensions/l4.nixmodules/nixos/server/proxy/extensions/kanidm.nixmodules/nixos/server/proxy/default.nixmodules/nixos/server/proxy/config.nixmodules/nixos/server/proxy/options.nix
📚 Learning: 2026-05-01T10:02:55.261Z
Learnt from: DaRacci
Repo: DaRacci/nix-config PR: 544
File: modules/nixos/core/sops.nix:49-53
Timestamp: 2026-05-01T10:02:55.261Z
Learning: In this nix-config repo, when declaring `sops.secrets` in Nix files, avoid explicitly setting `owner = "root"` and/or `group = "root"` if the intended ownership is root. `sops-nix` defaults `sops.secrets` to `root:root`, so adding these fields explicitly is redundant boilerplate.
Applied to files:
modules/nixos/server/proxy/extensions/cloudflared.nixhosts/server/nixio/proxy.nixmodules/nixos/server/proxy/extensions/dashboard.nixmodules/nixos/server/proxy/extensions/l4.nixmodules/nixos/server/proxy/extensions/kanidm.nixmodules/nixos/server/proxy/default.nixmodules/nixos/server/proxy/config.nixmodules/nixos/server/proxy/options.nix
📚 Learning: 2026-05-01T14:14:49.691Z
Learnt from: DaRacci
Repo: DaRacci/nix-config PR: 544
File: modules/nixos/core/gaming.nix:119-119
Timestamp: 2026-05-01T14:14:49.691Z
Learning: When configuring the NixOS `wivrn` module option `services.wivrn.config.json.application`, pass the raw package/derivation (e.g., `pkgs.wayvr`) rather than converting it to a string executable path (e.g., `lib.getExe pkgs.wayvr`). The upstream module expects a list of derivations/packages (it internally `toList`s the value, asserts the first element is a derivation, and then resolves the executable internally). Code review should not recommend changing `pkgs.wayvr` to `lib.getExe pkgs.wayvr` for this option.
Applied to files:
modules/nixos/server/proxy/extensions/cloudflared.nixhosts/server/nixio/proxy.nixmodules/nixos/server/proxy/extensions/dashboard.nixmodules/nixos/server/proxy/extensions/l4.nixmodules/nixos/server/proxy/extensions/kanidm.nixmodules/nixos/server/proxy/default.nixmodules/nixos/server/proxy/config.nixmodules/nixos/server/proxy/options.nix
📚 Learning: 2026-05-20T13:12:46.610Z
Learnt from: DaRacci
Repo: DaRacci/nix-config PR: 546
File: docs/site.nix:127-127
Timestamp: 2026-05-20T13:12:46.610Z
Learning: In DaRacci/nix-config, treating `passthru.discovery = false` as a known repo-wide convention to exclude a derivation from automated flake discovery/package CI. Do not require or flag an inline explanatory comment specifically for the absence of a comment when `passthru.discovery = false` is set.
Applied to files:
modules/nixos/server/proxy/extensions/cloudflared.nixhosts/server/nixio/proxy.nixmodules/nixos/server/proxy/extensions/dashboard.nixmodules/nixos/server/proxy/extensions/l4.nixmodules/nixos/server/proxy/extensions/kanidm.nixmodules/nixos/server/proxy/default.nixmodules/nixos/server/proxy/config.nixmodules/nixos/server/proxy/options.nix
📚 Learning: 2026-05-01T09:11:22.009Z
Learnt from: DaRacci
Repo: DaRacci/nix-config PR: 544
File: modules/nixos/core/gaming.nix:65-65
Timestamp: 2026-05-01T09:11:22.009Z
Learning: In Nix code, do not flag shell-variable literals like "$XDG_RUNTIME_DIR" used inside Steam’s `extraEnv` (e.g., `pkgs.steam.override { extraEnv = { ... }; }`, including `modules/nixos/core/gaming.nix`). The Steam wrapper script expands these shell variables at runtime, so they should be treated as intended unexpanded literals rather than an interpolation/quoting mistake.
Applied to files:
modules/nixos/server/proxy/extensions/cloudflared.nixmodules/nixos/server/proxy/extensions/dashboard.nixmodules/nixos/server/proxy/extensions/l4.nixmodules/nixos/server/proxy/extensions/kanidm.nixmodules/nixos/server/proxy/default.nixmodules/nixos/server/proxy/config.nixmodules/nixos/server/proxy/options.nix
📚 Learning: 2026-05-01T14:35:32.037Z
Learnt from: DaRacci
Repo: DaRacci/nix-config PR: 544
File: modules/nixos/core/remote.nix:153-179
Timestamp: 2026-05-01T14:35:32.037Z
Learning: In this repo’s NixOS module code (e.g., shell scripts produced via `writeShellApplication` inside `modules/nixos/**`), do not treat missing `XDG_STATE_HOME` fallbacks (like `${XDG_STATE_HOME:-$HOME/.local/state}`) as an error in the embedded shell script. On NixOS user sessions, `XDG_STATE_HOME` is reliably set via PAM/systemd, so flagging its absence as potentially unset is overly defensive for these generated scripts.
Applied to files:
modules/nixos/server/proxy/extensions/cloudflared.nixmodules/nixos/server/proxy/extensions/dashboard.nixmodules/nixos/server/proxy/extensions/l4.nixmodules/nixos/server/proxy/extensions/kanidm.nixmodules/nixos/server/proxy/default.nixmodules/nixos/server/proxy/config.nixmodules/nixos/server/proxy/options.nix
📚 Learning: 2026-06-20T14:33:25.328Z
Learnt from: DaRacci
Repo: DaRacci/nix-config PR: 590
File: modules/nixos/server/monitoring/collector/tempo.nix:71-72
Timestamp: 2026-06-20T14:33:25.328Z
Learning: When reviewing DaRacci/nix-config NixOS modules that use sops-nix, do not flag `sops.secrets` entries as missing `owner`, `group`, `mode`, or `restartUnits` if the secret declarations are only placeholder sources for `sops.templates`:
- The secret value is referenced exclusively via `config.sops.placeholder.<NAME>` inside a `sops.templates` definition (i.e., no other code reads the decrypted secret from the raw secret path).
- The rendered `sops.templates` output is what is used by systemd via a `systemd.services.*.serviceConfig.EnvironmentFile` (the template is the effective boundary).
In this pattern, the template’s own `restartUnits` are the relevant access-control/restart boundary; the raw `sops.secrets` files are only decrypted in-memory by sops-nix (run as root) to render the template. Therefore, empty-attrset `sops.secrets.<NAME> = { };` declarations should not be treated as missing permissions/restart hooks when they are only feeding a `sops.templates` placeholder.
Applied to files:
modules/nixos/server/proxy/extensions/cloudflared.nixmodules/nixos/server/proxy/extensions/dashboard.nixmodules/nixos/server/proxy/extensions/l4.nixmodules/nixos/server/proxy/extensions/kanidm.nixmodules/nixos/server/proxy/default.nixmodules/nixos/server/proxy/config.nixmodules/nixos/server/proxy/options.nix
📚 Learning: 2026-05-01T09:57:09.578Z
Learnt from: DaRacci
Repo: DaRacci/nix-config PR: 544
File: modules/nixos/services/ai-agent.nix:15-15
Timestamp: 2026-05-01T09:57:09.578Z
Learning: In this repo’s Nix modules, `inputs.services-zeroclaw` is a flake input that resolves to an attrset containing a `_file` attribute, and Nix coerces that attrset to a file path via `_file`. When importing/using it as a path in `imports` (e.g., `modules/nixos/services/ai-agent.nix`), use the string interpolation form "${inputs.services-zeroclaw}". Do not change it to `inputs.services-zeroclaw` (raw attrset form) in `imports`, because it will not work correctly.
Applied to files:
modules/nixos/server/proxy/extensions/cloudflared.nixmodules/nixos/server/proxy/extensions/dashboard.nixmodules/nixos/server/proxy/extensions/l4.nixmodules/nixos/server/proxy/extensions/kanidm.nixmodules/nixos/server/proxy/default.nixmodules/nixos/server/proxy/config.nixmodules/nixos/server/proxy/options.nix
🪛 LanguageTool
docs/src/modules/nixos/server/proxy.md
[typographical] ~141-~141: If specifying a range, consider using an en dash instead of a hyphen.
Context: ...onfig placement. Ranges: 0-49 reserved, 50-99 auth, 100-199 general, 200+ post-proces...
(HYPHEN_TO_EN)
🔇 Additional comments (11)
docs/src/modules/nixos/server/proxy.md (1)
49-50: LGTM!Also applies to: 123-235
.opencode/skills/modules/SKILL.md (1)
169-251: LGTM!hosts/server/nixio/proxy.nix (1)
48-52: LGTM!modules/nixos/server/proxy/extensions/dashboard.nix (1)
1-33: LGTM!modules/nixos/server/proxy/extensions/cloudflared.nix (1)
1-72: LGTM!modules/nixos/server/proxy/options.nix (1)
25-26: LGTM!Also applies to: 37-78, 94-111
modules/nixos/server/proxy/default.nix (1)
10-10: LGTM!Also applies to: 94-122, 131-142
modules/nixos/server/proxy/config.nix (1)
26-32: LGTM!Also applies to: 53-75, 145-146, 171-192
modules/nixos/server/proxy/extensions/kanidm.nix (3)
1-41: LGTM!Also applies to: 110-147, 180-220, 270-270
235-240: 🩺 Stability & AvailabilityConsider sanitising
:in bypass matcher names too. Vhost names can include ports, and this matcher name only replaces-and., so keys likeapp.example.com:8443will produce@bypass_auth_app_example_com:8443.
52-58: 🩺 Stability & AvailabilityKeep the Kanidm env-file wiring on
services.caddy. The generated config still resolves{env.OAUTH_${envPrefix}_CLIENT_SECRET}and{env.${envPrefix}_SHARED_KEY}at runtime, so the Caddy service still needs the template orEnvironmentFilethat exports those values.
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@modules/nixos/server/proxy/config.nix`:
- Around line 70-74: The current validation only checks for vhosts that
configure kanidm without listing the kanidm extension, but it misses the case
where server.proxy.extensions.kanidm.enable is false and a vhost still has
vh.kanidm set. Update the proxy config validation in config.nix so the same
rejection path also catches Kanidm-protected vhosts whenever the Kanidm
extension is disabled, using the existing virtualHosts filtering logic and the
getExtensionsForVhost-related checks to ensure these vhosts are rejected before
rendering.
In `@modules/nixos/server/proxy/extensions/kanidm.nix`:
- Around line 284-285: The secret rotation hook is restarting the wrong unit, so
rotated OAuth2 secrets won’t be reloaded by the Kanidm server/provision path.
Update the `restartUnits` entry in the `basicSecretFile` block in `kanidm.nix`
to target `kanidm.service` instead of `kanidm-unixd.service`, since
`services.kanidm.provision.systems.oauth2` is consumed by the server unit.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro
Run ID: a9dad0ef-21de-481a-81b8-d22ae35b830d
📒 Files selected for processing (5)
hosts/server/nixai/voice.nixhosts/server/nixcloud/home-assistant/connectivity.nixmodules/nixos/server/proxy/config.nixmodules/nixos/server/proxy/extensions/kanidm.nixmodules/nixos/server/proxy/extensions/l4.nix
📜 Review details
⏰ Context from checks skipped due to timeout. (2)
- GitHub Check: Build nixosConfigurations.nixcloud.config.system.build.toplevel on x86_64-linux
- GitHub Check: Build nixosConfigurations.nixai.config.system.build.toplevel on x86_64-linux
🧰 Additional context used
📓 Path-based instructions (4)
**/*.nix
📄 CodeRabbit inference engine (.opencode/skills/code-style-nix)
**/*.nix: Follow Nix code style conventions and best practices
Use consistent indentation and formatting in Nix configuration files
Follow established patterns for module organization in home-manager configurations
**/*.nix: Format code and check syntax usingnix fmt
Evaluate Nix expressions without building usingnix evalwith the target configuration path
Format specific Nix files or directories usingnix fmtfollowed by the file or directory path
Use--show-traceflag withnix buildornix evalcommands to diagnose evaluation errors
For infinite recursion errors in Nix builds, check for circular imports or conflicting option definitions
**/*.nix: Usebuiltins.traceto add trace statements and inspect values during Nix evaluation (format:builtins.trace "message: ${toString var}" var)
Usebuiltins.toJSONto convert complex Nix attribute sets to JSON for easier inspection during evaluation
Check for circular imports between modules and option definitions that depend on themselves to resolve infinite recursion errors
Verify attribute names are correct and imports are complete when debugging 'attribute not found' errors in Nix
Check option type definitions and ensure provided values match the expected type to resolve type mismatch errors
Read assertion messages and provide required configuration values when assertion failures occur in NixOS modules
**/*.nix: Store sensitive data insecrets.yamlencrypted with sops instead of hardcoding passwords, API keys, or tokens in plain text
Declare sops secrets with properowner,group, andmodeattributes; use restrictive modes like0400for secrets files
SetrestartUnitsorreloadUnitsfor sops secrets declarations so services that depend on secrets are restarted when secrets change
Useconfig.sops.placeholderin sops templates instead of directly interpolating secret paths in multi-secret templates
Do not pass secrets as environment variables in plain Nix; useenvironmentFileor...
Files:
hosts/server/nixcloud/home-assistant/connectivity.nixhosts/server/nixai/voice.nixmodules/nixos/server/proxy/extensions/l4.nixmodules/nixos/server/proxy/extensions/kanidm.nixmodules/nixos/server/proxy/config.nix
hosts/server/**/*.nix
📄 CodeRabbit inference engine (.opencode/skills/project-structure/SKILL.md)
Server machine-specific NixOS configs should be placed in
hosts/server/<machine>/
Files:
hosts/server/nixcloud/home-assistant/connectivity.nixhosts/server/nixai/voice.nix
modules/nixos/**/*.nix
📄 CodeRabbit inference engine (.opencode/skills/project-structure/SKILL.md)
Reusable NixOS module fragments should be placed in
modules/nixos/Use the standard NixOS module structure: destructure
{ config, lib, pkgs, ... }, bindcfgfromconfig.<namespace>.<name>, defineoptionswithmkEnableOption/mkOption, and gate runtime config withmkIf cfg.enable.
Files:
modules/nixos/server/proxy/extensions/l4.nixmodules/nixos/server/proxy/extensions/kanidm.nixmodules/nixos/server/proxy/config.nix
modules/**/*.nix
📄 CodeRabbit inference engine (.opencode/skills/modules/SKILL.md)
modules/**/*.nix: When extending submodules declared in another module, declare the sameoptions.<path>using a compatibleattrsOf (submodule ...)wrapper so the inneroptionssets merge additively.
Do not build submoduleimportsfromconfigvalues; dynamicimportsinside a submodule cause infinite recursion.
Static submoduleimportsare allowed when they do not read fromconfig.
UsemkIfinside the submoduleconfigfor conditional behavior; keep submodule option declarations unconditional.
Files:
modules/nixos/server/proxy/extensions/l4.nixmodules/nixos/server/proxy/extensions/kanidm.nixmodules/nixos/server/proxy/config.nix
🧠 Learnings (8)
📚 Learning: 2026-04-13T14:02:32.760Z
Learnt from: DaRacci
Repo: DaRacci/nix-config PR: 546
File: hosts/server/nixdev/default.nix:18-18
Timestamp: 2026-04-13T14:02:32.760Z
Learning: When configuring NixOS Docker via `virtualisation.docker.daemon.settings`, it is valid to set `storage-driver = "overlayfs"` (do not flag it as an invalid Docker storage-driver). Use `overlayfs` specifically for Docker Engine 29+ and/or when the containerd snapshotter integration is enabled (`virtualisation.docker.features.containerd-snapshotter = true`). Treat this as the containerd snapshotter name for OverlayFS, distinct from the legacy `overlay2` classic Docker storage driver.
Applied to files:
hosts/server/nixcloud/home-assistant/connectivity.nixhosts/server/nixai/voice.nixmodules/nixos/server/proxy/extensions/l4.nixmodules/nixos/server/proxy/extensions/kanidm.nixmodules/nixos/server/proxy/config.nix
📚 Learning: 2026-05-01T10:02:55.261Z
Learnt from: DaRacci
Repo: DaRacci/nix-config PR: 544
File: modules/nixos/core/sops.nix:49-53
Timestamp: 2026-05-01T10:02:55.261Z
Learning: In this nix-config repo, when declaring `sops.secrets` in Nix files, avoid explicitly setting `owner = "root"` and/or `group = "root"` if the intended ownership is root. `sops-nix` defaults `sops.secrets` to `root:root`, so adding these fields explicitly is redundant boilerplate.
Applied to files:
hosts/server/nixcloud/home-assistant/connectivity.nixhosts/server/nixai/voice.nixmodules/nixos/server/proxy/extensions/l4.nixmodules/nixos/server/proxy/extensions/kanidm.nixmodules/nixos/server/proxy/config.nix
📚 Learning: 2026-05-01T14:14:49.691Z
Learnt from: DaRacci
Repo: DaRacci/nix-config PR: 544
File: modules/nixos/core/gaming.nix:119-119
Timestamp: 2026-05-01T14:14:49.691Z
Learning: When configuring the NixOS `wivrn` module option `services.wivrn.config.json.application`, pass the raw package/derivation (e.g., `pkgs.wayvr`) rather than converting it to a string executable path (e.g., `lib.getExe pkgs.wayvr`). The upstream module expects a list of derivations/packages (it internally `toList`s the value, asserts the first element is a derivation, and then resolves the executable internally). Code review should not recommend changing `pkgs.wayvr` to `lib.getExe pkgs.wayvr` for this option.
Applied to files:
hosts/server/nixcloud/home-assistant/connectivity.nixhosts/server/nixai/voice.nixmodules/nixos/server/proxy/extensions/l4.nixmodules/nixos/server/proxy/extensions/kanidm.nixmodules/nixos/server/proxy/config.nix
📚 Learning: 2026-05-20T13:12:46.610Z
Learnt from: DaRacci
Repo: DaRacci/nix-config PR: 546
File: docs/site.nix:127-127
Timestamp: 2026-05-20T13:12:46.610Z
Learning: In DaRacci/nix-config, treating `passthru.discovery = false` as a known repo-wide convention to exclude a derivation from automated flake discovery/package CI. Do not require or flag an inline explanatory comment specifically for the absence of a comment when `passthru.discovery = false` is set.
Applied to files:
hosts/server/nixcloud/home-assistant/connectivity.nixhosts/server/nixai/voice.nixmodules/nixos/server/proxy/extensions/l4.nixmodules/nixos/server/proxy/extensions/kanidm.nixmodules/nixos/server/proxy/config.nix
📚 Learning: 2026-05-01T09:11:22.009Z
Learnt from: DaRacci
Repo: DaRacci/nix-config PR: 544
File: modules/nixos/core/gaming.nix:65-65
Timestamp: 2026-05-01T09:11:22.009Z
Learning: In Nix code, do not flag shell-variable literals like "$XDG_RUNTIME_DIR" used inside Steam’s `extraEnv` (e.g., `pkgs.steam.override { extraEnv = { ... }; }`, including `modules/nixos/core/gaming.nix`). The Steam wrapper script expands these shell variables at runtime, so they should be treated as intended unexpanded literals rather than an interpolation/quoting mistake.
Applied to files:
modules/nixos/server/proxy/extensions/l4.nixmodules/nixos/server/proxy/extensions/kanidm.nixmodules/nixos/server/proxy/config.nix
📚 Learning: 2026-05-01T14:35:32.037Z
Learnt from: DaRacci
Repo: DaRacci/nix-config PR: 544
File: modules/nixos/core/remote.nix:153-179
Timestamp: 2026-05-01T14:35:32.037Z
Learning: In this repo’s NixOS module code (e.g., shell scripts produced via `writeShellApplication` inside `modules/nixos/**`), do not treat missing `XDG_STATE_HOME` fallbacks (like `${XDG_STATE_HOME:-$HOME/.local/state}`) as an error in the embedded shell script. On NixOS user sessions, `XDG_STATE_HOME` is reliably set via PAM/systemd, so flagging its absence as potentially unset is overly defensive for these generated scripts.
Applied to files:
modules/nixos/server/proxy/extensions/l4.nixmodules/nixos/server/proxy/extensions/kanidm.nixmodules/nixos/server/proxy/config.nix
📚 Learning: 2026-06-20T14:33:25.328Z
Learnt from: DaRacci
Repo: DaRacci/nix-config PR: 590
File: modules/nixos/server/monitoring/collector/tempo.nix:71-72
Timestamp: 2026-06-20T14:33:25.328Z
Learning: When reviewing DaRacci/nix-config NixOS modules that use sops-nix, do not flag `sops.secrets` entries as missing `owner`, `group`, `mode`, or `restartUnits` if the secret declarations are only placeholder sources for `sops.templates`:
- The secret value is referenced exclusively via `config.sops.placeholder.<NAME>` inside a `sops.templates` definition (i.e., no other code reads the decrypted secret from the raw secret path).
- The rendered `sops.templates` output is what is used by systemd via a `systemd.services.*.serviceConfig.EnvironmentFile` (the template is the effective boundary).
In this pattern, the template’s own `restartUnits` are the relevant access-control/restart boundary; the raw `sops.secrets` files are only decrypted in-memory by sops-nix (run as root) to render the template. Therefore, empty-attrset `sops.secrets.<NAME> = { };` declarations should not be treated as missing permissions/restart hooks when they are only feeding a `sops.templates` placeholder.
Applied to files:
modules/nixos/server/proxy/extensions/l4.nixmodules/nixos/server/proxy/extensions/kanidm.nixmodules/nixos/server/proxy/config.nix
📚 Learning: 2026-05-01T09:57:09.578Z
Learnt from: DaRacci
Repo: DaRacci/nix-config PR: 544
File: modules/nixos/services/ai-agent.nix:15-15
Timestamp: 2026-05-01T09:57:09.578Z
Learning: In this repo’s Nix modules, `inputs.services-zeroclaw` is a flake input that resolves to an attrset containing a `_file` attribute, and Nix coerces that attrset to a file path via `_file`. When importing/using it as a path in `imports` (e.g., `modules/nixos/services/ai-agent.nix`), use the string interpolation form "${inputs.services-zeroclaw}". Do not change it to `inputs.services-zeroclaw` (raw attrset form) in `imports`, because it will not work correctly.
Applied to files:
modules/nixos/server/proxy/extensions/l4.nixmodules/nixos/server/proxy/extensions/kanidm.nixmodules/nixos/server/proxy/config.nix
🔇 Additional comments (5)
modules/nixos/server/proxy/extensions/l4.nix (1)
45-52: LGTM!Also applies to: 80-93, 143-160
hosts/server/nixai/voice.nix (1)
29-29: LGTM!Also applies to: 42-42
hosts/server/nixcloud/home-assistant/connectivity.nix (1)
146-146: LGTM!modules/nixos/server/proxy/extensions/kanidm.nix (1)
176-177: LGTM!modules/nixos/server/proxy/config.nix (1)
45-68: LGTM!Also applies to: 85-92
No description provided.