If you are trying to config wifi raspberry pi boards running the modern Bookworm OS (or later), stop looking for /etc/wpa_supplicant/wpa_supplicant.conf. That legacy file is ignored. Raspberry Pi OS has transitioned entirely to NetworkManager and nmcli for wireless configuration. This guide gives you the exact terminal commands, a hardware-backed Python monitoring script, and the specific debugging steps to fix the exact error strings NetworkManager throws when connections fail.
gpiozero with the lgpio backend, which is natively supported on Pi 5.
Parts List & Hardware Pin Mapping
To make WiFi debugging physical, we are building a status indicator with a hardware fallback trigger. If the Pi drops off the network, the LED turns red. Pressing the button forces a connection to a mobile hotspot fallback.
| Component | Specification / Variant | GPIO Pin (BCM) | Physical Pin |
|---|---|---|---|
| Raspberry Pi | Pi 5 (8GB) or Pi 4 Model B | N/A | N/A |
| RGB LED (Common Cathode) | 5mm standard, 20mA | 17 (R), 27 (G), 22 (B) | 11, 13, 15 |
| Current Limiting Resistors | 3x 220Ω or 330Ω (1/4W) | In-line with R, G, B | N/A |
| Tactile Pushbutton | 6x6mm SPST Normally Open | 5 (Input) | 29 |
| Power & Ground | N/A | 3.3V (Pwr), GND | 1 (3.3V), 6 (GND) |
The Modern CLI Method: nmcli Step-by-Step
NetworkManager replaces both wpa_supplicant and dhcpcd. Here is the exact sequence to scan, connect, and verify your wireless connection from the terminal.
- Check the Radio State: Before scanning, ensure the WiFi radio isn't soft-blocked by regulatory domain rules.
nmcli radio wifi
If it returns 'disabled', enable it with:nmcli radio wifi on - Scan for Networks: List available SSIDs with signal strength.
nmcli device wifi list - Connect to the SSID: Pass your credentials directly. NetworkManager will automatically save this as a persistent profile.
sudo nmcli device wifi connect "Your_SSID_Name" password "Your_Secure_Password" - Verify the Connection Profile: Confirm the profile is set to auto-connect on boot.
nmcli connection show
Look for your SSID in the 'NAME' column and ensure 'AUTOCONNECT' is set to 'yes'.
If
nmcli device wifi list returns nothing, or connections instantly drop, your regulatory domain is likely unset. The Pi disables WiFi transmission until a country code is defined. Run sudo raspi-config, navigate to Localisation Options > WLAN Country, select your region, and reboot.
Python WiFi Monitor & Fallback Script
This script monitors the NetworkManager state. If the primary WiFi drops, it illuminates the red LED and attempts a reconnection. If you press the physical button on GPIO 5, it forces a connection to a fallback mobile hotspot. This is highly useful for headless Pi deployments in the field.
import subprocess
import time
from gpiozero import RGBLED, Button
from signal import pause
# --- Pin Definitions (BCM Numbering) ---
RED_PIN = 17
GREEN_PIN = 27
BLUE_PIN = 22
BUTTON_PIN = 5
# Initialize Hardware
led = RGBLED(red=RED_PIN, green=GREEN_PIN, blue=BLUE_PIN)
btn = Button(BUTTON_PIN, pull_up=True, bounce_time=0.1)
# --- Network Configuration ---
PRIMARY_SSID = "HomeNetwork_5G"
FALLBACK_SSID = "FieldMobileHotspot"
WIFI_PASS = "YourSecurePasswordHere"
def check_wifi_status():
"""Queries NetworkManager for active connection state."""
try:
result = subprocess.run(
["nmcli", "-t", "-f", "STATE", "general", "status"],
capture_output=True, text=True, check=True
)
return "connected" in result.stdout.lower()
except subprocess.CalledProcessError:
return False
def attempt_connect(ssid):
"""Attempts to connect to a specific SSID using nmcli."""
led.color = (1, 0.5, 0) # Orange indicates 'connecting'
try:
subprocess.run(
["sudo", "nmcli", "device", "wifi", "connect", ssid, "password", WIFI_PASS],
check=True, capture_output=True, text=True
)
return True
except subprocess.CalledProcessError as e:
print(f"Connection failed for {ssid}: {e.stderr.strip()}")
return False
def fallback_trigger():
"""Hardware button callback to force fallback network."""
print("Button pressed! Attempting fallback connection...")
if not attempt_connect(FALLBACK_SSID):
led.color = (1, 0, 0) # Solid red on failure
# Bind button press event
btn.when_pressed = fallback_trigger
# --- Main Monitoring Loop ---
try:
print("Starting WiFi Monitor... Press Ctrl+C to exit.")
while True:
if check_wifi_status():
led.color = (0, 1, 0) # Green = Connected
else:
led.color = (1, 0, 0) # Red = Disconnected
print("Network dropped. Attempting primary reconnect...")
attempt_connect(PRIMARY_SSID)
time.sleep(5) # Poll every 5 seconds to avoid CPU spam
except KeyboardInterrupt:
print("\nMonitor stopped.")
led.off()
How to extend or simplify this build: To simplify, remove the button and fallback SSID logic, leaving only the LED status loop. To extend, integrate the official NetworkManager D-Bus API to listen for asynchronous state change signals rather than polling every 5 seconds, which reduces CPU wakeups on battery-powered Pi projects.
Debugging: Exact Error Strings & Ranked Causes
When configuring WiFi via CLI or Python, NetworkManager will halt and throw specific errors. Here is how to decode them.
Error 1: "Error: Connection activation failed: (7) Secrets were required, but not provided."
What it means: NetworkManager found the SSID, but the PSK (password) is missing, incorrect, or the encryption type (WPA2 vs WPA3) mismatches the saved profile.
- Cause 1 (Most Likely): Typo in the password string, or passing the password without quotes in bash, causing special characters (like
$or&) to be evaluated as variables. - Cause 2: You are trying to connect to a WPA3-Enterprise network using a standard WPA2-Personal command. You must configure 802.1x certificates via
nmtuiinstead. - Fix: Delete the corrupted profile and re-enter with strict quoting:
nmcli connection delete "SSID"followed by the connect command using single quotes for the password.
Error 2: "Error: No suitable device found for this connection" or "Error: Device wlan0 not found"
What it means: The software stack cannot see the physical WiFi chip.
- Cause 1 (Most Likely): The
wlan0interface is soft-blocked byrfkill. - Cause 2: The
brcmfmacfirmware crashed or failed to load during boot (common if the power supply is marginal and the Pi 5 brownouts the PCIe/WiFi bus). - Cause 3: NetworkManager service is masked or conflicting with legacy
dhcpcdservices left over from an OS upgrade.
- RF Kill Status: Run
rfkill list. If 'Soft blocked' says 'yes', runsudo rfkill unblock wifi. - Service State: Run
systemctl status NetworkManager. Ensure it is 'active (running)'. If you see 'dhcpcd.service' running alongside it, disable the legacy service:sudo systemctl disable dhcpcd. - Power Supply Integrity: Check
dmesg | grep -i voltage. If you see 'Under-voltage detected', the WiFi chip is the first peripheral to drop offline. Upgrade to the official 27W USB-C PD power supply.
Frequently Asked Questions
How to config wifi raspberry pi headless without a monitor?
For Bookworm OS, the legacy method of dropping a wpa_supplicant.conf file into the boot partition no longer works. Instead, use the Raspberry Pi Imager on your desktop PC. Click the "Gear" icon (Advanced Options) before flashing the SD card. Here, you can input your SSID, password, and set the WLAN country code. The Imager securely injects these credentials into the NetworkManager configuration during the first boot sequence. Alternatively, if you are using a USB-to-TTL serial console cable, plug it into GPIO 14 (TX) and 15 (RX), connect via PuTTY at 115200 baud, and use the nmcli commands detailed above.
Why is my raspberry pi wifi disconnecting randomly on Bookworm?
Random disconnects on the Pi 4 and Pi 5 are almost always tied to power management or USB 3.0 interference. First, the Pi's WiFi chip attempts to enter power-save mode, which causes latency spikes and drops on some routers. You can disable WiFi power management via NetworkManager by creating a configuration file:
sudo nano /etc/NetworkManager/conf.d/default-wifi-powersave-on.conf
Change the value from 3 (enabled) to 2 (disabled). Save and reboot. Second, if you have a USB 3.0 SSD plugged into the Pi, unshielded USB 3.0 data lines emit RF noise exactly in the 2.4GHz spectrum. Move your Pi to a 5GHz network, or use a shielded USB extension cable to move the SSD away from the Pi's antenna.
How to switch between WiFi networks using Python on Raspberry Pi?
As demonstrated in the script above, you use Python's built-in subprocess module to call nmcli. Because NetworkManager handles the underlying DHCP requests and WPA handshakes, you do not need third-party networking libraries. Simply wrap the command ["nmcli", "device", "wifi", "connect", "SSID", "password", "PASS"] in subprocess.run() with capture_output=True. Always wrap this in a try/except subprocess.CalledProcessError block, as nmcli will return a non-zero exit code if the AP is out of range, allowing your Python script to gracefully trigger a fallback routine rather than crashing the entire application.






