If you are still trying to edit /etc/dhcpcd.conf to set a static IP, stop immediately. That file is dead. Starting with Raspberry Pi OS Bookworm and continuing into Trixie, the Raspberry Pi Foundation completely replaced dhcpcd with NetworkManager. Attempting to use legacy methods will result in your Pi silently falling back to DHCP or dropping off the network entirely.
To change IP address Raspberry Pi on modern OS versions, you must use the nmcli (NetworkManager Command Line Interface) tool. Below, we will cover the exact CLI commands to set a static IP, and then build a hardware I2C OLED monitor that displays your Pi's active IP address on boot—complete with Python error handling for network interface delays.
Project Spec Sheet & Parts List
This build pairs a network configuration workflow with a physical IP readout. This is especially useful for headless setups or robotics projects where the Pi moves between different VLANs or subnets.
| Component | Exact Variant / Model | Notes & Pricing (Approx.) |
|---|---|---|
| Microcontroller | Raspberry Pi 5 (8GB RAM) | Requires active cooler; uses lgpio instead of legacy RPi.GPIO ($80) |
| Display | Waveshare 1.3" OLED HAT (SH1106) | 128x64 I2C interface, 3.3V logic ($14) |
| Power Supply | Official Raspberry Pi 27W USB-C PD | Required to prevent brownout warnings on Pi 5 ($12) |
| Storage | 32GB Samsung EVO Plus microSD | A1/A2 rated for OS boot reliability ($9) |
Hardware Assembly & Pin Mapping
The Waveshare 1.3" OLED HAT plugs directly onto the first 26 pins of the Pi 5 GPIO header. While it physically covers more pins, it only actively uses the I2C bus and power rails. Ensure your Pi is powered off and the active cooler is seated before pressing the HAT onto the headers.
| OLED HAT Pin Label | Raspberry Pi 5 GPIO (BCM) | Physical Pin Number | Function |
|---|---|---|---|
| VCC | 3V3 | 1 | 3.3V Power Rail |
| GND | GND | 6 | Common Ground |
| SDA | GPIO 2 | 3 | I2C Data Line |
| SCL | GPIO 3 | 5 | I2C Clock Line |
sudo raspi-config → Interface Options → I2C → Enable. Verify it with ls /dev/i2c*—you should see /dev/i2c-1.
How to Change IP Address Raspberry Pi via NetworkManager
NetworkManager uses "connection profiles" rather than binding settings directly to hardware interface names (like eth0). This prevents configuration breakage if the kernel assigns a different predictable network interface name (like enp1s0f0).
- Identify your active connection profile:
Runnmcli connection show. Look under the "NAME" column. For Ethernet, it is usuallyWired connection 1. For WiFi, it will be your SSID name. - Assign the static IP and subnet mask:
sudo nmcli connection modify "Wired connection 1" ipv4.addresses 192.168.1.50/24
(Replace 192.168.1.50 with your desired IP, and /24 with your subnet, typically /24 for home networks). - Set the default gateway (your router's IP):
sudo nmcli connection modify "Wired connection 1" ipv4.gateway 192.168.1.1 - Define DNS servers:
sudo nmcli connection modify "Wired connection 1" ipv4.dns "8.8.8.8 1.1.1.1" - Switch the IPv4 method from DHCP to Manual:
sudo nmcli connection modify "Wired connection 1" ipv4.method manual - Restart the connection to apply changes:
sudo nmcli connection up "Wired connection 1"
Verify the change by typing ip -4 addr show. You should see your new static IP listed under the active Ethernet interface. For deeper architectural context, refer to the official Raspberry Pi NetworkManager documentation.
Python IP Monitor Script (With Error Handling)
Network interfaces on the Pi 5 can take 3 to 8 seconds to negotiate a link and pull an IP address on boot. If a Python script queries the IP immediately, it will crash. The script below targets the Pi 5, uses the lgpio backend required for Bookworm/Trixie, and implements a retry loop with explicit hardware pin definitions.
Prerequisites: sudo apt install python3-pip python3-venv libopenjp2-7 libtiff6 i2c-tools then pip install luma.oled lgpio
import time
import socket
import subprocess
import sys
from luma.core.interface.serial import i2c
from luma.oled.device import sh1106
from PIL import Image, ImageDraw, ImageFont
# --- HARDWARE PIN & BUS DEFINITIONS ---
I2C_PORT = 1 # Maps to Physical pins 3 (SDA) and 5 (SCL)
I2C_ADDRESS = 0x3C # Waveshare 1.3" OLED default I2C address
OLED_WIDTH = 128
OLED_HEIGHT = 64
MAX_RETRIES = 10 # Wait up to 10 seconds for network link
# --- DISPLAY INITIALIZATION ---
try:
serial = i2c(port=I2C_PORT, address=I2C_ADDRESS)
device = sh1106(serial, width=OLED_WIDTH, height=OLED_HEIGHT)
except Exception as e:
print(f"[FATAL] OLED Init Failed: {e}")
print("Check I2C enablement and wiring.")
sys.exit(1)
def get_ip_address(interface='eth0'):
"""Fetches IP using socket, falling back to nmcli if interface name is unpredictable."""
try:
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.connect(("8.8.8.8", 80))
ip = s.getsockname()[0]
s.close()
return ip
except Exception:
# Fallback to nmcli for modern NetworkManager environments
try:
cmd = "nmcli -g IP4.ADDRESS connection show --active | head -n 1"
result = subprocess.check_output(cmd, shell=True).decode('utf-8').strip()
return result.split('/')[0] if result else 'No IP'
except subprocess.CalledProcessError:
return 'Network Down'
def main():
# Font setup (using default PIL font for broad compatibility)
font_large = ImageFont.load_default()
retries = 0
ip_addr = 'Waiting for DHCP...'
while retries < MAX_RETRIES:
ip_addr = get_ip_address()
if ip_addr != 'No IP' and ip_addr != 'Network Down' and ip_addr != 'Waiting for DHCP...':
break
time.sleep(1)
retries += 1
# Render to OLED
image = Image.new('1', (OLED_WIDTH, OLED_HEIGHT))
draw = ImageDraw.Draw(image)
draw.text((0, 0), "Pi 5 Status:", font=font_large, fill=255)
draw.text((0, 20), "IP Address:", font=font_large, fill=255)
draw.text((0, 35), ip_addr, font=font_large, fill=255)
device.display(image)
print(f"[SUCCESS] Displaying IP: {ip_addr}")
if __name__ == "__main__":
main()
For comprehensive API details on the display driver, consult the luma.oled ReadTheDocs documentation.
Debugging: Exact Error Strings & Ranked Causes
When configuring networks or driving I2C displays on the Pi 5, you will inevitably hit roadblocks. Here are the exact error strings you will see, ranked by frequency, and how to fix them.
1. "Error: Connection 'eth0' not found."
- Cause: You tried to run
nmcli connection modify eth0. NetworkManager uses profile names, not kernel interface names. - Fix: Run
nmcli connection showand use the exact string from the NAME column (e.g.,"Wired connection 1").
2. "RTNETLINK answers: File exists"
- Cause: You are attempting to assign a static IP that is already actively bound to another interface (like a USB-to-Ethernet adapter or a VPN tunnel), or the IP is currently leased to another device on the LAN causing an ARP conflict.
- Fix: Run
ip addr flush dev eth0to clear stale leases, then bring the connection up. Ensure your router's DHCP pool excludes your chosen static IP.
3. "ModuleNotFoundError: No module named 'lgpio'" or "RuntimeError: This module can only be run on a Raspberry Pi"
- Cause: The legacy
RPi.GPIOlibrary is hardcoded for Pi 4 and older Broadcom chips. The Pi 5 uses the RP1 southbridge chip, which breaks legacy GPIO libraries. - Fix: Uninstall the old library (
pip uninstall RPi.GPIO) and install the modern replacement:pip install lgpio. Theluma.corelibrary will automatically detect and uselgpioif it is present in the environment.
First Three Things to Check When It Fails:
- I2C Bus Presence: Run
i2cdetect -y 1. If the grid is empty, your OLED HAT is not seated properly or I2C is disabled inraspi-config. - Active Connection State: Run
nmcli device status. If Ethernet shows "disconnected", your cable is bad or the switch port is dead. - DHCP Pool Overlap: Log into your router. If your router hands out IPs from 192.168.1.2 to 192.168.1.254, setting a static IP in that range will eventually cause an IP collision.
Extending and Simplifying the Build
How to Simplify: If you don't need the physical OLED readout and just want a headless static IP setup for a server rack, strip away the Python script and hardware entirely. Simply execute the six nmcli commands listed above, and add a cronjob that emails you if the link drops using iptables logging.
How to Extend: Turn this into a network diagnostic tool. Wire a momentary pushbutton to GPIO 17 (Physical Pin 11) and a 10k pull-down resistor to GND. Modify the Python script to listen for a button press using lgpio. When pressed, have the script toggle the NetworkManager profile between ipv4.method manual (Static) and ipv4.method auto (DHCP). This allows you to physically switch your Pi between a lab bench subnet and a home network without needing a keyboard or SSH access.
Frequently Asked Questions
How do I change IP address Raspberry Pi without a monitor?
If your Pi is headless and you don't know its current IP, connect it directly to your PC via Ethernet. Set your PC's Ethernet adapter to a static IP in the 169.254.x.x (link-local) range. Alternatively, log into your router's admin panel and check the DHCP client lease table to find the Pi's hostname (usually raspberrypi) and its currently assigned IP, then SSH in to run the nmcli commands.
Why did my raspberry pi static IP change after reboot?
This happens almost exclusively because you edited the deprecated /etc/dhcpcd.conf file. In modern Pi OS (Bookworm and newer), dhcpcd is disabled by default. NetworkManager ignores that file entirely and requests a DHCP lease on boot. You must use nmcli connection modify to make the static IP persistent across reboots.
How to change IP address Raspberry Pi using nmcli for WiFi?
The process is identical to Ethernet, but the connection name will be your SSID. First, find the profile name with nmcli connection show. Then apply the manual IP settings:
sudo nmcli connection modify "MyWiFiSSID" ipv4.addresses 192.168.1.60/24 ipv4.gateway 192.168.1.1 ipv4.dns "8.8.8.8" ipv4.method manual
Finally, reconnect with sudo nmcli connection up "MyWiFiSSID".
Can I use the desktop GUI to set a static IP instead of the terminal?
Yes. If you are running the desktop environment of Pi OS, click the Network icon in the top right system tray, select "Advanced Options" or "Edit Connections", choose your active interface, and navigate to the IPv4 tab. Change the Method from "Automatic (DHCP)" to "Manual", input your Address, Netmask (usually 255.255.255.0), and Gateway, then save and reconnect.






