Announcing - NixOS-DNS

tldr: manage your dns deployments with nixos.
I spent a lot of time documenting everything and making it so hopefully other people find it useful as well.
docs: https://janik-haag.github.io/NixOS-DNS/
source: https://github.com/Janik-Haag/nixos-dns/

30 Likes

Does this so something clever to avoid to fully evaluating all hosts, so that having the records across 25 nixosConfigurations does not need the equivalent of a lot of RAM?

1 Like

No sadly nothing special Feel free to poke me or open a pr/issue if you have ideas on how to improve it.
I would guess that if you use it with flakes that it uses the cached evaluations.

I had a similar problem with ldap login and solved it by having the options for in the shared configuration files which are also set independently of the service being enabled.
The result is that every host has access to those options.
See https://github.com/SuperSandro2000/nixos-modules/blob/28865ab38ccea31881114e4b949e98705ccf5cfd/modules/mastodon.nix#L70-L74

1 Like

No need to be clever. If you pick what you need, evaluating network stuff of 25 hosts, is on the order of fully evaluating a single host.

NIX_SHOW_STATS=1 nix-instantiate --eval --expr --strict --json 'with import ./. {}; let ok = { fileSystems."/".device = "x"; boot.loader.grub.enable = false; services.postgresql.enable = true; }; in map (i: let inherit (nixos ok) config; in [config.networking.hostName config.networking.interfaces]) (lib.range 1 25)'
[["nixos",{}],["nixos",{}],["nixos",{}],["nixos",{}],["nixos",{}],["nixos",{}],["nixos",{}],["nixos",{}],["nixos",{}],["nixos",{}],["nixos",{}],["nixos",{}],["nixos",{}],["nixos",{}],["nixos",{}],["nixos",{}],["nixos",{}],["nixos",{}],["nixos",{}],["nixos",{}],["nixos",{}],["nixos",{}],["nixos",{}],["nixos",{}],["nixos",{}]]
{
  "cpuTime": 2.9355220794677734,
  "envs": {
    "bytes": 268190456,
    "elements": 13354117,
    "number": 10084845
  },
  "gc": {
    "heapSize": 402915328,
    "totalBytes": 1445898336
  },

Note that the postgresql service is insignificant, because nothing of substance is evaluated.

-"totalBytes": 1445856592
+"totalBytes": 1445898336
3 Likes

The only time I eval stuff from nixos directly is in here:

I check if the config has the attribute with lib.hasAttrByPath [ "config" "networking" "domains" "baseDomains" ] and then just access it with ($host).config.networking.domains.baseDomains
and that once for subDomains and once for baseDomains. Maybe there is some better way to do that, I also don’t really know how efficient performant wise that is.

The code is a bit ugly and I should redo some of it :see_no_evil:

@Janik Provided that I know nothing about octodns, how does it compare to GitHub - kirelagin/dns.nix: A Nix DSL for DNS zone files to render zone files or have DNS records nixified?

dns.nix provides utilities to generate zonefiles like the extraConfig key here: dnsConfig - NixOS-DNS. NixOS-DNS also supports reading nixosConfigurations so you can define metadata inside your nixos hosts config, which you most likely already have because many services require domains and NixOS-DNS then merges all of them dynamically like described in Usage - NixOS-DNS

Hope that helps.

1 Like

That really helped, yes.

It’s kinda common with a lot of nix projects to forget to state clearly and prominently what the use-case for them is, why I would want them, what they offer and how to use them in an ELI5 sort of way. You might want to consider putting that in the summary of your docs, which currently reads:

This is the documentation for NixOS-DNS which was built to decouple modules even more from NixOS hosts and is slowly escalating into anything nix*-dns. Please open a issue if you find something is missing.

Here you will find:

  • automagically generated docs for the modules and utility functions (Work In Progress)
  • general usage instructions
  • a contributing/development guide
  • debugging help

Meanwhile, I was thinking:
"What modules from which hosts? What does that have to do with DNS? What do the modules do exactly? Does that solve XY problem I’ve been having with DNS and NixOS? Does it setup a DNS-server for me or not? I’m con-f-used :wink: "

It should have a clean mission statement and an example of the kind of problems you’d use it for.

I tried putting this in the motivation section in the readme: GitHub - Janik-Haag/NixOS-DNS: Manage your dns zones with NixOS

1 Like

Thanks for adding the motivation, this definitely help at describing what this is about. This is an interesting concept which I guess could be generalized.

For example, today I manage all my WireGuard configuration in a single file, where all hosts are listed. But this might as well be aggregated from evaluating other hosts as well, thus the router / DNS server would list the host of the network, and pull the configuration evaluation as a mean to fetch some aggregate option definition for each of the hosts. This could be made available as a hidden option in config.system.build for example.

Another use case could be for doing some port forwarding from nginx. Where you want a jump host to forward a connection into your private network.

In general terms, any config where it make sense to define in a single logical module, but where multiple machines have to be configured from this single source of truth.

This would help with consistencies of configuration and reduce mistake!

I guess this might be worth an RFC to mention how the configuration can be exported, either by generating a new JSON, YAML, Nix file, or how it can be directly imported by evaluating the other hosts configuration which would provide such aggregate.

1 Like

I think I might be a few steps ahead of you and don’t want to get your hopes up… but I’m currently working on a proof of concept of building netbox datafiles with nix, reading the data from json.
And am planning to write nix functions so users can easily query that data and for example automatically map the ip-address/s that are associated with a given hostname to the hosts wan interfaces or generating network-manager vpn profiles.

There is two reason for wanting to read json instead of writing the data directly in nix, builtins.fromJson is to my knowledge the most efficient way to read a large amount of data in nix and the second thing is working with json in other programming languages is a lot easier then generating nix code, so in the future one could build upon that and write cli tooling that exports current configuration from netbox, helps with editing large config parts or implements some sort of ci-checks.

I’ll publish the poc once I finished it and will try to apply for funding to buy me time to built this out.

Overall I think this project would have a number of benefits, like less documentation drift and a better documented infrastructure, but also easier management of large scale NixOS deployments. Also think about having tooling like nixos vm tests that validate your deployment is actually working and then git bisecting over your network documentation and checking where a faulty configuration was introduced.

You should of course be able to use the Project without netbox but it’s the de facto standard network documentation tool, it’s open source and there is a team of people being paid to work on it full time.
There data modeling is quite thought out and regarded as one of the best in the industry, so replicating that data structure as nixos modules seems like the sensible thing to do. And if you choose to use it with netbox/integrate it into a existing deployment you also get all the netbox benifits, like an api for other people to build upon.

1 Like