nixos: Add option networking.networkmanager.dynamicHosts

This allows non-privileged users to configure local DNS
entries by editing hosts files read by NetworkManager's dnsmasq
instance.
This commit is contained in:
Rickard Nilsson 2018-06-08 16:59:32 +02:00
parent a381b78998
commit e6c3d5a507

View File

@ -6,6 +6,9 @@ with lib;
let
cfg = config.networking.networkmanager;
dynamicHostsEnabled =
cfg.dynamicHosts.enable && cfg.dynamicHosts.hostsDirs != {};
# /var/lib/misc is for dnsmasq.leases.
stateDirs = "/var/lib/NetworkManager /var/lib/dhclient /var/lib/misc";
@ -253,6 +256,51 @@ in {
so you don't need to to that yourself.
'';
};
dynamicHosts = {
enable = mkOption {
type = types.bool;
default = false;
description = ''
Enabling this option requires the
<option>networking.networkmanager.useDnsmasq</option> option to be
enabled too. If enabled, the directories defined by the
<option>networking.networkmanager.dynamicHosts.hostsDirs</option>
option will be set up when the service starts. The dnsmasq instance
managed by NetworkManager will then watch those directories for
hosts files (see the <literal>--hostsdir</literal> option of
dnsmasq). This way a non-privileged user can add or override DNS
entries on the local system (depending on what hosts directories
that are configured)..
'';
};
hostsDirs = mkOption {
type = with types; attrsOf (submodule {
options = {
user = mkOption {
type = types.str;
default = "root";
description = ''
The user that will own the hosts directory.
'';
};
group = mkOption {
type = types.str;
default = "root";
description = ''
The group that will own the hosts directory.
'';
};
};
});
default = {};
description = ''
Defines a set of directories (relative to
<literal>/run/NetworkManager/hostdirs</literal>) that dnsmasq will
watch for hosts files.
'';
};
};
};
};
@ -261,10 +309,17 @@ in {
config = mkIf cfg.enable {
assertions = [{
assertion = config.networking.wireless.enable == false;
message = "You can not use networking.networkmanager with networking.wireless";
}];
assertions = [
{ assertion = config.networking.wireless.enable == false;
message = "You can not use networking.networkmanager with networking.wireless";
}
{ assertion = dynamicHostsEnabled && cfg.useDnsmasq;
message = ''
To use networking.networkmanager.dynamicHosts you also need to enable
networking.networkmanager.useDnsmasq
'';
}
];
environment.etc = with cfg.basePackages; [
{ source = configFile;
@ -298,7 +353,13 @@ in {
++ lib.imap1 (i: s: {
inherit (s) source;
target = "NetworkManager/dispatcher.d/${dispatcherTypesSubdirMap.${s.type}}03userscript${lib.fixedWidthNumber 4 i}";
}) cfg.dispatcherScripts;
}) cfg.dispatcherScripts
++ optional (dynamicHostsEnabled)
{ target = "NetworkManager/dnsmasq.d/dyndns.conf";
text = concatMapStrings (n: ''
hostsdir=/run/NetworkManager/hostsdirs/${n}
'') (attrNames cfg.dynamicHosts.hostsDirs);
};
environment.systemPackages = cfg.packages;
@ -334,6 +395,21 @@ in {
'';
};
systemd.services.nm-setup-hostsdirs = mkIf dynamicHostsEnabled {
wantedBy = [ "network-manager.service" ];
before = [ "network-manager.service" ];
partOf = [ "network-manager.service" ];
script = concatStrings (mapAttrsToList (n: d: ''
mkdir -p "/run/NetworkManager/hostsdirs/${n}"
chown "${d.user}:${d.group}" "/run/NetworkManager/hostsdirs/${n}"
chmod 0775 "/run/NetworkManager/hostsdirs/${n}"
'') cfg.dynamicHosts.hostsDirs);
serviceConfig = {
Type = "oneshot";
RemainAfterExist = true;
};
};
# Turn off NixOS' network management
networking = {
useDHCP = false;