Turning a Raspberry Pi as a Wi-Fi router is a staple embedded networking project, but if you are following tutorials from 2022 or earlier, your build will fail. Older guides rely on dhcpcd and manual hostapd configurations, both of which are deprecated and disabled by default in Raspberry Pi OS Bookworm (Debian 12). Today, the correct, native method uses NetworkManager (nmcli) for the access point and the nftables backend for NAT routing.
This guide targets the Raspberry Pi 4 Model B (4GB) running Raspberry Pi OS Bookworm (64-bit). We will bridge the Gigabit Ethernet WAN to the onboard dual-band Wi-Fi LAN, complete with DHCP and NAT, giving you a fully functional travel router or isolated IoT network gateway.
Hardware Spec Sheet & Network Interface Mapping
Time to Complete: 45 minutes.
Before writing any configuration files, verify your hardware capabilities. The onboard Wi-Fi chipset dictates your maximum real-world AP throughput. Do not expect Wi-Fi 6 speeds from the Pi 4's onboard radio; if you need higher throughput, you must use a Pi 5 with a USB 3.0 Wi-Fi 6 adapter.
| Board Variant | Wi-Fi Chipset | Bands | Max Real-World AP Throughput | Recommended PSU |
|---|---|---|---|---|
| Raspberry Pi 4 Model B (4GB) | Cypress CYW43455 | 2.4GHz / 5GHz | ~65 Mbps (5GHz, 1m range) | Official 5.1V 3.0A USB-C |
| Raspberry Pi 400 | Cypress CYW43455 | 2.4GHz / 5GHz | ~65 Mbps (5GHz, 1m range) | Official 5.1V 3.0A USB-C |
| Raspberry Pi 5 (8GB) + USB Adapter | Depends on Adapter (e.g., MT7921) | 2.4 / 5 / 6GHz | ~300+ Mbps (Wi-Fi 6, 5GHz) | Official 27W USB-C PD |
Interface & IP Mapping
When configuring the router, you must strictly separate the WAN (internet-facing) and LAN (device-facing) interfaces. Predictable network interface names are enabled by default in Bookworm.
| Role | Interface Name | IP Address | Subnet Mask | DHCP Pool |
|---|---|---|---|---|
| WAN (Uplink) | eth0 (or end0) |
DHCP from upstream | /24 (Typical) | N/A |
| LAN (Hotspot) | wlan0 |
192.168.50.1 | 255.255.255.0 | 192.168.50.10 - .100 |
Parts List & Prerequisites
- Compute: Raspberry Pi 4 Model B (4GB or 8GB variant).
- Storage: 32GB SanDisk Extreme microSD card (A2 rating for high IOPS during DHCP/logging).
- Power: Official Raspberry Pi 27W USB-C Power Supply (prevents brownouts when the Wi-Fi radio spikes during client association).
- OS: Raspberry Pi OS Lite (64-bit) Bookworm release. Do not use the Desktop version; the GUI NetworkManager applet will conflict with our CLI headless setup.
- Connection: Ethernet cable connected to your primary upstream router/modem.
Step-by-Step Build: AP and NAT Routing
Because dhcpcd is disabled in Bookworm, we will use nmcli to create a shared Wi-Fi connection. This single command handles the SSID broadcast, WPA2 security, and spins up an internal dnsmasq instance for DHCP automatically. We then enable IP forwarding and configure NAT.
1. Update System and Install Dependencies
Ensure your system is patched and the iptables package (which routes to the nftables backend in Debian 12) is installed.
sudo apt update && sudo apt upgrade -y
sudo apt install network-manager iptables -y
2. Execute the Router Configuration Script
Save the following bash script as setup_router.sh. This script includes interface definitions, error handling, and persistent sysctl configurations. It targets the Raspberry Pi 4 Model B where the ethernet interface is eth0. Note: If you are on a Pi 5, your ethernet interface might be named end0; update the WAN_IF variable accordingly.
#!/bin/bash
set -e
# --- Interface & Network Definitions ---
WAN_IF="eth0" # Uplink interface (use 'end0' on Pi 5)
LAN_IF="wlan0" # Wi-Fi AP interface
SSID="FluxNet-IoT"
PASSWORD="SuperSecret123!"
LAN_IP="192.168.50.1/24"
# --- Pre-flight Checks ---
if [ "$EUID" -ne 0 ]; then
echo "Error: This script must be run as root (use sudo)."
exit 1
fi
if ! ip link show "$WAN_IF" &> /dev/null; then
echo "Error: WAN interface $WAN_IF not found. Check your ethernet cable or interface name."
exit 1
fi
# --- 1. Configure Wi-Fi Access Point via NetworkManager ---
echo "Configuring Wi-Fi Hotspot on $LAN_IF..."
# Delete existing hotspot connection if it exists to prevent duplicates
nmcli connection delete "FluxHotspot" &> /dev/null || true
nmcli connection add type wifi ifname "$LAN_IF" con-name "FluxHotspot" \
ssid "$SSID" mode ap ipv4.method shared ipv4.addresses "$LAN_IP" \
wifi-sec.key-mgmt wpa-psk wifi-sec.psk "$PASSWORD" \
wifi.band a wifi.channel 36
echo "Activating Hotspot..."
nmcli connection up "FluxHotspot"
# --- 2. Enable IP Forwarding Persistently ---
echo "Enabling IPv4 forwarding..."
sysctl -w net.ipv4.ip_forward=1
if ! grep -q "^net.ipv4.ip_forward=1" /etc/sysctl.conf; then
echo "net.ipv4.ip_forward=1" >> /etc/sysctl.conf
fi
# --- 3. Configure NAT (Masquerade) via iptables/nftables backend ---
echo "Configuring NAT routing..."
# Flush existing rules to prevent duplicate MASQUERADE entries
iptables -t nat -D POSTROUTING -o "$WAN_IF" -j MASQUERADE &> /dev/null || true
iptables -t nat -A POSTROUTING -o "$WAN_IF" -j MASQUERADE
# Save rules for persistence across reboots
apt install iptables-persistent -y || true
netfilter-persistent save || iptables-save > /etc/iptables/rules.v4
echo "Success: Raspberry Pi is now routing traffic from $LAN_IF to $WAN_IF."
3. Verify the Build
Run the script: sudo bash setup_router.sh. Once complete, connect your phone or laptop to the FluxNet-IoT SSID. Open a terminal on your Pi and run nmcli connection show --active to verify both eth0 and FluxHotspot are active.
Debugging: Exact Errors and the "First Three" Checks
When your Raspberry Pi as a Wi-Fi router fails to pass traffic or broadcast an SSID, do not blindly reboot. Perform these three diagnostic checks first:
- Check RF Kill Status: Run
rfkill list. Ifwlan0shows "Soft blocked: yes", runsudo rfkill unblock wifi. NetworkManager will not start an AP on a blocked radio. - Verify Default Gateway: Run
ip route. Ensure your default route points out ofeth0(e.g.,default via 192.168.1.1 dev eth0). If the default route is missing, your Pi has no internet to share. - Confirm IP Forwarding: Run
sysctl net.ipv4.ip_forward. If it returns0, NAT is dead. Re-run the sysctl command from the script.
Common Error Strings & Ranked Causes
| Exact Error String | Ranked Causes & Fixes |
|---|---|
Error: Connection activation failed: (7) Secrets were required, but not provided. |
1. WPA2 password in nmcli was omitted or contained unescaped bash special characters (like !). Wrap the password in single quotes in the script.2. The wifi-sec.key-mgmt flag was missing, defaulting to an open network while a PSK was supplied. |
Warning: Extension MASQUERADE revision 0 not supported, missing kernel module? |
1. The nf_nat kernel module is not loaded. Fix: sudo modprobe nf_nat.2. You are using an outdated iptables binary that doesn't map to the Bookworm nftables backend. Reinstall via sudo apt install --reinstall iptables. |
Error: Device 'wlan0' not compatible with connection 'FluxHotspot'. |
1. You requested a 5GHz channel (e.g., 36) but the regulatory domain is unset, blocking 5GHz. Fix: sudo iw reg set US (or your local ISO code) and reboot.2. Another service (like legacy hostapd) has locked the interface. Fix: sudo systemctl stop hostapd. |
For deeper insights into how Debian 12 handles the transition from legacy iptables to nftables, refer to the Debian NetworkManager Wiki and the Netfilter NAT documentation.
Extending or Simplifying Your Router Build
Depending on your end goal, you may want to add network-wide features or strip away the manual Linux configuration entirely.
How to Extend: Add Network-Wide Ad Blocking
The most common extension for a Pi router is integrating Pi-hole. Because we used NetworkManager's shared mode, the Pi is already acting as the DHCP server for the 192.168.50.x subnet.
- Install Pi-hole:
curl -sSL https://install.pi-hole.net | bash. - During setup, assign Pi-hole to the
wlan0interface. - Pi-hole will automatically hijack the DHCP DNS distribution, forcing all connected Wi-Fi clients to use its filtered DNS resolver without requiring manual
dnsmasqedits.
How to Simplify: Use a Dedicated Router OS
If you find yourself constantly tweaking iptables rules, managing VLANs, or setting up QoS, you are outgrowing Raspberry Pi OS.
- OpenWrt: Flash OpenWrt for Raspberry Pi. It provides a full LuCI web GUI, native firewall zone management, and package management specifically designed for routing. It handles the NAT and AP bridging natively without bash scripts.
- Raspberry Pi Connect: If your goal is simply remote access to the Pi rather than routing traffic for other devices, skip the router build entirely and use the official Raspberry Pi Connect service for secure WireGuard-based remote shell access.
Building a Raspberry Pi as a Wi-Fi router on Bookworm requires abandoning legacy tutorials and embracing NetworkManager. By defining your interfaces clearly and leveraging the nftables backend, you get a stable, low-power routing node that survives reboots and OS updates.






