Difficulty Rating: Intermediate | Time Required: 20 Minutes | Target OS: Raspberry Pi OS Bookworm/Trixie (64-bit)

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.

Decision Tree: How to Configure Raspberry Pi WiFi
Your ScenarioRequired ToolVerdict / Action
Pre-flashing a new SD card (Headless)Raspberry Pi Imager GUIChoose 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 terminalChoose this for remote management. Follow the step-by-step CLI guide below.
Connected to a monitor/keyboard (Desktop)nm-applet GUIClick the network icon in the top right taskbar. Standard desktop WiFi selection.
Enterprise WPA2/WPA3 (EAP-TLS/PEAP)nmcli or nmtuiUse 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.

Spec Sheet: Raspberry Pi WiFi Silicon
Board VariantWiFi ChipsetBandsAntenna Notes & Edge Cases
Raspberry Pi 5 (4GB/8GB)Broadcom BCM43452.4GHz / 5GHzSupports WPA3-SAE. Excellent throughput, but onboard PCB antenna struggles through metal enclosures.
Raspberry Pi 4 Model BBroadcom BCM434552.4GHz / 5GHzKnown to drop 5GHz connections if USB 3.0 ports are heavily utilized without shielded cables (RF interference).
Raspberry Pi Zero 2 WBroadcom BCM434362.4GHz OnlyDo 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.

  1. Verify NetworkManager is running:
    systemctl status NetworkManager
    Look for "active (running)". If it's dead, run sudo systemctl start NetworkManager.
  2. 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-config5 Localisation OptionsL4 WLAN Country → Select your country (e.g., US, GB, DE).
  3. 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.
  4. 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.
  5. Verify the connection and IP assignment:
    nmcli connection show
    ip -4 addr show wlan0
Callout Tip: WPA3-SAE Compatibility
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

ComponentGPIO Pin (BCM)Physical Pin
LED Anode (+)GPIO 17Pin 11
LED Cathode (-)GNDPin 9
Current Limiting Resistor330Ω 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

  1. Is the radio soft-blocked? Run rfkill list. If "Soft blocked: yes" appears under Wireless LAN, run sudo rfkill unblock wifi.
  2. Is the regulatory domain set? Run iw reg get. If it returns "country 00" or "world", 5GHz DFS channels are disabled. Set it via raspi-config.
  3. Is the interface named correctly? Run nmcli device status. If you have a USB WiFi dongle plugged in, the onboard chip might be wlan0 and the dongle wlan1. Adjust your commands accordingly.

Error String Decoder

Exact Error StringRanked CausesThe 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.