If you are searching for how to set static IP for Raspberry Pi, the first thing you need to know is that the old tutorials are wrong for modern systems. If you are running Raspberry Pi OS "Bookworm" (Debian 12-based, the standard from late 2023 through 2026), the legacy dhcpcd.conf method is deprecated. Editing that file will do absolutely nothing. Bookworm uses NetworkManager by default, meaning you must use the nmcli command-line tool or the nmtui text interface to assign static addresses.

This guide gives you the exact, bench-tested procedure for locking down a static IP on a headless Raspberry Pi 5 or 4, complete with the automated bash script I use for fleet deployments, and the exact error strings you will hit if your subnet math is off.

1. Hardware & Network Planning Matrix

Before touching the terminal, you need a concrete IP plan. Guessing your gateway or subnet mask is the fastest way to lock yourself out of a headless Pi. Below is the reference matrix for a standard Class C home/lab network.

Target Board & Parts List

  • Board: Raspberry Pi 5 (8GB) or Raspberry Pi 4 Model B (4GB/8GB)
  • OS: Raspberry Pi OS Bookworm (64-bit, Lite or Desktop)
  • Network: Cat6 Ethernet cable (preferred for static server assignments) or 2.4GHz/5GHz Wi-Fi
  • Debugging: USB-to-TTL serial adapter (CP2102 or PL2303) for headless recovery

Network Interface & IP Allocation Table

NetworkManager separates the interface (e.g., eth0) from the connection profile (e.g., Wired connection 1). You must configure the profile, not the raw interface.

Parameter Ethernet Profile (Wired) Wi-Fi Profile (Wireless) Notes / Constraints
Connection Name Wired connection 1 MyWiFiNetwork Case-sensitive. Use exactly what nmcli con show outputs.
Target Static IP 192.168.1.50/24 192.168.1.51/24 CIDR notation is mandatory. /24 = 255.255.255.0 subnet mask.
Gateway 192.168.1.1 192.168.1.1 Must be on the same subnet as the static IP.
DNS Servers 1.1.1.1, 8.8.8.8 1.1.1.1, 8.8.8.8 Comma-separated, no spaces.
Method manual manual Tells NetworkManager to ignore DHCP offers.

Headless Debugging: UART Pin Mapping

If you mistype your gateway and lose SSH access, you need a physical backdoor. Here is the exact pin mapping to connect a USB-TTL serial adapter to the Pi's GPIO header for direct console access.

Pi GPIO Pin (Physical) BCM Function USB-TTL Adapter Pin Wiring Rule
Pin 6 GND GND Common ground is mandatory for logic levels.
Pin 8 GPIO 14 (TXD) RXD (Receive) TX always connects to RX (cross-over).
Pin 10 GPIO 15 (RXD) TXD (Transmit) RX always connects to TX (cross-over).

Note: Ensure your USB-TTL adapter is set to 3.3V logic. Feeding 5V into Pin 10 will fry the Pi's UART controller.

2. The Right Way: Setting Static IP via nmcli

Open your SSH session or serial terminal. We are going to modify the default Ethernet connection profile. Do not try to create a new profile from scratch unless you are bonding interfaces; modifying the existing one preserves your link-state rules.

  1. Identify your active connections:
    nmcli connection show
    Look under the "NAME" column. For a fresh Pi OS install on Ethernet, it is almost always Wired connection 1.
  2. Assign the Static IP, Gateway, and DNS:
    nmcli connection modify "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
    Crucial: The quotes around the connection name are required if it contains spaces.
  3. Apply the changes by bouncing the interface:
    nmcli connection up "Wired connection 1"
    Your SSH session will freeze and disconnect immediately because your IP address just changed. Reconnect using the new static IP.
  4. Verify the assignment:
    ip -4 addr show eth0
    You should see inet 192.168.1.50/24 in the output.
Callout Tip: The "autoconnect" Priority
NetworkManager assigns an autoconnect-priority to profiles. If you have multiple wired profiles, ensure your static profile has the highest priority so it boots first: nmcli con mod "Wired connection 1" connection.autoconnect-priority 10.

3. Automated Setup & Verification Script

When provisioning multiple Pis for a sensor array or home lab cluster, typing nmcli flags manually invites typos. Below is a complete, production-ready bash script. It targets Raspberry Pi OS Bookworm (64-bit) and includes error handling to verify that nmcli exists, the connection profile is valid, and the gateway is reachable post-assignment.

#!/bin/bash
# Target: Raspberry Pi 5 / 4 (Raspberry Pi OS Bookworm 64-bit)
# Purpose: Set static IP via NetworkManager (nmcli) with error handling

set -e # Exit immediately if a command exits with a non-zero status

# --- CONFIGURATION VARIABLES ---
CONN_NAME="Wired connection 1"
STATIC_IP="192.168.1.50/24"
GATEWAY="192.168.1.1"
DNS="1.1.1.1,8.8.8.8"

# --- PRE-FLIGHT CHECKS ---
# 1. Verify NetworkManager is the active network daemon
if ! command -v nmcli &> /dev/null; then
    echo "FATAL: nmcli not found. Are you on Bullseye or older using dhcpcd?"
    exit 1
fi

# 2. Check if the target connection profile actually exists
if ! nmcli connection show "$CONN_NAME" &> /dev/null; then
    echo "ERROR: Connection '$CONN_NAME' not found."
    echo "Run 'nmcli con show' to find your exact interface profile name."
    exit 1
fi

# --- APPLY CONFIGURATION ---
echo "Applying static IP configuration to '$CONN_NAME'..."
nmcli connection modify "$CONN_NAME" \
    ipv4.addresses "$STATIC_IP" \
    ipv4.gateway "$GATEWAY" \
    ipv4.dns "$DNS" \
    ipv4.method manual

echo "Restarting connection to apply changes..."
# We use 'up' which implicitly brings down the previous state
nmcli connection up "$CONN_NAME" || echo "WARNING: Connection dropped (expected if SSH IP changed)."

# --- POST-FLIGHT VERIFICATION ---
# Wait 3 seconds for the link to negotiate and ARP to resolve
sleep 3 

if ping -c 3 -W 2 "$GATEWAY" &> /dev/null; then
    echo "SUCCESS: Gateway reachable at $GATEWAY. Static IP $STATIC_IP is live."
else
    echo "WARNING: Cannot ping gateway. Check subnet mask, physical link, and gateway IP."
    exit 1
fi

4. Debugging: Exact Error Strings and Fixes

NetworkManager is notoriously pedantic about syntax. If your setup fails, you will likely hit one of these exact error strings. Here is the ranked cause list and the fix for each.

Error 1: Error: unknown connection 'eth0'.

  • Cause: You are treating nmcli like the old ifupdown system. eth0 is the hardware interface name, but nmcli connection modify expects the Connection Name (the profile).
  • Fix: Run nmcli con show and use the value in the NAME column (e.g., "Wired connection 1").

Error 2: Error: Failed to add 'Wired connection 1' connection: connection already exists.

  • Cause: You accidentally used nmcli connection add instead of nmcli connection modify. The add command tries to create a brand new profile from scratch.
  • Fix: Use modify to edit existing profiles. If you truly want a fresh profile, delete the old one first: nmcli con delete "Wired connection 1".

Error 3: ping: connect: Network is unreachable

  • Cause: Subnet mismatch. Your static IP and your gateway do not share the same network space based on your CIDR mask. For example, setting IP 192.168.1.50/24 but gateway 192.168.0.1.
  • Fix: Verify your router's actual subnet. Most home routers use /24 (255.255.255.0), meaning the first three octets of the IP and Gateway must match exactly.

5. First Three Things to Check When It Fails

If you applied the settings, rebooted, and cannot reach the Pi via SSH or ping, do not immediately reflash the SD card. Run through this physical and logical checklist:

  1. Check for IP Conflicts on the LAN: If you assigned 192.168.1.50 but your router's DHCP pool hasn't excluded that address, the router may have handed it to your phone or a smart TV. The resulting ARP conflict will drop the Pi's packets. Fix: Log into your router and shrink the DHCP pool (e.g., .100 to .200) or bind the Pi's MAC address to the static IP in the router's DHCP reservation table.
  2. Verify the Physical Link State: Run nmcli device status via your UART serial console. If eth0 shows as disconnected or unavailable, NetworkManager refuses to apply the IP profile to a dead link. Check your Cat6 cable and switch port LEDs.
  3. Inspect the Routing Table: Run ip route. If the default via line is missing or points to the wrong gateway, your Pi can talk to local devices but cannot route to the internet or external subnets. Re-apply the ipv4.gateway parameter via nmcli.

6. Extending and Simplifying the Build

Depending on your end goal, a manual static IP on the Pi itself might be the wrong architectural choice. Here is how to simplify or extend this setup based on real-world deployment scenarios.

Simplify: Use DHCP Reservations (The "No-Touch" Method)

If you are deploying a Pi in a home environment where you control the router, do not set the static IP on the Pi. Leave the Pi on DHCP (ipv4.method auto). Instead, log into your router (pfSense, UniFi, or standard consumer Asus/Netgear) and create a DHCP Reservation binding the Pi's MAC address to 192.168.1.50.
Why? If you move the Pi to a different network (e.g., a friend's house or a different VLAN), a hardcoded static IP will instantly brick your network access. DHCP reservations keep the Pi portable while guaranteeing the IP never changes on your home LAN.

Extend: mDNS and Avahi for Headless Discovery

If you hate memorizing IP addresses entirely, ensure the avahi-daemon package is installed and running. This enables multicast DNS (mDNS). You can then SSH into your Pi using its hostname followed by .local, regardless of what IP the DHCP server or NetworkManager assigns it:

ssh pi@raspberrypi.local

This is the standard protocol used by Apple (Bonjour) and modern Linux distributions for local network discovery, completely bypassing the need to check your router's client list for the Pi's current IP.

Authoritative References:
For deeper reading on the transition from dhcpcd to NetworkManager in Raspberry Pi OS, consult the official Raspberry Pi Network Configuration documentation. For advanced nmcli syntax and property flags, refer to the NetworkManager nmcli manual.