forked from mirrors/nixpkgs
01b90dce78
This is a refactor of how resolvconf is managed on NixOS. We split it into a separate service which is enabled internally depending on whether we want /etc/resolv.conf to be managed by it. Various services now take advantage of those configuration options. We also now use systemd instead of activation scripts to update resolv.conf. NetworkManager now uses the right option for rc-manager DNS automatically, so the configuration option shouldn't be exposed.
142 lines
3.7 KiB
Nix
142 lines
3.7 KiB
Nix
{ config, lib, pkgs, ... }:
|
|
|
|
with lib;
|
|
|
|
let
|
|
|
|
cfg = config.services.unbound;
|
|
|
|
stateDir = "/var/lib/unbound";
|
|
|
|
access = concatMapStringsSep "\n " (x: "access-control: ${x} allow") cfg.allowedAccess;
|
|
|
|
interfaces = concatMapStringsSep "\n " (x: "interface: ${x}") cfg.interfaces;
|
|
|
|
isLocalAddress = x: substring 0 3 x == "::1" || substring 0 9 x == "127.0.0.1";
|
|
|
|
forward =
|
|
optionalString (any isLocalAddress cfg.forwardAddresses) ''
|
|
do-not-query-localhost: no
|
|
'' +
|
|
optionalString (cfg.forwardAddresses != []) ''
|
|
forward-zone:
|
|
name: .
|
|
'' +
|
|
concatMapStringsSep "\n" (x: " forward-addr: ${x}") cfg.forwardAddresses;
|
|
|
|
rootTrustAnchorFile = "${stateDir}/root.key";
|
|
|
|
trustAnchor = optionalString cfg.enableRootTrustAnchor
|
|
"auto-trust-anchor-file: ${rootTrustAnchorFile}";
|
|
|
|
confFile = pkgs.writeText "unbound.conf" ''
|
|
server:
|
|
directory: "${stateDir}"
|
|
username: unbound
|
|
chroot: "${stateDir}"
|
|
pidfile: ""
|
|
${interfaces}
|
|
${access}
|
|
${trustAnchor}
|
|
${cfg.extraConfig}
|
|
${forward}
|
|
'';
|
|
|
|
in
|
|
|
|
{
|
|
|
|
###### interface
|
|
|
|
options = {
|
|
services.unbound = {
|
|
|
|
enable = mkEnableOption "Unbound domain name server";
|
|
|
|
allowedAccess = mkOption {
|
|
default = [ "127.0.0.0/24" ];
|
|
type = types.listOf types.str;
|
|
description = "What networks are allowed to use unbound as a resolver.";
|
|
};
|
|
|
|
interfaces = mkOption {
|
|
default = [ "127.0.0.1" ] ++ optional config.networking.enableIPv6 "::1";
|
|
type = types.listOf types.str;
|
|
description = "What addresses the server should listen on.";
|
|
};
|
|
|
|
forwardAddresses = mkOption {
|
|
default = [ ];
|
|
type = types.listOf types.str;
|
|
description = "What servers to forward queries to.";
|
|
};
|
|
|
|
enableRootTrustAnchor = mkOption {
|
|
default = true;
|
|
type = types.bool;
|
|
description = "Use and update root trust anchor for DNSSEC validation.";
|
|
};
|
|
|
|
extraConfig = mkOption {
|
|
default = "";
|
|
type = types.lines;
|
|
description = ''
|
|
Extra unbound config. See
|
|
<citerefentry><refentrytitle>unbound.conf</refentrytitle><manvolnum>8
|
|
</manvolnum></citerefentry>.
|
|
'';
|
|
};
|
|
|
|
};
|
|
};
|
|
|
|
###### implementation
|
|
|
|
config = mkIf cfg.enable {
|
|
|
|
environment.systemPackages = [ pkgs.unbound ];
|
|
|
|
users.users.unbound = {
|
|
description = "unbound daemon user";
|
|
isSystemUser = true;
|
|
};
|
|
|
|
networking.resolvconf.useLocalResolver = mkDefault true;
|
|
|
|
systemd.services.unbound = {
|
|
description = "Unbound recursive Domain Name Server";
|
|
after = [ "network.target" ];
|
|
before = [ "nss-lookup.target" ];
|
|
wants = [ "nss-lookup.target" ];
|
|
wantedBy = [ "multi-user.target" ];
|
|
|
|
preStart = ''
|
|
mkdir -m 0755 -p ${stateDir}/dev/
|
|
cp ${confFile} ${stateDir}/unbound.conf
|
|
${optionalString cfg.enableRootTrustAnchor ''
|
|
${pkgs.unbound}/bin/unbound-anchor -a ${rootTrustAnchorFile} || echo "Root anchor updated!"
|
|
chown unbound ${stateDir} ${rootTrustAnchorFile}
|
|
''}
|
|
touch ${stateDir}/dev/random
|
|
${pkgs.utillinux}/bin/mount --bind -n /dev/urandom ${stateDir}/dev/random
|
|
'';
|
|
|
|
serviceConfig = {
|
|
ExecStart = "${pkgs.unbound}/bin/unbound -d -c ${stateDir}/unbound.conf";
|
|
ExecStopPost="${pkgs.utillinux}/bin/umount ${stateDir}/dev/random";
|
|
|
|
ProtectSystem = true;
|
|
ProtectHome = true;
|
|
PrivateDevices = true;
|
|
Restart = "always";
|
|
RestartSec = "5s";
|
|
};
|
|
};
|
|
|
|
# If networkmanager is enabled, ask it to interface with unbound.
|
|
networking.networkmanager.dns = "unbound";
|
|
|
|
};
|
|
|
|
}
|