New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
nixos/knot: allow full configuration by nix values #81460
Conversation
One idea not yet implemented: {
# Example usage:
zones.foo = "inline string";
zones.bar = ./some-file;
zones.baz = some derivation; # e.g. writeText, fetch* or whatever
# where implementation might be something like:
nixConfig.zone = flip mapAttrs zones
(n: v: {
storage = "/var/lib/knot";
file = if isString v then pkgs.writeText n v else v;
});
} |
So far I absolutely haven't looked at aspects like what happens on errors. Some common problems might lead to horrible nix traces, for example. |
This comment has been minimized.
This comment has been minimized.
This pull request has been mentioned on NixOS Discourse. There might be relevant details there: https://discourse.nixos.org/t/generating-yaml-in-a-nix-module/2519/5 |
Ultimately something like this would be awesome https://github.com/kirelagin/dns.nix. |
Generating the zone files themselves seems like an orthogonal task. In particular, it should be the same for all DNS servers. I think I've seen multiple proposals for some such generator already. |
I marked this as stale due to inactivity. → More info |
Hello, any updates on this ? How can I help ? |
Test and review, I think. I got basically no reactions here, so I didn't feel like going forward with it. IIRC that's the only reason why this got left behind by me. EDIT: well and that other "competing PR", as we can't really have both at once. I could rebase a look about possible silent conflicts, but I expect an issue is only in the tests even though it's been years. |
3ff94a1
to
a762cca
Compare
Rebased. Made the new declarative configuration into the Updated the remaining knot configs in our tests accordingly. |
I think we should keep
|
Ok looked a bit deeper in knot docs and I believe that the current PR cannot handle modules (https://www.knot-dns.cz/docs/latest/html/modules.html). It seems to me that all modules are parsed by |
Here is a patch :
|
We're also going to run into ordering problems with mods. https://www.knot-dns.cz/docs/latest/html/configuration.html#query-modules |
Hmm, do you think it is worth continuing that way ? Or should the module let the user provide the ordering ? |
We could either make this a fixed order for now, or work with priorities (e.g. nginx location blocks would be the prior art), or maybe even toposort. But even then there is the issue, that the current approach silently ignores "extra" configuration. |
I think the PR now has everything that's been suggested. Also /cc @lheckemann as potentially interested in reacting to this PR. |
Nit: maybe |
Feel free to improve on that nit, I'm very much inclined to include this in NixOS 23.11 either way. Even in its current state, it is a big improvement. |
71c894f
to
1869818
Compare
I think this is the last call. There has been too much opportunity for feedback already. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
❤️
I think all interested parties have approved. Thanks for your work on this, it makes using knot much more pleasant than working with the upstream config format. |
Naive question: wouldn't this be a bit simpler if knot's yaml parser would be a full yaml 1.1 parser and not only supporting a tiny subset? |
in result; | ||
|
||
configFile = if cfg.settingsFile != null then | ||
assert cfg.settings == {} && cfg.keyFiles == []; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should move this to a full fledged module system assertion to make it UX wise a lot better.
Right now I receive the following error which is a bit confusing.
… while evaluating a branch condition
at /nix/store/4h9mf2ydqjgjawihf3zkshkznm4mkavg-source/lib/customisation.nix:256:8:
255| drv' = (lib.head outputsList).value;
256| in if drv == null then null else
| ^
257| lib.deepSeq drv' drv';
… while calling the 'head' builtin
at /nix/store/4h9mf2ydqjgjawihf3zkshkznm4mkavg-source/lib/attrsets.nix:820:11:
819| || pred here (elemAt values 1) (head values) then
820| head values
| ^
821| else
(stack trace truncated; use '--show-trace' to show the full trace)
error: assertion '(((cfg).settings == { }) && ((cfg).keyFiles == [ ]))' failed
at /nix/store/4h9mf2ydqjgjawihf3zkshkznm4mkavg-source/nixos/modules/services/networking/knot.nix:106:5:
105| configFile = if cfg.settingsFile != null then
106| assert cfg.settings == {} && cfg.keyFiles == [];
| ^
107| cfg.settingsFile
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also this isn't mentioned in the release-notes, so I am currently a bit confused how to migrate of the following:
keyFiles = [
config.sops.secrets."knot/keyFile".path
];
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If you switch to settings
instead of extraConfig
, you can keep keyFiles
.
As for the module, one way is to make the assertion better (as you suggest), another way is to implement full compatibility.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I ended up with this diff to have an identical knot.conf file without rewriting my config.
diff --git machines/neon/configuration.nix machines/neon/configuration.nix
index 947b152..594c898 100644
--- machines/neon/configuration.nix
+++ machines/neon/configuration.nix
@@ -134,10 +134,8 @@
knot = {
enable = true;
- keyFiles = [
- config.sops.secrets."knot/keyFile".path
- ];
- extraConfig = /* yaml */ ''
+ settingsFile = pkgs.writeText "knot.conf" /* yaml */ ''
+ include: ${config.sops.secrets."knot/keyFile".path}
acl:
- id: transfer
key: transfer
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@SuperSandro2000 Thank you, this was helpful. My configuration looked very similar to yours.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually, people may want to revert similar config changes when updating past PR #258361 - as such includes will surely often fail build-time validation that was disabled by accident. (I'm sure people do want validation when not using secrets.)
@@ -97,6 +97,8 @@ | |||
|
|||
- `pass` now does not contain `password-store.el`. Users should get `password-store.el` from Emacs lisp package set `emacs.pkgs.password-store`. | |||
|
|||
- `services.knot` now supports `.settings` from RFC42. The change is not 100% compatible with the previous `.extraConfig`. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should relay contain what is not compatible or some link to maybe here or somewhere else because right now lonely from this line I am totally unsure what to other than just give it a shot.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would also appreciate seeing more detail here. The error generated without making any changes to my previous config was (at least to my eyes) fairly cryptic:
Full error trace:
error:
… while calling the 'head' builtin
at /nix/store/8lg5579v1k5mc63ypzfagrcl8l32x3bh-source/lib/attrsets.nix:820:11:
819| || pred here (elemAt values 1) (head values) then
820| head values
| ^
821| else
… while evaluating the attribute 'value'
at /nix/store/8lg5579v1k5mc63ypzfagrcl8l32x3bh-source/lib/modules.nix:807:9:
806| in warnDeprecation opt //
807| { value = builtins.addErrorContext "while evaluating the option `${showOption loc}':" value;
| ^
808| inherit (res.defsFinal') highestPrio;
(stack trace truncated; use '--show-trace' to show the full trace)
error: assertion '(((cfg).settings == { }) && ((cfg).keyFiles == [ ]))' failed
at /nix/store/8lg5579v1k5mc63ypzfagrcl8l32x3bh-source/nixos/modules/services/networking/knot.nix:106:5:
105| configFile = if cfg.settingsFile != null then
106| assert cfg.settings == {} && cfg.keyFiles == [];
| ^
107| cfg.settingsFile
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The error should be gone after merging PR #258361
I don't think it is that much currently. I mostly configured my knot by copying the yaml from the documentation page section by section. Now I would need to translate it to nix code and make sure that the limited parser still understands what I am doing. It would mean I could built my own functions to generate repetitive sections but there are currently no value adding options like nginx' enableACME or complete location blocks like nextcloud or mastodon has. |
I see a part the other way than you: translating to nix code will work around the limited YAML parser, e.g. it will ensure that ordering of the sections is correct. Either way, I don't think |
That is an interesting fact I didn't know about. How about we write this into the release notes to motivate people to migrate their config? |
I think it's OK if they don't migrate. And |
Solving ordering was a necessity in this PR. Nix attrsets are unordered, so the user no longer can reliably affect ordering. |
Uh, so I guess continuing on PR #258361 |
type = types.lines; | ||
default = ""; | ||
settings = mkOption { | ||
type = types.attrs; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for this huge improvement! Please be aware that this type.attrs
does not merge the settings
as expected with other options, especially when the configuration is split between modules. Using a freeform submodule as suggested in the RFC followed by this PR would solve that.
This seems desired by multiple people. Let's work out how to do this, starting with this prototype. See the commit messages.
settings
RFC for reference: https://github.com/NixOS/rfcs/blob/master/rfcs/0042-config-option.md