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.
Bench Tip: If you type 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.

  1. Identify your active connection name:
    Run nmcli con show --active. You are looking for the name under the 'NAME' column, typically Wired connection 1 for Ethernet or preconfigured for Wi-Fi.
  2. Verify the target IP is actually free:
    Never guess. Run ping -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.
  3. 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
  4. Restart the connection to apply changes:
    sudo nmcli con up "Wired connection 1"
  5. Verify the routing table:
    Run ip 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 show to list all profiles. Use the exact string from the 'NAME' column in your nmcli con mod command, 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 eth0 and wlan0), 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 with sudo 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/16 instead 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 via nmcli con mod "Wired connection 1" ipv4.addresses 192.168.1.50/24.
The First 3 Things to Check When It Fails:
  1. 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?
  2. 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.
  3. DNS Resolution: Can you ping 8.8.8.8 but not google.com? Your IP is fine, but NetworkManager failed to write to /etc/resolv.conf. Run resolvectl status to 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.