at 17.09-beta 10 kB view raw
1{ config, lib, pkgs, ... }: 2 3with pkgs; 4with lib; 5 6let 7 cfg = config.networking.networkmanager; 8 9 # /var/lib/misc is for dnsmasq.leases. 10 stateDirs = "/var/lib/NetworkManager /var/lib/dhclient /var/lib/misc"; 11 12 dns = 13 if cfg.useDnsmasq then "dnsmasq" 14 else if config.services.resolved.enable then "systemd-resolved" 15 else if config.services.unbound.enable then "unbound" 16 else "default"; 17 18 configFile = writeText "NetworkManager.conf" '' 19 [main] 20 plugins=keyfile 21 dhcp=${cfg.dhcp} 22 dns=${dns} 23 24 [keyfile] 25 ${optionalString (cfg.unmanaged != []) 26 ''unmanaged-devices=${lib.concatStringsSep ";" cfg.unmanaged}''} 27 28 [logging] 29 level=${cfg.logLevel} 30 31 [connection] 32 ipv6.ip6-privacy=2 33 ethernet.cloned-mac-address=${cfg.ethernet.macAddress} 34 wifi.cloned-mac-address=${cfg.wifi.macAddress} 35 ''; 36 37 /* 38 [network-manager] 39 Identity=unix-group:networkmanager 40 Action=org.freedesktop.NetworkManager.* 41 ResultAny=yes 42 ResultInactive=no 43 ResultActive=yes 44 45 [modem-manager] 46 Identity=unix-group:networkmanager 47 Action=org.freedesktop.ModemManager* 48 ResultAny=yes 49 ResultInactive=no 50 ResultActive=yes 51 */ 52 polkitConf = '' 53 polkit.addRule(function(action, subject) { 54 if ( 55 subject.isInGroup("networkmanager") 56 && (action.id.indexOf("org.freedesktop.NetworkManager.") == 0 57 || action.id.indexOf("org.freedesktop.ModemManager") == 0 58 )) 59 { return polkit.Result.YES; } 60 }); 61 ''; 62 63 ns = xs: writeText "nameservers" ( 64 concatStrings (map (s: "nameserver ${s}\n") xs) 65 ); 66 67 overrideNameserversScript = writeScript "02overridedns" '' 68 #!/bin/sh 69 tmp=`${coreutils}/bin/mktemp` 70 ${gnused}/bin/sed '/nameserver /d' /etc/resolv.conf > $tmp 71 ${gnugrep}/bin/grep 'nameserver ' /etc/resolv.conf | \ 72 ${gnugrep}/bin/grep -vf ${ns (cfg.appendNameservers ++ cfg.insertNameservers)} > $tmp.ns 73 ${optionalString (cfg.appendNameservers != []) "${coreutils}/bin/cat $tmp $tmp.ns ${ns cfg.appendNameservers} > /etc/resolv.conf"} 74 ${optionalString (cfg.insertNameservers != []) "${coreutils}/bin/cat $tmp ${ns cfg.insertNameservers} $tmp.ns > /etc/resolv.conf"} 75 ${coreutils}/bin/rm -f $tmp $tmp.ns 76 ''; 77 78 dispatcherTypesSubdirMap = { 79 "basic" = ""; 80 "pre-up" = "pre-up.d/"; 81 "pre-down" = "pre-down.d/"; 82 }; 83 84 macAddressOpt = mkOption { 85 type = types.either types.str (types.enum ["permanent" "preserve" "random" "stable"]); 86 default = "preserve"; 87 example = "00:11:22:33:44:55"; 88 description = '' 89 "XX:XX:XX:XX:XX:XX": MAC address of the interface. 90 <literal>permanent</literal>: use the permanent MAC address of the device. 91 <literal>preserve</literal>: dont change the MAC address of the device upon activation. 92 <literal>random</literal>: generate a randomized value upon each connect. 93 <literal>stable</literal>: generate a stable, hashed MAC address. 94 ''; 95 }; 96 97in { 98 99 ###### interface 100 101 options = { 102 103 networking.networkmanager = { 104 105 enable = mkOption { 106 type = types.bool; 107 default = false; 108 description = '' 109 Whether to use NetworkManager to obtain an IP address and other 110 configuration for all network interfaces that are not manually 111 configured. If enabled, a group <literal>networkmanager</literal> 112 will be created. Add all users that should have permission 113 to change network settings to this group. 114 ''; 115 }; 116 117 unmanaged = mkOption { 118 type = types.listOf types.string; 119 default = []; 120 description = '' 121 List of interfaces that will not be managed by NetworkManager. 122 Interface name can be specified here, but if you need more fidelity 123 see "Device List Format" in NetworkManager.conf man page. 124 ''; 125 }; 126 127 # Ugly hack for using the correct gnome3 packageSet 128 basePackages = mkOption { 129 type = types.attrsOf types.package; 130 default = { inherit networkmanager modemmanager wpa_supplicant 131 networkmanager_openvpn networkmanager_vpnc 132 networkmanager_openconnect networkmanager_fortisslvpn 133 networkmanager_pptp networkmanager_l2tp 134 networkmanager_iodine; }; 135 internal = true; 136 }; 137 138 packages = mkOption { 139 type = types.listOf types.path; 140 default = [ ]; 141 description = '' 142 Extra packages that provide NetworkManager plugins. 143 ''; 144 apply = list: (attrValues cfg.basePackages) ++ list; 145 }; 146 147 dhcp = mkOption { 148 type = types.enum [ "dhclient" "dhcpcd" "internal" ]; 149 default = "dhclient"; 150 description = '' 151 Which program (or internal library) should be used for DHCP. 152 ''; 153 }; 154 155 logLevel = mkOption { 156 type = types.enum [ "OFF" "ERR" "WARN" "INFO" "DEBUG" "TRACE" ]; 157 default = "WARN"; 158 description = '' 159 Set the default logging verbosity level. 160 ''; 161 }; 162 163 appendNameservers = mkOption { 164 type = types.listOf types.str; 165 default = []; 166 description = '' 167 A list of name servers that should be appended 168 to the ones configured in NetworkManager or received by DHCP. 169 ''; 170 }; 171 172 insertNameservers = mkOption { 173 type = types.listOf types.str; 174 default = []; 175 description = '' 176 A list of name servers that should be inserted before 177 the ones configured in NetworkManager or received by DHCP. 178 ''; 179 }; 180 181 ethernet.macAddress = macAddressOpt; 182 wifi.macAddress = macAddressOpt; 183 184 useDnsmasq = mkOption { 185 type = types.bool; 186 default = false; 187 description = '' 188 Enable NetworkManager's dnsmasq integration. NetworkManager will run 189 dnsmasq as a local caching nameserver, using a "split DNS" 190 configuration if you are connected to a VPN, and then update 191 resolv.conf to point to the local nameserver. 192 ''; 193 }; 194 195 dispatcherScripts = mkOption { 196 type = types.listOf (types.submodule { 197 options = { 198 source = mkOption { 199 type = types.path; 200 description = '' 201 A script. 202 ''; 203 }; 204 205 type = mkOption { 206 type = types.enum (attrNames dispatcherTypesSubdirMap); 207 default = "basic"; 208 description = '' 209 Dispatcher hook type. Only basic hooks are currently available. 210 ''; 211 }; 212 }; 213 }); 214 default = []; 215 description = '' 216 A list of scripts which will be executed in response to network events. 217 ''; 218 }; 219 }; 220 }; 221 222 223 ###### implementation 224 225 config = mkIf cfg.enable { 226 227 assertions = [{ 228 assertion = config.networking.wireless.enable == false; 229 message = "You can not use networking.networkmanager with networking.wireless"; 230 }]; 231 232 boot.kernelModules = [ "ppp_mppe" ]; # Needed for most (all?) PPTP VPN connections. 233 234 environment.etc = with cfg.basePackages; [ 235 { source = configFile; 236 target = "NetworkManager/NetworkManager.conf"; 237 } 238 { source = "${networkmanager_openvpn}/etc/NetworkManager/VPN/nm-openvpn-service.name"; 239 target = "NetworkManager/VPN/nm-openvpn-service.name"; 240 } 241 { source = "${networkmanager_vpnc}/etc/NetworkManager/VPN/nm-vpnc-service.name"; 242 target = "NetworkManager/VPN/nm-vpnc-service.name"; 243 } 244 { source = "${networkmanager_openconnect}/etc/NetworkManager/VPN/nm-openconnect-service.name"; 245 target = "NetworkManager/VPN/nm-openconnect-service.name"; 246 } 247 { source = "${networkmanager_fortisslvpn}/etc/NetworkManager/VPN/nm-fortisslvpn-service.name"; 248 target = "NetworkManager/VPN/nm-fortisslvpn-service.name"; 249 } 250 { source = "${networkmanager_pptp}/etc/NetworkManager/VPN/nm-pptp-service.name"; 251 target = "NetworkManager/VPN/nm-pptp-service.name"; 252 } 253 { source = "${networkmanager_l2tp}/etc/NetworkManager/VPN/nm-l2tp-service.name"; 254 target = "NetworkManager/VPN/nm-l2tp-service.name"; 255 } 256 { source = "${networkmanager_strongswan}/etc/NetworkManager/VPN/nm-strongswan-service.name"; 257 target = "NetworkManager/VPN/nm-strongswan-service.name"; 258 } 259 { source = "${networkmanager_iodine}/etc/NetworkManager/VPN/nm-iodine-service.name"; 260 target = "NetworkManager/VPN/nm-iodine-service.name"; 261 } 262 ] ++ optional (cfg.appendNameservers == [] || cfg.insertNameservers == []) 263 { source = overrideNameserversScript; 264 target = "NetworkManager/dispatcher.d/02overridedns"; 265 } 266 ++ lib.imap1 (i: s: { 267 inherit (s) source; 268 target = "NetworkManager/dispatcher.d/${dispatcherTypesSubdirMap.${s.type}}03userscript${lib.fixedWidthNumber 4 i}"; 269 }) cfg.dispatcherScripts; 270 271 environment.systemPackages = cfg.packages; 272 273 users.extraGroups = [{ 274 name = "networkmanager"; 275 gid = config.ids.gids.networkmanager; 276 } 277 { 278 name = "nm-openvpn"; 279 gid = config.ids.gids.nm-openvpn; 280 }]; 281 users.extraUsers = [{ 282 name = "nm-openvpn"; 283 uid = config.ids.uids.nm-openvpn; 284 extraGroups = [ "networkmanager" ]; 285 } 286 { 287 name = "nm-iodine"; 288 isSystemUser = true; 289 group = "networkmanager"; 290 }]; 291 292 systemd.packages = cfg.packages; 293 294 systemd.services."network-manager" = { 295 wantedBy = [ "network.target" ]; 296 restartTriggers = [ configFile ]; 297 298 preStart = '' 299 mkdir -m 700 -p /etc/NetworkManager/system-connections 300 mkdir -m 755 -p ${stateDirs} 301 ''; 302 }; 303 304 # Turn off NixOS' network management 305 networking = { 306 useDHCP = false; 307 # use mkDefault to trigger the assertion about the conflict above 308 wireless.enable = lib.mkDefault false; 309 }; 310 311 powerManagement.resumeCommands = '' 312 ${config.systemd.package}/bin/systemctl restart network-manager 313 ''; 314 315 security.polkit.extraConfig = polkitConf; 316 317 services.dbus.packages = cfg.packages; 318 319 services.udev.packages = cfg.packages; 320 }; 321}