If you are trying to raspberry pi configure static ip addresses on modern hardware, stop looking for /etc/dhcpcd.conf. That file is dead. With the release of Raspberry Pi OS "Bookworm" (and continuing into 2026), the underlying network stack shifted entirely from dhcpcd to NetworkManager. Editing legacy config files will silently fail or break your routing table.

The direct answer: To set a static IP on a headless Raspberry Pi 5 or Pi 4 running Bookworm, you must use the nmcli command-line tool to modify the active connection profile, assigning the IPv4 address in CIDR notation (e.g., 192.168.1.50/24), setting the gateway, and pushing DNS servers, followed by a connection reload.

This guide targets the Raspberry Pi 5 (8GB) and Raspberry Pi 4 Model B (4GB/8GB) running 64-bit Raspberry Pi OS Bookworm. We will cover the exact nmcli syntax, provide a fleet-deployment bash script with error handling, and debug the specific NetworkManager errors that trap most makers migrating from older OS versions.

The Bookworm Shift: Why Old Tutorials Fail

For nearly a decade, the Raspberry Pi community relied on dhcpcd to handle DHCP leases and static IP assignments. However, dhcpcd struggled with modern enterprise WiFi security (WPA3), complex routing, and seamless integration with systemd. The Raspberry Pi Foundation adopted NetworkManager as the default in Bookworm to align with standard Linux desktop and server distributions.

When you attempt to use legacy methods on Bookworm, the dhcpcd daemon simply isn't running. Your changes to /etc/dhcpcd.conf are ignored, and your Pi will continue pulling a dynamic IP from your router's DHCP server, causing your SSH sessions to drop when the lease expires.

⚠️ Safety & Data Caveat: Changing network configurations on a headless Pi via SSH is risky. If you mistype the subnet mask or gateway, you will lock yourself out of the device. Always have a physical monitor and keyboard attached, or use a serial console (UART) connection as a fallback when modifying primary network interfaces.

Hardware & Network Interface Spec Sheet

Before assigning IPs, you need to know your physical interface limits and logical naming conventions. NetworkManager names connections based on the profile, not just the hardware interface. Below is the hardware spec sheet and the physical PoE pin mapping for headless rack deployments.

Board Variant Ethernet Controller Max Throughput Default Interface nmcli Device Type
Raspberry Pi 5 (8GB) Broadcom BCM54210PE 1000 Mbps (Gigabit) eth0 ethernet
Raspberry Pi 4 Model B Broadcom BCM54210PE 1000 Mbps (Gigabit) eth0 ethernet
Raspberry Pi 3B+ LAN7515 (USB 2.0) 300 Mbps (Bottlenecked) eth0 ethernet
Pi Zero 2 W (via USB) ASIX AX88179 1000 Mbps (USB 2.0 limit) eth0 / enx... ethernet

PoE HAT+ Pin Mapping for Headless Nodes

If you are deploying headless Pi 5 nodes in a network rack using Power over Ethernet, you must ensure the physical pin mapping on the 40-pin GPIO header aligns with the PoE HAT+ to prevent 5V rail shorts.

HAT Function GPIO Pin Number Signal Wire Color (Standard)
Main Power In 1 Pin 2 5V Red
Main Power In 2 Pin 4 5V Red
Ground Return 1 Pin 6 GND Black
Ground Return 2 Pin 9 GND Black
I2C SDA (Fan Ctrl) Pin 3 (GPIO 2) SDA1 Yellow

Step-by-Step: Headless Static IP Configuration

To configure the static IP via SSH, we use nmcli. The most common mistake beginners make is using the hardware interface name (eth0) instead of the NetworkManager connection profile name (usually Wired connection 1).

  1. Identify the Connection Name:
    Run nmcli connection show. Look under the "NAME" column. You will typically see Wired connection 1. Note this exact string.
  2. Set the Static IP and Gateway:
    Use CIDR notation for the subnet mask. Do not use 255.255.255.0.
    sudo nmcli con mod "Wired connection 1" ipv4.addresses 192.168.1.50/24
    sudo nmcli con mod "Wired connection 1" ipv4.gateway 192.168.1.1
  3. Set the DNS Servers:
    sudo nmcli con mod "Wired connection 1" ipv4.dns "1.1.1.1 8.8.8.8"
  4. Force Manual IP Assignment:
    Tell NetworkManager to stop asking for a DHCP lease.
    sudo nmcli con mod "Wired connection 1" ipv4.method manual
  5. Apply and Restart the Connection:
    sudo nmcli con up "Wired connection 1"
    Note: If you are on SSH, your session will drop immediately after this command. Reconnect using your new static IP.

Automated Bash Script for Fleet Deployment

If you are flashing multiple SD cards for a sensor network or cluster, doing this manually is tedious. Below is a complete, compilable bash script designed for Raspberry Pi OS Bookworm. It includes interface definitions, error handling, and a rollback mechanism if the gateway is unreachable.

#!/bin/bash
# =====================================================================
# Target: Raspberry Pi 5 (8GB) / Pi 4 (4GB) - Raspberry Pi OS Bookworm
# Purpose: Configure Static IP via NetworkManager (nmcli)
# Interface: eth0 (Profile Name: "Wired connection 1")
# =====================================================================

set -euo pipefail

# --- Interface & Network Definitions ---
CONN_NAME="Wired connection 1"
STATIC_IP="192.168.1.50/24"
GATEWAY="192.168.1.1"
DNS_SERVERS="1.1.1.1,8.8.8.8"

# --- Pre-flight Checks ---
if ! command -v nmcli &> /dev/null; then
    echo "[ERROR] nmcli not found. Are you running Bookworm or a distro without NetworkManager?"
    exit 1
fi

# Verify the connection profile exists
if ! nmcli con show | grep -q "$CONN_NAME"; then
    echo "[ERROR] Connection profile '$CONN_NAME' not found."
    echo "[INFO] Available profiles:"
    nmcli con show --active
    exit 1
fi

echo "[INFO] Backing up current DHCP configuration..."
OLD_METHOD=$(nmcli -g ipv4.method con show "$CONN_NAME")

echo "[INFO] Applying static IP configuration to '$CONN_NAME'..."
sudo nmcli con mod "$CONN_NAME" \
    ipv4.addresses "$STATIC_IP" \
    ipv4.gateway "$GATEWAY" \
    ipv4.dns "$DNS_SERVERS" \
    ipv4.method manual

echo "[INFO] Restarting connection to apply changes..."
sudo nmcli con up "$CONN_NAME"

# --- Verification & Rollback ---
sleep 3
echo "[INFO] Verifying gateway reachability..."
if ping -c 2 -W 2 "$GATEWAY" &> /dev/null; then
    echo "[SUCCESS] Static IP $STATIC_IP configured and gateway reachable."
else
    echo "[WARNING] Gateway $GATEWAY unreachable. Rolling back to DHCP..."
    sudo nmcli con mod "$CONN_NAME" ipv4.method auto
    sudo nmcli con mod "$CONN_NAME" -ipv4.addresses
    sudo nmcli con mod "$CONN_NAME" -ipv4.gateway
    sudo nmcli con up "$CONN_NAME"
    echo "[ERROR] Rollback complete. Check physical cabling and subnet math."
    exit 1
fi

Troubleshooting: Exact Errors and Ranked Fixes

NetworkManager is strict about syntax. When things fail, it throws specific errors. If your static IP assignment fails, the first three things to check are:

  1. The exact connection name: Run nmcli con show. If you typed eth0 instead of Wired connection 1, it will fail.
  2. The CIDR subnet mask: Ensure you used /24 and not 255.255.255.0. NetworkManager rejects dotted-decimal masks in the ipv4.addresses field.
  3. IP Conflicts: Ensure the static IP you chose isn't inside your router's active DHCP pool, or another device will fight the Pi for the MAC address.
Exact Error String Ranked Cause The Fix
Error: unknown connection 'eth0'. 1. Used hardware interface name instead of profile name. Use nmcli con show and replace eth0 with Wired connection 1.
Error: failed to set 'ipv4.addresses': '192.168.1.50 255.255.255.0' is not valid. 1. Used dotted-decimal subnet mask instead of CIDR. Change to 192.168.1.50/24.
RTNETLINK answers: File exists 1. IP address is already assigned to another active interface or alias. Run ip addr show, find the duplicate, and sudo ip addr del [IP]/24 dev [iface].
Warning: IPv4 address already in use (ARP probe failure) 1. Another device on the LAN holds this IP. Ping the target IP before assigning. Choose an IP outside the router's DHCP range.

Extending the Build: VLANs and Fallback DHCP

Once you have mastered the basic static IP assignment, you can extend your network architecture for more complex embedded deployments.

Adding 802.1Q VLAN Tagging

If your Pi 5 is acting as a network sensor or a router-on-a-stick, you can create virtual interfaces tied to specific VLANs using nmcli. This isolates your IoT traffic from your main LAN.

# Create a VLAN interface on eth0 for VLAN ID 20
sudo nmcli con add type vlan con-name "IoT-VLAN20" ifname "eth0.20" dev "eth0" id 20

# Assign a static IP to the VLAN interface
sudo nmcli con mod "IoT-VLAN20" ipv4.addresses 10.0.20.5/24 ipv4.method manual
sudo nmcli con up "IoT-VLAN20"

Simplifying with nmtui

If you prefer a visual interface but are stuck on a headless SSH session without a desktop environment, use nmtui (NetworkManager Text User Interface). Running sudo nmtui opens a pseudo-graphical menu in your terminal where you can arrow-key your way through editing IPv4 settings, selecting "Manual", and inputting your CIDR addresses. It handles the underlying nmcli syntax generation for you, reducing the chance of typos.

For further reading on advanced NetworkManager configurations, refer to the official nmcli documentation hosted by freedesktop.org.