summary refs log tree commit diff
path: root/nixos/modules/services/networking/wpa_supplicant.nix
diff options
context:
space:
mode:
Diffstat (limited to 'nixos/modules/services/networking/wpa_supplicant.nix')
-rw-r--r--nixos/modules/services/networking/wpa_supplicant.nix163
1 files changed, 78 insertions, 85 deletions
diff --git a/nixos/modules/services/networking/wpa_supplicant.nix b/nixos/modules/services/networking/wpa_supplicant.nix
index 9e04bd401906..1b655af6c82d 100644
--- a/nixos/modules/services/networking/wpa_supplicant.nix
+++ b/nixos/modules/services/networking/wpa_supplicant.nix
@@ -3,51 +3,30 @@
 with lib;
 
 let
-
   cfg = config.networking.wireless;
-  configFile = "/etc/wpa_supplicant.conf";
-
-  ifaces =
-    cfg.interfaces ++
-    optional (config.networking.WLANInterface != "") config.networking.WLANInterface;
-
-in
-
-{
-
-  ###### interface
-
+  configFile = if cfg.networks != {} then pkgs.writeText "wpa_supplicant.conf" ''
+    ${optionalString cfg.userControlled.enable ''
+      ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=${cfg.userControlled.group}
+      update_config=1''}
+    ${concatStringsSep "\n" (mapAttrsToList (ssid: networkConfig: ''
+      network={
+        ssid="${ssid}"
+        ${optionalString (networkConfig.psk != null) ''psk="${networkConfig.psk}"''}
+        ${optionalString (networkConfig.psk == null) ''key_mgmt=NONE''}
+      }
+    '') cfg.networks)}
+  '' else "/etc/wpa_supplicant.conf";
+in {
   options = {
-
-    networking.WLANInterface = mkOption {
-      default = "";
-      description = "Obsolete. Use <option>networking.wireless.interfaces</option> instead.";
-    };
-
     networking.wireless = {
-      enable = mkOption {
-        type = types.bool;
-        default = false;
-        description = ''
-          Whether to start <command>wpa_supplicant</command> to scan for
-          and associate with wireless networks.  Note: NixOS currently
-          does not manage <command>wpa_supplicant</command>'s
-          configuration file, <filename>${configFile}</filename>.  You
-          should edit this file yourself to define wireless networks,
-          WPA keys and so on (see
-          <citerefentry><refentrytitle>wpa_supplicant.conf</refentrytitle>
-          <manvolnum>5</manvolnum></citerefentry>), or use
-          networking.wireless.userControlled.* to allow users to add entries
-          through <command>wpa_cli</command> and <command>wpa_gui</command>.
-        '';
-      };
+      enable = mkEnableOption "wpa_supplicant";
 
       interfaces = mkOption {
         type = types.listOf types.str;
         default = [];
         example = [ "wlan0" "wlan1" ];
         description = ''
-          The interfaces <command>wpa_supplicant</command> will use.  If empty, it will
+          The interfaces <command>wpa_supplicant</command> will use. If empty, it will
           automatically use all wireless interfaces.
         '';
       };
@@ -58,6 +37,37 @@ in
         description = "Force a specific wpa_supplicant driver.";
       };
 
+      networks = mkOption {
+        type = types.attrsOf (types.submodule {
+          options = {
+            psk = mkOption {
+              type = types.nullOr types.str;
+              default = null;
+              description = ''
+                The network's pre-shared key in plaintext defaulting
+                to being a network without any authentication.
+
+                Be aware that these will be written to the nix store
+                in plaintext!
+              '';
+            };
+          };
+        });
+        description = ''
+          The network definitions to automatically connect to when
+           <command>wpa_supplicant</command> is running. If this
+           parameter is left empty wpa_supplicant will use
+          /etc/wpa_supplicant.conf as the configuration file.
+        '';
+        default = {};
+        example = literalExample ''
+          echelon = {
+            psk = "abcdefgh";
+          };
+          "free.wifi" = {};
+        '';
+      };
+
       userControlled = {
         enable = mkOption {
           type = types.bool;
@@ -68,10 +78,8 @@ in
             to depend on a large package such as NetworkManager just to pick nearby
             access points.
 
-            When you want to use this, make sure ${configFile} doesn't exist.
-            It will be created for you.
-
-            Currently it is also necessary to explicitly specify networking.wireless.interfaces.
+            When using a declarative network specification you cannot persist any
+            settings via wpa_gui or wpa_cli.
           '';
         };
 
@@ -85,64 +93,49 @@ in
     };
   };
 
+  config = mkMerge [
+    (mkIf cfg.enable {
+      environment.systemPackages =  [ pkgs.wpa_supplicant ];
 
-  ###### implementation
-
-  config = mkIf cfg.enable {
-
-    environment.systemPackages =  [ pkgs.wpa_supplicant ];
-
-    services.dbus.packages = [ pkgs.wpa_supplicant ];
+      services.dbus.packages = [ pkgs.wpa_supplicant ];
 
-    # FIXME: start a separate wpa_supplicant instance per interface.
-    jobs.wpa_supplicant =
-      { description = "WPA Supplicant";
+      # FIXME: start a separate wpa_supplicant instance per interface.
+      systemd.services.wpa_supplicant = let
+        ifaces = cfg.interfaces;
+      in {
+        description = "WPA Supplicant";
 
         wantedBy = [ "network.target" ];
 
         path = [ pkgs.wpa_supplicant ];
 
-        preStart = ''
-          touch -a ${configFile}
-          chmod 600 ${configFile}
-        '' + optionalString cfg.userControlled.enable ''
-          if [ ! -s ${configFile} ]; then
-            echo "ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=${cfg.userControlled.group}" >> ${configFile}
-            echo "update_config=1" >> ${configFile}
-          fi
+        script = ''
+          ${if ifaces == [] then ''
+            for i in $(cd /sys/class/net && echo *); do
+              DEVTYPE=
+              source /sys/class/net/$i/uevent
+              if [ "$DEVTYPE" = "wlan" -o -e /sys/class/net/$i/wireless ]; then
+                ifaces="$ifaces''${ifaces:+ -N} -i$i"
+              fi
+            done
+          '' else ''
+            ifaces="${concatStringsSep " -N " (map (i: "-i${i}") ifaces)}"
+          ''}
+          exec wpa_supplicant -s -u -D${cfg.driver} -c ${configFile} $ifaces
         '';
-
-        script =
-          ''
-            ${if ifaces == [] then ''
-              for i in $(cd /sys/class/net && echo *); do
-                DEVTYPE=
-                source /sys/class/net/$i/uevent
-                if [ "$DEVTYPE" = "wlan" -o -e /sys/class/net/$i/wireless ]; then
-                  ifaces="$ifaces''${ifaces:+ -N} -i$i"
-                fi
-              done
-            '' else ''
-              ifaces="${concatStringsSep " -N " (map (i: "-i${i}") ifaces)}"
-            ''}
-            exec wpa_supplicant -s -u -D${cfg.driver} -c ${configFile} $ifaces
-          '';
       };
 
-    powerManagement.resumeCommands =
-      ''
+      powerManagement.resumeCommands = ''
         ${config.systemd.package}/bin/systemctl try-restart wpa_supplicant
       '';
 
-    assertions = [{ assertion = !cfg.userControlled.enable || cfg.interfaces != [];
-                    message = "user controlled wpa_supplicant needs explicit networking.wireless.interfaces";}];
-
-    # Restart wpa_supplicant when a wlan device appears or disappears.
-    services.udev.extraRules =
-      ''
+      # Restart wpa_supplicant when a wlan device appears or disappears.
+      services.udev.extraRules = ''
         ACTION=="add|remove", SUBSYSTEM=="net", ENV{DEVTYPE}=="wlan", RUN+="${config.systemd.package}/bin/systemctl try-restart wpa_supplicant.service"
       '';
-
-  };
-
+    })
+    {
+      meta.maintainers = with lib.maintainers; [ globin ];
+    }
+  ];
 }