8 cfg = config.services.dnsdist;
10 toLua = lib.generators.toLua { };
12 mkBind = cfg: toLua "${cfg.listenAddress}:${toString cfg.listenPort}";
14 configFile = pkgs.writeText "dnsdist.conf" ''
15 setLocal(${mkBind cfg})
16 ${lib.optionalString cfg.dnscrypt.enable dnscryptSetup}
23 provider_key = ${toLua cfg.dnscrypt.providerKey}
24 cert_lifetime = ${toLua cfg.dnscrypt.certLifetime} * 60
26 function file_exists(name)
27 local f = io.open(name, "r")
28 return f ~= nil and io.close(f)
31 function dnscrypt_setup()
32 -- generate provider keys on first run
33 if provider_key == nil then
34 provider_key = "/var/lib/dnsdist/private.key"
35 if not file_exists(provider_key) then
36 generateDNSCryptProviderKeys("/var/lib/dnsdist/public.key",
37 "/var/lib/dnsdist/private.key")
38 print("DNSCrypt: generated provider keypair")
42 -- generate resolver certificate
44 generateDNSCryptCertificate(
45 provider_key, "/run/dnsdist/resolver.cert", "/run/dnsdist/resolver.key",
46 cert_serial, now - 60, now + cert_lifetime)
48 ${mkBind cfg.dnscrypt}, ${toLua cfg.dnscrypt.providerName},
49 "/run/dnsdist/resolver.cert", "/run/dnsdist/resolver.key")
52 function maintenance()
53 -- certificate rotation
55 local dnscrypt = getDNSCryptBind(0)
57 if ((now - last_rotation) > 0.9 * cert_lifetime) then
58 -- generate and start using a new certificate
59 dnscrypt:generateAndLoadInMemoryCertificate(
60 provider_key, cert_serial + 1,
61 now - 60, now + cert_lifetime)
63 -- stop advertising the last certificate
64 dnscrypt:markInactive(cert_serial)
66 -- remove the second to last certificate
67 if (cert_serial > 1) then
68 dnscrypt:removeInactiveCertificate(cert_serial - 1)
71 print("DNSCrypt: rotated certificate")
73 -- increment serial number
74 cert_serial = cert_serial + 1
86 enable = lib.mkEnableOption "dnsdist domain name server";
88 listenAddress = lib.mkOption {
90 description = "Listen IP address";
93 listenPort = lib.mkOption {
94 type = lib.types.port;
95 description = "Listen port";
100 enable = lib.mkEnableOption "a DNSCrypt endpoint to dnsdist";
102 listenAddress = lib.mkOption {
103 type = lib.types.str;
104 description = "Listen IP address of the endpoint";
108 listenPort = lib.mkOption {
109 type = lib.types.port;
110 description = "Listen port of the endpoint";
114 providerName = lib.mkOption {
115 type = lib.types.str;
116 default = "2.dnscrypt-cert.${config.networking.hostName}";
117 defaultText = lib.literalExpression "2.dnscrypt-cert.\${config.networking.hostName}";
118 example = "2.dnscrypt-cert.myresolver";
120 The name that will be given to this DNSCrypt resolver.
123 The provider name must start with `2.dnscrypt-cert.`.
128 providerKey = lib.mkOption {
129 type = lib.types.nullOr lib.types.path;
132 The filepath to the provider secret key.
133 If not given a new provider key pair will be generated in
134 /var/lib/dnsdist on the first run.
137 The file must be readable by the dnsdist user/group.
142 certLifetime = lib.mkOption {
143 type = lib.types.ints.positive;
146 The lifetime (in minutes) of the resolver certificate.
147 This will be automatically rotated before expiration.
153 extraConfig = lib.mkOption {
154 type = lib.types.lines;
157 Extra lines to be added verbatim to dnsdist.conf.
163 config = lib.mkIf cfg.enable {
164 users.users.dnsdist = {
165 description = "dnsdist daemons user";
170 users.groups.dnsdist = { };
172 systemd.packages = [ pkgs.dnsdist ];
174 systemd.services.dnsdist = {
175 wantedBy = [ "multi-user.target" ];
177 startLimitIntervalSec = 0;
181 RuntimeDirectory = "dnsdist";
182 StateDirectory = "dnsdist";
183 # upstream overrides for better nixos compatibility
186 "${pkgs.dnsdist}/bin/dnsdist --check-config --config ${configFile}"
190 "${pkgs.dnsdist}/bin/dnsdist --supervised --disable-syslog --config ${configFile}"