If you are running a headless cluster, a Pi-hole DNS server, or an MQTT broker, a shifting DHCP lease will eventually break your network. Knowing how to set static IP in Raspberry Pi environments is a fundamental skill for any embedded developer. However, the method changed drastically with the release of Raspberry Pi OS Bookworm (Debian 12). The legacy dhcpcd daemon is dead; NetworkManager is now the undisputed standard.
This guide gives you the exact 2026 workflow using nmcli, complete with hardware interface mapping, a production-ready bash script, and the exact error strings you will hit when things go wrong.
The Decision Path: NetworkManager vs. Legacy dhcpcd
Before typing a single command, you must match your OS version to the correct networking daemon. Do not mix them, or your Pi will fail to route traffic on reboot.
| OS Version (Debian Base) | Default Network Daemon | Configuration Method | Verdict |
|---|---|---|---|
| Bookworm (Debian 12) & Newer | NetworkManager | nmcli or nmtui |
DEFAULT PICK: Use nmcli. |
| Bullseye (Debian 11) | dhcpcd (NM available) | /etc/dhcpcd.conf |
Upgrade to Bookworm, or use dhcpcd. |
| Buster (Debian 10) & Older | dhcpcd | /etc/dhcpcd.conf |
Legacy. Migrate hardware if possible. |
sudo nano /etc/dhcpcd.conf on a fresh Bookworm install, you will either get an empty file or a deprecation warning. Stop. Close the file. Use nmcli instead. See the official Raspberry Pi configuration documentation for the deprecation timeline.
Hardware & Network Interface Mapping
This guide targets the Raspberry Pi 5 (8GB) and Raspberry Pi 4 Model B (4GB/8GB) running Raspberry Pi OS Bookworm (64-bit). Unlike microcontrollers where you map GPIO pins, setting a static IP requires mapping logical network interfaces to their physical hardware buses to ensure you are configuring the correct adapter.
Parts List
- Board: Raspberry Pi 5 (8GB) or Pi 4 Model B
- Power: Official 27W USB-C PD Power Supply (Pi 5) or 15W USB-C (Pi 4)
- Storage: 32GB MicroSD (A2 rating) or NVMe SSD via PCIe HAT
- Network: Cat6 UTP Ethernet Cable (for Gigabit
eth0)
Interface to Hardware Bus Mapping
| Logical Interface | Hardware Controller | Physical Bus | Connector / Antenna |
|---|---|---|---|
eth0 |
RP1 PCIe MAC (Pi 5) / BCM54210PE (Pi 4) | PCIe (Pi 5) / RGMII (Pi 4) | RJ45 Jack |
wlan0 |
Infineon CYW43455 (Wi-Fi 5) | SDIO | Onboard PCB Trace Antenna |
Step-by-Step: How to Set Static IP via nmcli
NetworkManager uses the concept of 'connections' rather than just interfaces. A connection is a profile that can be applied to an interface. Here is the exact sequence to lock down your wired Ethernet.
- Identify your active connection name:
Runnmcli con show --active. You are looking for the name under the 'NAME' column, typicallyWired connection 1for Ethernet orpreconfiguredfor Wi-Fi. - Verify the target IP is actually free:
Never guess. Runping -c 3 192.168.1.50(replace with your target). If it replies, pick a different IP. If it times out, it is safe to claim. - Apply the static IPv4 configuration:
sudo nmcli con mod "Wired connection 1" ipv4.addresses 192.168.1.50/24 ipv4.gateway 192.168.1.1 ipv4.dns "1.1.1.1 8.8.8.8" ipv4.method manual - Restart the connection to apply changes:
sudo nmcli con up "Wired connection 1" - Verify the routing table:
Runip route. Ensure your default gateway points to your router's IP.
Automated Bash Script with Error Handling
When provisioning a fleet of Pi nodes via SSH, doing this manually is prone to typos. Below is a complete, compilable Bash script that applies the static IP, checks for execution errors, and validates network reachability. Save this as set_static_ip.sh.
#!/bin/bash
# Target: Raspberry Pi OS Bookworm (NetworkManager)
# Usage: sudo ./set_static_ip.sh eth0 192.168.1.50 192.168.1.1
set -e
IFACE=$1
TARGET_IP=$2
GATEWAY=$3
CON_NAME=$(nmcli -g GENERAL.CONNECTION device show "$IFACE" | head -n 1)
if [ -z "$CON_NAME" ]; then
echo "ERROR: No active NetworkManager connection found for interface $IFACE."
exit 1
fi
echo "Modifying connection profile: $CON_NAME"
# Apply static IP settings
if ! nmcli con mod "$CON_NAME" \
ipv4.addresses "$TARGET_IP/24" \
ipv4.gateway "$GATEWAY" \
ipv4.dns "1.1.1.1 9.9.9.9" \
ipv4.method manual; then
echo "FATAL: nmcli modification failed. Check syntax and permissions."
exit 2
fi
# Restart connection
echo "Bringing up $CON_NAME..."
if ! nmcli con up "$CON_NAME"; then
echo "ERROR: Failed to bring up connection. Reverting to DHCP."
nmcli con mod "$CON_NAME" ipv4.method auto
nmcli con up "$CON_NAME"
exit 3
fi
# Validate Gateway Reachability
sleep 2
if ping -c 2 -W 2 "$GATEWAY" > /dev/null; then
echo "SUCCESS: Static IP $TARGET_IP applied and gateway $GATEWAY is reachable."
else
echo "WARNING: IP applied, but gateway $GATEWAY is unreachable. Check subnet mask."
fi
Troubleshooting: Exact Error Strings and Fixes
When network configuration fails, Linux throws specific kernel or daemon errors. Here are the top three errors you will encounter, ranked by frequency, with their exact fixes.
1. "Error: Unknown connection 'Wired connection 1'."
- Cause: You are using a default string that doesn't match the actual profile name stored in NetworkManager. This happens often if the Pi was initially set up via the Raspberry Pi Imager with custom Wi-Fi settings, which alters default naming.
- Fix: Run
nmcli con showto list all profiles. Use the exact string from the 'NAME' column in yournmcli con modcommand, wrapped in quotes.
2. "RTNETLINK answers: File exists"
- Cause: You are trying to assign an IP address that is already bound to another interface on the same Pi (e.g., you accidentally assigned the same static IP to both
eth0andwlan0), or the kernel routing table already has a conflicting subnet route. - Fix: Flush the IP from the offending interface using
sudo ip addr flush dev wlan0, then restart the NetworkManager service withsudo systemctl restart NetworkManager.
3. "Network is unreachable" (When pinging external hosts)
- Cause: Your subnet mask (CIDR notation) is wrong, or the gateway IP you specified does not exist on the local broadcast domain. If you type
192.168.1.50/16instead of/24, the Pi will think the entire 192.168.x.x range is local and won't send traffic to the gateway. - Fix: Verify your CIDR. For 99% of home and lab networks, the suffix is
/24(255.255.255.0). Correct it vianmcli con mod "Wired connection 1" ipv4.addresses 192.168.1.50/24.
- IP Conflict: Did you ping the target IP from another machine before assigning it to ensure the DHCP server hadn't already leased it to a phone or laptop?
- Gateway Ping: Can the Pi ping its own gateway (
ping 192.168.1.1)? If not, your physical layer (cable/switch) or VLAN tagging is wrong. - DNS Resolution: Can you ping
8.8.8.8but notgoogle.com? Your IP is fine, but NetworkManager failed to write to/etc/resolv.conf. Runresolvectl statusto check DNS bindings.
Extending and Simplifying Your Network Build
Once your base static IP is locked in, you will inevitably need to adapt the network for specific embedded use cases. Here is how to scale the configuration up or down.
How to Extend: VLAN Tagging for IoT Isolation
If you are running home automation (Home Assistant) or MQTT brokers, you should isolate them on a separate VLAN. NetworkManager handles this natively without touching /etc/network/interfaces.
Command: sudo nmcli con add type vlan con-name IoT-VLAN ifname eth0.20 dev eth0 id 20 ipv4.addresses 10.0.20.5/24 ipv4.gateway 10.0.20.1 ipv4.method manual
This creates a virtual interface eth0.20 tagged for VLAN 20, keeping your Pi's IoT traffic segregated from your main LAN.
How to Simplify: The nmtui Terminal UI
If you are SSH'd in from a tablet or just hate memorizing nmcli flag syntax, use the built-in Terminal User Interface.
Command: sudo nmtui
This launches a blue-screen, arrow-key-driven menu. You can navigate to 'Edit a connection', select your interface, and type the static IP, gateway, and DNS into simple text fields. It writes the exact same underlying configuration files as the CLI, but with zero syntax errors. For more on NetworkManager's architecture, refer to the Debian NetworkManager Wiki or the official nmcli man pages.
By standardizing on nmcli and respecting the hardware bus mappings of the Pi 4 and Pi 5, you eliminate the 'phantom offline' issues that plague legacy dhcpcd configurations. Lock your IP, verify your routes, and your embedded projects will stay online through every router reboot.






