-
-
Notifications
You must be signed in to change notification settings - Fork 14.4k
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: init #56922
nixos/knot: init #56922
Conversation
I'm still trying to figure out how and where to deploy zonefiles and also where mutable data will be written to. I'm new to Knot DNS and have no experience running it yet. |
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.
Overall it looks like a good first draft. Thanks for working on it! 👍
When running the daemon with an empty configuration I received a bunch of warnings which we might want to investigate:
server# [ 8.219413] knotd[792]: 2019-03-06T14:06:29 info: Knot DNS 2.7.6 starting
server# [ 8.221783] knotd[792]: 2019-03-06T14:06:29 info: loading 0 zones
server# [ 8.233685] knotd[792]: warning: cannot open persistent timer DB '/nix/store/0sv2dhwmfr3q7y67n2q0jfqipmfmjm5r-knot-dns-2.7.6/var/lib/knot/timers' (not exists)
server# [ 8.238169] knotd[792]: 2019-03-06T14:06:29 warning: cannot open persistent timer DB '/nix/store/0sv2dhwmfr3q7y67n2q0jfqipmfmjm5r-knot-dns-2.7.6/var/lib/knot/timers' (not exists)
server# [ 8.241953] knotd[792]: 2019-03-06T14:06:29 warning: no zones loaded
server# [ 8.244193] knotd[792]: 2019-03-06T14:06:29 info: starting server
server# [ 8.246495] knotd[792]: 2019-03-06T14:06:29 info: server started in the foreground, PID 792
server# [ 8.249342] knotd[792]: 2019-03-06T14:06:29 info: control, binding to '/run/knot/knot.sock'
server# [ 8.252291] knotd[792]: warning: no zones loaded
Thanks, I'm looking into the feedback tonight. |
It's possible we'll want to modify the |
The timer implementation changed between between 2.7.6 and 2.8.0 and I guess we should probably bump to 2.8.0 before investigating. https://gitlab.labs.nic.cz/knot/knot-dns/commit/844209ef4fb68b582648871c44dd82fb3ce2e3b7 |
There's a catch for knot-resolver, so I opened #56974 to at least serve as base for developing the nixos service. |
Yup, the timer warnings are gone on 2.8.0.
|
@andir: what about using this? { # Knot DNS uses a restricted version of YAML.
nix2yaml = let
quoteString = s: ''"${toString s}"'';
n2y = indent: val:
if isAttrs val then concatStringsSep "\n${indent}"
(mapAttrsToList
# This is a bit wacky - set directly under a set would start on bad indent,
# so we start those on a new line, but not other types of attribute values.
(aname: aval: "${aname}:${if isAttrs aval then "\n${indent} " else " "}"
+ n2y (indent + " ") aval)
val
)
+ "\n"
else
if isList val && stringLength indent < 4 then concatMapStrings
(elem: "\n${indent}- " + n2y (indent + " ") elem)
val
else
if isList val /* and long indent */ then
"[ " + concatMapStringsSep ", " quoteString val + " ]" else
quoteString val;
in n2y "";
} Example output: server:
listen: [ "0.0.0.0@53", ":@53" ]
zone:
- domain: "deleg.example.com."
file: "/nix/store/2vn5pj4hsbsjbwr9is3syb01r7zsbcqn-deleg.example.com."
storage: "/var/lib/knot"
- domain: "example.com."
file: "/nix/store/f9cxcqcw3kxk0pb8nv6a8dahxbzdfs44-example.com."
storage: "/var/lib/knot" |
@vcunat that looks great and (almost) works for my test that I hacked together 👍. I had to convert paths to string before passing it to the function but that is a trivial thing to add. |
I thought |
Ah, it's the other way around... I break the usual semantics by applying |
I was using the following during my tests: let
zones."example.com." = ''
@ SOA ns.example.com noc.example.com 666 7200 3600 1209600 3600
ipv4 A 1.2.3.4
ipv6 AAAA abcd::eeff
deleg NS ns.example.com
ns A 192.168.0.1
ns AAAA dead:beef::1
'';
zones."deleg.example.com." = ''
@ SOA ns.example.com noc.example.com 666 7200 3600 1209600 3600
@ A 9.8.7.6
@ AAAA fedc::bbaa
'';
#zones."." = ''
# @ SOA ns.example.com noc.example.com 666 7200 3600 1209600 3600
# root A 1.8.7.4
# root AAAA acbd::4
#'';
nix2yaml = with lib; let
quoteString = s: ''"${toString s}"'';
n2y = indent: val:
if isAttrs val then concatStringsSep "\n${indent}"
(mapAttrsToList
# This is a bit wacky - set directly under a set would start on bad indent,
# so we start those on a new line, but not other types of attribute values.
(aname: aval: "${aname}:${if isAttrs aval then "\n${indent} " else " "}"
+ n2y (indent + " ") aval)
val
)
+ "\n"
else
if isList val && stringLength indent < 4 then concatMapStrings
(elem: "\n${indent}- " + n2y (indent + " ") elem)
val
else
if isList val /* and long indent */ then
"[ " + concatMapStringsSep ", " quoteString val + " ]" else
quoteString val;
in n2y "";
in {
networking.nameservers = lib.mkForce [ "192.168.0.1" ];
networking.interfaces.eth1.ipv4.addresses = [
{ address = "192.168.0.1"; prefixLength = 24; }
];
networking.interfaces.eth1.ipv6.addresses = [
{ address = "dead:beef::1"; prefixLength = 64; }
];
services.knot = {
enable = true;
extraConfig = nix2yaml {
server.listen = [ "0.0.0.0@53" "::@53" ];
zone = lib.mapAttrsToList (n: v: { domain = n; storage = "/var/lib/knot"; file = toString (pkgs.writeText n v); }) zones;
};
}; I added the extra |
Right, there were some subtle issues, commented in the code. rec { # Knot DNS uses a restricted version of YAML.
nix2yaml = let
# We don't want paths like ./my-zone.txt be converted to plain strings.
quoteString = s: ''"${if builtins.typeOf s == "path" then s else toString s}"'';
# We don't want to walk the insides of derivation attributes.
doRecurse = val: isAttrs val && !isDerivation val;
n2y = indent: val:
if doRecurse val then concatStringsSep "\n${indent}"
(mapAttrsToList
# This is a bit wacky - set directly under a set would start on bad indent,
# so we start those on a new line, but not other types of attribute values.
(aname: aval: "${aname}:${if doRecurse aval then "\n${indent} " else " "}"
+ n2y (indent + " ") aval)
val
)
+ "\n"
else
if isList val && stringLength indent < 4 then concatMapStrings
(elem: "\n${indent}- " + n2y (indent + " ") elem)
val
else
if isList val /* and long indent */ then
"[ " + concatMapStringsSep ", " quoteString val + " ]" else
quoteString val;
in n2y "";
extraConfig = {
server.listen = [ "0.0.0.0@53" "::@53" ];
zone = mapAttrsToList
(n: v: {
domain = n;
storage = "/var/lib/knot";
file = if isString v then pkgs.writeText n v else v;
})
zones;
};
# which works with these options that came into my mind:
zones.foo = "inline string";
zones.bar = ./some-file;
zones.baz = some derivation; # e.g. writeText, fetch* or whatever
} |
I guess we could make a similar "zone.*" processing built into the conversion into YAML (as a pre-processor map on nix level), so that people have an simple way of configuring it in a way that's more natural in nix. EDIT: another concern is that it would be nice to get more uniformity among nixos configs for different auth DNS implementations, but let's leave that for further iterations. Furthermore, IETF works on RESTCONF modelling for that purpose... |
@vcunat how do you feel about merging the current implementation once it gets a test and then only afterwards investing in a more "complete" nix integration? I think it would make sense to experiment with the different options before putting each through a nixpkgs PR. My personal DNS servers will move to this as soon as we merge this and I get the time to roll it out. |
Yes, I'm in favor of faster iteration. |
The changes might be (mostly) backward compatible even, if we only support the basic config options now – those that don't affect the configuration file. But anyway, I don't expect people will massively start to use the new service, so 100% compatibility doesn't seem too important. |
I reviewed the systemd unit config, comparing it to upstream unit. Minor changes:
[resolved below] Now, the change I consider big: |
The idea is to avoid issues with both exhausting our UID/GID preallocation space (that is rather limited) and to avoid any kind of UID/GID reuse attacks. Systemd will take care of making the StateDirectory (usually /var/lib/) writable for the dynamic user. We had a few discussions on IRC (#nixos{,-dev,-chat,-security,…}) where the conclusion was that dynamic users + state dir might be desireable for new services. There isn't anything documented about that idea just yet. On that note we might want to set |
So the state directory contents will still be persistent and kept across service/system restarts, right? (Changing the ownership in case systemd starts it with a different UID/GID, etc.) |
Yes
…On Mon, Mar 11, 2019 at 9:22 AM Vladimír Čunát ***@***.***> wrote:
So the state directory will still be persistent and kept across
service/system restarts, right? (Changing the ownership in case systemd
starts it with a different UID/GID, etc.)
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#56922 (comment)>, or mute
the thread
<https://github.com/notifications/unsubscribe-auth/AAm_dHiLYFK4A_TQbd4Qa9CAFEheoAj0ks5vViBmgaJpZM4bfrm9>
.
|
OK, sounds good (with my limited knowledge). Dir permissions sound OK as well, according to
|
Thanks for your reviews. I made the following changes:
I'm looking into tests right now. Also I'm still wondering what (the package, the module, something else?) is responsible for getting man pages into the system environment. |
Regarding the state directories permission: [root@juno:~]$ ls -lah /var/lib/knot
lrwxrwxrwx 1 root root 12 Mar 3 02:58 /var/lib/knot -> private/knot [root@juno:~]$ ls -lah /var/lib/private/knot/
total 8.0K
drwx------ 2 knot knot 4.0K Mar 3 02:58 .
drwx------ 4 root root 4.0K Mar 3 02:58 .. [hexa@juno:~]$ ls -lah /var/lib/private/knot
ls: cannot access '/var/lib/private/knot': Permission denied |
The last commit adds tests, I adapted the test set already used by nsd.
|
The last commit links the man pages into the system environment, thanks to @vcunat. |
4fb3f5c
to
a5f8a1a
Compare
I just tried enabling DNSSEC signing and the initialization failed because my zones currently reside in the nix store and Knot seems to want to write data in the same directory. I will probably need to symlink the zones somewhere below the Edit: Would probably a good idea to update the tests with a working DNSSEC example.
|
Hmm, perhaps this approach? For a master server, that is. For slaves the preceding example would probably be suitable, but we haven't really discussed slaves here yet. |
No, unfortunately that does not seem to change the behaviour. Edit: Additionally moving {journal,timer,key}-db to template:
- id: default
storage: /nix/store/rrip306yqhjf221z5aaaak9g5ar8az7i-zonefiles
dnssec-signing: on
zonefile-sync: -1
zonefile-load: difference
journal-content: changes
journal-db: /var/lib/knot/journal
kasp-db: /var/lib/knot/kasp
timer-db: /var/lib/knot/timer
|
The tests now enable Edit: I'm just in the process of extending the tests to a master/slave setup, after which I would consider this pull request done. |
I just pushed the updated tests with the master/slave setup. Is there anything else? |
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 can't see anything else ATM. Let's reiterate if needed.
(cherry picked from commit 3aecf21)
This pull request has been mentioned on Nix community. There might be relevant details there: https://discourse.nixos.org/t/generating-yaml-in-a-nix-module/2519/5 |
Motivation for this change
Allow for easier usage by creating a module with a secure-by-default systemd unit.
Things done
sandbox
innix.conf
on non-NixOS)nix-shell -p nox --run "nox-review wip"
./result/bin/
)nix path-info -S
before and after)