nixpkgs/nixos/modules/services/networking/unbound.nix
Nikolay Amiantov 01b90dce78 resolvconf service: init
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.
2019-07-15 20:25:39 +03:00

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";
};
}