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.

Cherry-picked from e6c3d5a507909c4e0c0a5013040684cce89c35ce and
5a566004a2b12c3d91bf0acdb704f1b40770c28f.
This commit is contained in:
Rickard Nilsson 2018-07-05 23:22:09 +02:00
parent 499203e199
commit d80292dbd2

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";
@ -317,6 +320,52 @@ 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.dns</option> option to be
set to <literal>dnsmasq</literal>. 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.
'';
};
};
};
};
@ -325,10 +374,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 || (dynamicHostsEnabled && cfg.dns == "dnsmasq");
message = ''
To use networking.networkmanager.dynamicHosts you also need to set
networking.networkmanager.dns = "dnsmasq"
'';
}
];
environment.etc = with cfg.basePackages; [
{ source = configFile;
@ -362,7 +418,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;
@ -398,6 +460,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;