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