If you are trying to configure Raspberry Pi WiFi by editing /etc/wpa_supplicant/wpa_supplicant.conf, stop immediately. That tutorial is from 2021. With the shift to Raspberry Pi OS Bookworm (and the newer Trixie releases), the underlying network stack was completely overhauled. wpa_supplicant and dhcpcd have been deprecated and replaced by NetworkManager.
The fastest, most reliable way to configure Raspberry Pi WiFi on modern OS versions is via the nmcli (NetworkManager Command Line Interface) tool for headless setups, or the Raspberry Pi Imager's OS customization menu for pre-provisioning. Below is the definitive guide to getting your Pi 5, Pi 4, or Zero 2 W online, complete with a Python watchdog script to keep it there.
The 2026 Reality: NetworkManager Replaced wpa_supplicant
Before touching the terminal, you need to choose your configuration path based on your physical access to the board. NetworkManager handles WiFi profiles as discrete connection files stored in /etc/NetworkManager/system-connections/, requiring root permissions to modify.
| Your Scenario | Required Tool | Verdict / Action |
|---|---|---|
| Pre-flashing a new SD card (Headless) | Raspberry Pi Imager GUI | Choose this for initial setup. Use the OS Customization menu (gear icon) to inject WiFi credentials before the first boot. |
| Already booted, SSH access only (Headless) | nmcli via terminal | Choose this for remote management. Follow the step-by-step CLI guide below. |
| Connected to a monitor/keyboard (Desktop) | nm-applet GUI | Click the network icon in the top right taskbar. Standard desktop WiFi selection. |
| Enterprise WPA2/WPA3 (EAP-TLS/PEAP) | nmcli or nmtui | Use nmtui (text UI) for complex certificate-based enterprise networks. |
Parts List & Board Variant Compatibility
The code and commands in this guide target the Raspberry Pi 5 (8GB variant) running Raspberry Pi OS Bookworm (64-bit). However, the NetworkManager implementation is identical across the Pi 4 Model B and Pi Zero 2 W. Note the hardware differences in the WiFi silicon, which directly affect 5GHz connectivity.
| Board Variant | WiFi Chipset | Bands | Antenna Notes & Edge Cases |
|---|---|---|---|
| Raspberry Pi 5 (4GB/8GB) | Broadcom BCM4345 | 2.4GHz / 5GHz | Supports WPA3-SAE. Excellent throughput, but onboard PCB antenna struggles through metal enclosures. |
| Raspberry Pi 4 Model B | Broadcom BCM43455 | 2.4GHz / 5GHz | Known to drop 5GHz connections if USB 3.0 ports are heavily utilized without shielded cables (RF interference). |
| Raspberry Pi Zero 2 W | Broadcom BCM43436 | 2.4GHz Only | Do not attempt 5GHz config. Chipset physically lacks 5GHz RF front-end. |
For authoritative details on the Bookworm networking stack transition, refer to the official Raspberry Pi NetworkManager documentation.
Step-by-Step: Headless WiFi Configuration via nmcli
If you are SSH'd into your Pi over Ethernet (or using a serial console) and need to connect it to WiFi, follow these exact steps. We will use nmcli, the command-line frontend for NetworkManager.
- Verify NetworkManager is running:
systemctl status NetworkManager
Look for "active (running)". If it's dead, runsudo systemctl start NetworkManager. - Set the Regulatory Domain (Crucial for 5GHz):
The Pi will refuse to scan 5GHz DFS (Dynamic Frequency Selection) channels until a country code is set. If your router is on a high 5GHz channel, it will appear invisible until you do this.
sudo raspi-config→ 5 Localisation Options → L4 WLAN Country → Select your country (e.g., US, GB, DE). - Scan for available networks:
sudo nmcli device wifi rescan
sudo nmcli device wifi list
Identify your SSID and note the IN-USE, BARS, and SECURITY columns. - Connect to the WiFi network:
sudo nmcli device wifi connect "Your_SSID" password "Your_Password"
Replace the strings with your actual credentials. Keep the quotes to handle spaces in SSIDs. - Verify the connection and IP assignment:
nmcli connection show
ip -4 addr show wlan0
If your router forces WPA3 and the connection fails, you may need to explicitly tell NetworkManager to use SAE (Simultaneous Authentication of Equals). Run:
sudo nmcli connection modify "Your_SSID" wifi-sec.pmf required wifi-sec.key-mgmt sae
Python Network Watchdog: Code & GPIO Pin Mapping
Headless Pis in remote locations (like garden sensors or attic gateways) occasionally drop WiFi due to router DHCP lease expirations or RF noise. Below is a complete, compilable Python script that monitors the WiFi state via nmcli and toggles a physical status LED. If the connection drops, it attempts a clean NetworkManager restart.
Target Board: Raspberry Pi 5 (8GB)
Library: gpiozero (Pre-installed on Bookworm; do not use the deprecated RPi.GPIO).
GPIO Pin Mapping Table
| Component | GPIO Pin (BCM) | Physical Pin |
|---|---|---|
| LED Anode (+) | GPIO 17 | Pin 11 |
| LED Cathode (-) | GND | Pin 9 |
| Current Limiting Resistor | 330Ω in series with Anode | |
Complete Python Watchdog Script
import subprocess
import time
import sys
from gpiozero import LED
# --- Pin Definitions ---
WIFI_STATUS_LED = LED(17)
SSID_TARGET = 'Your_SSID'
def check_wifi_connection():
"""Checks if wlan0 is connected to the target SSID using nmcli."""
try:
# Get the active SSID on wlan0
result = subprocess.run(
['nmcli', '-g', 'GENERAL.CONNECTION', 'device', 'show', 'wlan0'],
capture_output=True, text=True, check=True
)
active_ssid = result.stdout.strip()
return active_ssid == SSID_TARGET
except subprocess.CalledProcessError:
# wlan0 might be down or disconnected
return False
except FileNotFoundError:
print('Error: nmcli not found. Is NetworkManager installed?')
sys.exit(1)
def restart_network_manager():
"""Restarts the NetworkManager service to force a reconnection."""
print('Connection lost. Restarting NetworkManager...')
WIFI_STATUS_LED.blink(0.2, 0.2) # Fast blink during reset
try:
subprocess.run(['sudo', 'systemctl', 'restart', 'NetworkManager'], check=True)
time.sleep(10) # Allow time for DHCP handshake
except subprocess.CalledProcessError as e:
print(f'Failed to restart NetworkManager: {e}')
if __name__ == '__main__':
print(f'Starting WiFi Watchdog for SSID: {SSID_TARGET}')
while True:
if check_wifi_connection():
WIFI_STATUS_LED.on() # Solid ON = Connected
time.sleep(30) # Check every 30 seconds
else:
WIFI_STATUS_LED.off() # OFF = Disconnected
print('WiFi disconnected detected.')
restart_network_manager()
time.sleep(60) # Wait 60s before next check after reset
For deeper integration with NetworkManager's D-Bus API instead of polling via subprocess, consult the NetworkManager nmcli reference.
Troubleshooting: Exact Error Strings & Ranked Causes
When configuring WiFi via CLI, NetworkManager is highly specific about its error outputs. Here is how to decode the exact error strings you will encounter.
First 3 Things to Check When WiFi Fails
- Is the radio soft-blocked? Run
rfkill list. If "Soft blocked: yes" appears under Wireless LAN, runsudo rfkill unblock wifi. - Is the regulatory domain set? Run
iw reg get. If it returns "country 00" or "world", 5GHz DFS channels are disabled. Set it viaraspi-config. - Is the interface named correctly? Run
nmcli device status. If you have a USB WiFi dongle plugged in, the onboard chip might bewlan0and the donglewlan1. Adjust your commands accordingly.
Error String Decoder
| Exact Error String | Ranked Causes | The Fix |
|---|---|---|
Error: Connection activation failed: (7) Secrets were required, but not provided. |
1. Incorrect WiFi password. 2. WPA3-SAE mismatch on a WPA2/WPA3 transitional router. |
Double-check the password. If using WPA3, force SAE authentication via the wifi-sec.key-mgmt sae flag shown in the Callout Tip above. |
Error: No network with SSID 'MyNetwork' found. |
1. 5GHz DFS channel hidden by missing country code. 2. Router is broadcasting a hidden SSID. 3. Pi is out of physical range. |
Set the WLAN country. For hidden SSIDs, append hidden yes to your nmcli connection add command. |
Warning: Wi-Fi is blocked by rfkill. |
1. Software block applied by OS. 2. Hardware switch (rare on Pi, common on laptops). |
Execute sudo rfkill unblock wifi and verify with rfkill list. |
Error: Device 'wlan0' not found. |
1. USB WiFi dongle shifted interface naming. 2. Kernel module for WiFi chip failed to load. |
Run ip link show to find the actual interface name (e.g., wlan1). If missing entirely, check dmesg | grep brcmfmac for firmware crashes. |
Extending and Simplifying the Build
How to Simplify:
If you are deploying a fleet of Pis and want to avoid SSH setup entirely, use the Raspberry Pi Imager on your desktop PC. Before clicking "Write", click the gear icon (OS Customization). You can inject the WiFi SSID, password, and country code directly into the image. The Pi will apply these to NetworkManager on the very first boot, completely bypassing the need for Ethernet or nmcli configuration.
How to Extend:
If your Pi is housed in a metal enclosure (like the official Pi 5 metal case or a waterproof outdoor junction box), the onboard PCB antenna will suffer severe signal attenuation. Extend the build by purchasing a USB WiFi adapter with an external RP-SMA antenna connector (e.g., the Panda Wireless PAU09). When you plug it in, NetworkManager will automatically detect it. You can then prioritize the USB adapter over the onboard chip by setting a lower route metric:
sudo nmcli connection modify "Your_SSID" ipv4.route-metric 50
Final Recommendation: Do not waste time trying to resurrect wpa_supplicant on modern Raspberry Pi OS. For initial headless deployment, use the Raspberry Pi Imager's OS Customization tool. For runtime management, remote debugging, and automated watchdog scripts, use nmcli. It is the native, supported standard for 2026 and beyond.






