summary refs log tree commit diff
path: root/nixos/modules/services/networking/networkmanager.nix
blob: 1d5682f5f3fba104dba7b5ce7ca9ffe9bb3d952a (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
{ config, pkgs, ... }:

with pkgs.lib;
with pkgs;

let
  cfg = config.networking.networkmanager;

  stateDirs = "/var/lib/NetworkManager /var/lib/dhclient";

  configFile = writeText "NetworkManager.conf" ''
    [main]
    plugins=keyfile

    [keyfile]
    ${optionalString (config.networking.hostName != "") ''
      hostname=${config.networking.hostName}
    ''}

    [logging]
    level=WARN
  '';

  polkitConf = ''
    [network-manager]
    Identity=unix-group:networkmanager
    Action=org.freedesktop.NetworkManager.*
    ResultAny=yes
    ResultInactive=no
    ResultActive=yes

    [modem-manager]
    Identity=unix-group:networkmanager
    Action=org.freedesktop.ModemManager.*
    ResultAny=yes
    ResultInactive=no
    ResultActive=yes
  '';

  ipUpScript = writeScript "01nixos-ip-up" ''
    #!/bin/sh
    if test "$2" = "up"; then
      ${config.systemd.package}/bin/systemctl start ip-up.target
    fi
  '';

  overrideNameserversScript = writeScript "02overridedns" ''
    #!/bin/sh
    ${optionalString cfg.overrideNameservers "${gnused}/bin/sed -i '/nameserver /d' /etc/resolv.conf"}
    ${concatStrings (map (s: ''
      ${optionalString cfg.appendNameservers
        "${gnused}/bin/sed -i '/nameserver ${s}/d' /etc/resolv.conf"
      }
      echo 'nameserver ${s}' >> /etc/resolv.conf
    '') config.networking.nameservers)}
  '';

in {

  ###### interface

  options = {

    networking.networkmanager = {

      enable = mkOption {
        default = false;
        merge = mergeEnableOption;
        description = ''
          Whether to use NetworkManager to obtain an IP address and other
          configuration for all network interfaces that are not manually
          configured. If enabled, a group <literal>networkmanager</literal>
          will be created. Add all users that should have permission
          to change network settings to this group.
        '';
      };
  
      packages = mkOption {
        default = [ ];
        description = ''
          Extra packages that provide NetworkManager plugins.
        '';
        merge = mergeListOption;
        apply = list: [ networkmanager modemmanager wpa_supplicant ] ++ list;
      };

      overrideNameservers = mkOption {
        default = false;
        description = ''
          If enabled, any nameservers received by DHCP or configured in
          NetworkManager will be replaced by the nameservers configured
          in the <literal>networking.nameservers</literal> option. This
          option overrides the <literal>appendNameservers</literal> option
          if both are enabled.
        '';
      };

      appendNameservers = mkOption {
        default = false;
        description = ''
          If enabled, the name servers configured in the
          <literal>networking.nameservers</literal> option will be appended
          to the ones configured in NetworkManager or received by DHCP.
        '';
      };

    };
  };


  ###### implementation

  config = mkIf cfg.enable {

    assertions = [{
      assertion = config.networking.wireless.enable == false;
      message = "You can not use networking.networkmanager with services.networking.wireless";
    }];

    environment.etc = [
      { source = ipUpScript;
        target = "NetworkManager/dispatcher.d/01nixos-ip-up";
      }
      { source = configFile;
        target = "NetworkManager/NetworkManager.conf";
      }
      { source = "${networkmanager_openvpn}/etc/NetworkManager/VPN/nm-openvpn-service.name";
        target = "NetworkManager/VPN/nm-openvpn-service.name";
      }
      { source = "${networkmanager_vpnc}/etc/NetworkManager/VPN/nm-vpnc-service.name";
        target = "NetworkManager/VPN/nm-vpnc-service.name";
      }
      { source = "${networkmanager_openconnect}/etc/NetworkManager/VPN/nm-openconnect-service.name";
        target = "NetworkManager/VPN/nm-openconnect-service.name";
      }
    ] ++ pkgs.lib.optional (cfg.overrideNameservers || cfg.appendNameservers)
           { source = overrideNameserversScript;
             target = "NetworkManager/dispatcher.d/02overridedns";
           };

    environment.systemPackages = cfg.packages ++ [
        networkmanager_openvpn
        networkmanager_vpnc
        networkmanager_openconnect
        ];

    users.extraGroups = singleton {
      name = "networkmanager";
      gid = config.ids.gids.networkmanager;
    };

    systemd.packages = cfg.packages;

    # Create an initialisation service that both starts
    # NetworkManager when network.target is reached,
    # and sets up necessary directories for NM.
    systemd.services."networkmanager-init" = {
      description = "NetworkManager initialisation";
      wantedBy = [ "network.target" ];
      partOf = [ "NetworkManager.service" ];
      wants = [ "NetworkManager.service" ];
      before = [ "NetworkManager.service" ];
      script = ''
        mkdir -m 700 -p /etc/NetworkManager/system-connections
        mkdir -m 755 -p ${stateDirs}
      '';
      serviceConfig = {
        Type = "oneshot";
      };
    };

    # Turn off NixOS' network management
    networking = {
      useDHCP = false;
      wireless.enable = false;
    };

    powerManagement.resumeCommands = ''
      systemctl restart NetworkManager
    '';

    security.polkit.permissions = polkitConf;

    # openvpn plugin has only dbus interface
    services.dbus.packages = cfg.packages ++ [
        networkmanager_openvpn
        networkmanager_vpnc
        networkmanager_openconnect
        ];

    services.udev.packages = cfg.packages;
  };
}