Wpa_supplicant stops working after upgrading NixOS from 25.11 to 26.05

I have a modular NixOS configuration that I mostly copied from some blogs I can’t remember. My wifi is set in a module that defines the following (and nothing else):

#root/modules/system/networking/default.nix
{
  networking.hostName = "myHostName";
  networking.wireless = {
    enable = true;
    networks."myNetwork".psk = "XXX";
    extraConfig = "ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=wheel";
  };
  networking.networkmanager.enable = false;
}

That’s from the official guidance on setting up wpa_supplicant in the NixOS configuration. None of the other modules deal with networking.

(Edit: I’m hearing that the wiki I linked above is not official)
The flake.nix file at the root of the directory includes the following:

#root/flake.nix
{
  description = "NixOS config";

  inputs = {
    nixpkgs.url = "github:NixOS/nixpkgs/nixos-25.11";
    home-manager = {
      url = "github:nix-community/home-manager/release-25.11";
      inputs.nixpkgs.follows = "nixpkgs";
    };
  };

  outputs = inputs@{ nixpkgs, home-manager, ... }: 
  let
    mkHost = hostname: nixpkgs.lib.nixosSystem {
      specialArgs = { inherit inputs; };
      modules = [
        ./hosts/${hostname}
        ./modules/system
        ./modules/user/system-level
        home-manager.nixosModules.home-manager {
          home-manager = {
            useGlobalPkgs = true;
            useUserPackages = true;
            users.me = import ./modules/user/home-manager;
            extraSpecialArgs = { inherit inputs; };
          };
        }
      ];
    };
  in
  {
    nixosConfigurations = {
      myHostName = mkHost "myHostName";
    };
  };
}

I have no issues until I change the flake inputs to their 26.05 versions (and update the flake lock file/rebuild). Then after rebooting I have no wifi connection. Here are some command outputs (taken from this discourse post):

$ systemctl status wpa_supplicant
× wpa_supplicant.service - WPA Supplicant instance
     Loaded: loaded (/etc/systemd/system/wpa_supplicant.service; enabled; preset: ignored)
     Active: failed (Result: exit-code) since Mon 2026-08-03 00:36:50 EDT; 2min 8s ago
   Duration: 1.504s
 Invocation: 4415daa3da0c42c094eae2c83486a25a
    Process: 623 ExecStart=/nix/store/n58zh5ph3gyxkywbpi6bhxixnnnq96lv-unit-script-wpa_supplicant-start/bin/wpa_supplicant-start (code=exited, status=255/EXCEPTION)
   Main PID: 623 (code=exited, status=255/EXCEPTION)
         IP: 0B in, 0B out
         IO: 10M read, 0B written
   Mem peak: 12.5M
        CPU: 173ms

Aug 03 00:36:49 myHostName wpa_supplicant-start[623]: Adding interface wlp3s0
Aug 03 00:36:50 myHostName wpa_supplicant[623]: Successfully initialized wpa_supplicant
Aug 03 00:36:50 myHostName wpa_supplicant[623]: mkdir[ctrl_interface=/var/run/wpa_supplicant]: No such file or directory
Aug 03 00:36:50 myHostName systemd[1]: wpa_supplicant.service: Main process exited, code=exited, status=255/EXCEPTION
Aug 03 00:36:50 myHostName wpa_supplicant[623]: Failed to initialize control interface 'DIR=/var/run/wpa_supplicant GROUP=wheel'.
                                                You may have another wpa_supplicant process already running or the file was
                                                left by an unclean termination of wpa_supplicant in which case you will need
                                                to manually remove this file before starting wpa_supplicant again.
Aug 03 00:36:50 myHostName systemd[1]: wpa_supplicant.service: Failed with result 'exit-code'.
Aug 03 00:36:50 myHostName wpa_supplicant[623]: wlp3s0: CTRL-EVENT-DSCP-POLICY clear_all
Aug 03 00:36:50 myHostName systemd[1]: wpa_supplicant.service: Consumed 173ms CPU time over 1.504s wall clock time, 12.5M memory peak, 10M read from disk.
Aug 03 00:36:50 myHostName wpa_supplicant[623]: wlp3s0: CTRL-EVENT-DSCP-POLICY clear_all
Aug 03 00:36:50 myHostName wpa_supplicant[623]: nl80211: deinit ifname=wlp3s0 disabled_11b_rates=0
$ journalctl -b -u wpa_supplicant
Aug 03 00:36:48 myHostName systemd[1]: Started WPA Supplicant instance.
Aug 03 00:36:49 myHostName wpa_supplicant-start[623]: Adding interface wlp3s0
Aug 03 00:36:50 myHostName wpa_supplicant[623]: Successfully initialized wpa_supplicant
Aug 03 00:36:50 myHostName wpa_supplicant[623]: mkdir[ctrl_interface=/var/run/wpa_supplicant]: No such file or directory
Aug 03 00:36:50 myHostName systemd[1]: wpa_supplicant.service: Main process exited, code=exited, status=255/EXCEPTION
Aug 03 00:36:50 myHostName wpa_supplicant[623]: Failed to initialize control interface 'DIR=/var/run/wpa_supplicant GROUP=wheel'.
                                                You may have another wpa_supplicant process already running or the file was
                                                left by an unclean termination of wpa_supplicant in which case you will need
                                                to manually remove this file before starting wpa_supplicant again.
Aug 03 00:36:50 myHostName systemd[1]: wpa_supplicant.service: Failed with result 'exit-code'.
Aug 03 00:36:50 myHostName wpa_supplicant[623]: wlp3s0: CTRL-EVENT-DSCP-POLICY clear_all
Aug 03 00:36:50 myHostName systemd[1]: wpa_supplicant.service: Consumed 173ms CPU time over 1.504s wall clock time, 12.5M memory peak, 10M read from disk.
Aug 03 00:36:50 myHostName wpa_supplicant[623]: wlp3s0: CTRL-EVENT-DSCP-POLICY clear_all
Aug 03 00:36:50 myHostName wpa_supplicant[623]: nl80211: deinit ifname=wlp3s0 disabled_11b_rates=0

This is the relevant hardware information, I think. IDK how wifi works though…

03:00.0 Network controller: Intel Corporation Wireless 3165 (rev 79)
	Subsystem: Intel Corporation Device 4410
	Control: I/O- Mem+ BusMaster+ SpecCycle- MemWINV- VGASnoop- ParErr- Stepping- SERR- FastB2B- DisINTx+
	Status: Cap+ 66MHz- UDF- FastB2B- ParErr- DEVSEL=fast >TAbort- <TAbort- <MAbort- >SERR- <PERR- INTx-
	Latency: 0
	Interrupts: pin B disabled, MSI(X) routed to IRQ 137
	Region 0: Memory at df200000 (64-bit, non-prefetchable) [size=8K]
	Capabilities: [c8] Power Management version 3
		Flags: PMEClk- DSI+ D1- D2- AuxCurrent=0mA PME(D0+,D1-,D2-,D3hot+,D3cold+)
		Status: D0 NoSoftRst- PME-Enable- DSel=0 DScale=0 PME-
	Capabilities: [d0] MSI: Enable+ Count=1/1 Maskable- 64bit+
		Address: 00000000fee00518  Data: 0000
	Capabilities: [40] Express (v2) Endpoint, IntMsgNum 0
		DevCap:	MaxPayload 128 bytes, PhantFunc 0, Latency L0s <512ns, L1 unlimited
			ExtTag- AttnBtn- AttnInd- PwrInd- RBE+ FLReset+ SlotPowerLimit 0W TEE-IO-
		DevCtl:	CorrErr- NonFatalErr- FatalErr- UnsupReq-
			RlxdOrd+ ExtTag- PhantFunc- AuxPwr+ NoSnoop+ FLReset-
			MaxPayload 128 bytes, MaxReadReq 128 bytes
		DevSta:	CorrErr- NonFatalErr- FatalErr- UnsupReq- AuxPwr+ TransPend-
		LnkCap:	Port #0, Speed 2.5GT/s, Width x1, ASPM L1, Exit Latency L1 <32us
			ClockPM+ Surprise- LLActRep- BwNot- ASPMOptComp+
		LnkCtl:	ASPM L1 Enabled; RCB 64 bytes, LnkDisable- CommClk+
			ExtSynch- ClockPM+ AutWidDis- BWInt- AutBWInt- FltModeDis-
		LnkSta:	Speed 2.5GT/s, Width x1
			TrErr- Train- SlotClk+ DLActive- BWMgmt- ABWMgmt-
		DevCap2: Completion Timeout: Range B, TimeoutDis+ NROPrPrP- LTR+
			 10BitTagComp- 10BitTagReq- OBFF Via WAKE#, ExtFmt- EETLPPrefix-
			 EmergencyPowerReduction Not Supported, EmergencyPowerReductionInit-
			 FRS- TPHComp- ExtTPHComp-
			 AtomicOpsCap: 32bit- 64bit- 128bitCAS-
		DevCtl2: Completion Timeout: 16ms to 55ms, TimeoutDis-
			 AtomicOpsCtl: ReqEn-
			 IDOReq- IDOCompl- LTR+ EmergencyPowerReductionReq-
			 10BitTagReq- OBFF Disabled, EETLPPrefixBlk-
		LnkCtl2: Target Link Speed: 2.5GT/s, EnterCompliance- SpeedDis-
			 Transmit Margin: Normal Operating Range, EnterModifiedCompliance- ComplianceSOS-
			 Compliance Preset/De-emphasis: -6dB de-emphasis, 0dB preshoot
		LnkSta2: Current De-emphasis Level: -3.5dB, EqualizationComplete- EqualizationPhase1-
			 EqualizationPhase2- EqualizationPhase3- LinkEqualizationRequest-
			 Retimer- 2Retimers- CrosslinkRes: unsupported, FltMode-
	Capabilities: [100 v1] Advanced Error Reporting
		UESta:	DLP- SDES- TLP- FCP- CmpltTO- CmpltAbrt- UnxCmplt- RxOF- MalfTLP-
			ECRC- UnsupReq- ACSViol- UncorrIntErr- BlockedTLP- AtomicOpBlocked- TLPBlockedErr-
			PoisonTLPBlocked- DMWrReqBlocked- IDECheck- MisIDETLP- PCRC_CHECK- TLPXlatBlocked-
		UEMsk:	DLP- SDES- TLP- FCP- CmpltTO- CmpltAbrt- UnxCmplt- RxOF- MalfTLP-
			ECRC- UnsupReq- ACSViol- UncorrIntErr- BlockedTLP- AtomicOpBlocked- TLPBlockedErr-
			PoisonTLPBlocked- DMWrReqBlocked- IDECheck- MisIDETLP- PCRC_CHECK- TLPXlatBlocked-
		UESvrt:	DLP+ SDES+ TLP- FCP+ CmpltTO- CmpltAbrt- UnxCmplt- RxOF+ MalfTLP+
			ECRC- UnsupReq- ACSViol- UncorrIntErr+ BlockedTLP- AtomicOpBlocked- TLPBlockedErr-
			PoisonTLPBlocked- DMWrReqBlocked- IDECheck- MisIDETLP- PCRC_CHECK- TLPXlatBlocked-
		CESta:	RxErr- BadTLP+ BadDLLP- Rollover- Timeout+ AdvNonFatalErr+ CorrIntErr- HeaderOF-
		CEMsk:	RxErr- BadTLP- BadDLLP- Rollover- Timeout- AdvNonFatalErr+ CorrIntErr- HeaderOF-
		AERCap:	First Error Pointer: 00, ECRCGenCap- ECRCGenEn- ECRCChkCap- ECRCChkEn-
			MultHdrRecCap- MultHdrRecEn- TLPPfxPres- HdrLogCap-
		HeaderLog: 00000000 00000000 00000000 00000000
	Capabilities: [140 v1] Device Serial Number b8-81-98-ff-ff-d8-b9-7c
	Capabilities: [14c v1] Latency Tolerance Reporting
		Max snoop latency: 3145728ns
		Max no snoop latency: 3145728ns
	Capabilities: [154 v1] L1 PM Substates
		L1SubCap: PCI-PM_L1.2+ PCI-PM_L1.1+ ASPM_L1.2+ ASPM_L1.1+ L1_PM_Substates+
			  PortCommonModeRestoreTime=30us PortTPowerOnTime=60us
		L1SubCtl1: PCI-PM_L1.2- PCI-PM_L1.1- ASPM_L1.2- ASPM_L1.1-
			   T_CommonMode=0us LTR1.2_Threshold=0ns
		L1SubCtl2: T_PwrOn=10us
	Kernel driver in use: iwlwifi
	Kernel modules: iwlwifi

What’s going on? How can I find out how to fix this?

Due to additional hardening added in NixOS 26.05, wpa_supplicant can’t create that directory itself. If you still want a control socket, you can add networking.wireless.userControlled = true.

nixos.wiki is not the official NixOS wiki, wiki.nixos.org is the official NixOS wiki.

3 Likes

From the NixOS 26.05 release notes:

Similarly, the ctrl_interface directory set in wpa_supplicant ’s conf must be writeable by the wpa_supplicant user so that the wpa_supplicant daemon can start successfully.
If you were changing ctrl_interface in extraConfig or in /etc/wpa_supplicant/imperative.conf , please remove that line.

2 Likes

Thank you! Removing that line was enough. To be explicit, my networking module now defines:

#root/modules/system/networking/default.nix
{
  networking.hostName = "myHostName";
  networking.wireless = {
    enable = true;
    networks."myNetwork".psk = "XXX";
    # --REMOVED--
    #extraConfig = "ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=wheel";
  };
  networking.networkmanager.enable = false;
}

Probably for the best, I had no idea what that was doing.

To use the language that MaxHearnden did in their reply, I don’t think I want a “control socket” right now.

It just allows users of the wheel group (those that can run sudo) to control wpa_supplicant while it’s running. Typically with wpa_cli, you can add a network, do a scan, etc.

1 Like