nmcli can configure network interfaces, but it’s a higher-level tool that abstracts away many of the details ip provides.

# Show current IP configuration
ip addr show

# Show current routing table
ip route show

# Bring an interface up
ip link set eth0 up

# Bring an interface down
ip link set eth0 down

# Assign an IP address to an interface
ip addr add 192.168.1.100/24 dev eth0

# Remove an IP address from an interface
ip addr del 192.168.1.100/24 dev eth0

# Add a default route
ip route add default via 192.168.1.1

# Remove a default route
ip route del default

# Show ARP cache
ip neigh show

nmcli provides a more user-friendly, declarative way to manage network connections. It interacts with NetworkManager, which is the service responsible for configuring network devices.

# List all network devices and their states
nmcli device status

# List all configured network connections
nmcli connection show

# Show details of a specific connection
nmcli connection show "Wired connection 1"

# Create a new wired connection
nmcli connection add type ethernet con-name "MyEth0" ifname eth0

# Configure a static IP address for a connection
nmcli connection modify "MyEth0" ipv4.method manual ipv4.addresses 192.168.1.100/24 ipv4.gateway 192.168.1.1

# Configure DNS for a connection
nmcli connection modify "MyEth0" ipv4.dns "8.8.8.8,8.8.4.4"

# Enable DHCP for a connection
nmcli connection modify "MyEth0" ipv4.method auto

# Activate a connection
nmcli connection up "MyEth0"

# Deactivate a connection
nmcli connection down "MyEth0"

# Delete a connection
nmcli connection delete "MyEth0"

The surprising truth is that nmcli doesn’t directly manipulate the kernel’s network stack like ip does. Instead, it tells the NetworkManager service what you want, and NetworkManager then uses underlying tools (which often include ip or rtnl messages) to achieve the desired state. This means that if NetworkManager isn’t running or is misconfigured, nmcli commands might appear to work but won’t persist, or they might fail entirely.

Consider a scenario where you’re setting up a new server and need to assign a static IP address. Using ip directly, you’d run commands like:

ip link set eth0 up
ip addr add 10.0.0.50/24 dev eth0
ip route add default via 10.0.0.1 dev eth0
echo "nameserver 8.8.8.8" > /etc/resolv.conf

These changes are immediate but transient; they’ll be lost on reboot. To make them permanent, you’d typically edit configuration files in /etc/network/interfaces (on Debian/Ubuntu) or files in /etc/sysconfig/network-scripts/ (on RHEL/CentOS).

With nmcli, the process is different:

# Ensure the device is managed by NetworkManager
nmcli device status

# If eth0 isn't listed or is unmanaged, you might need to enable it
nmcli radio wifi off # Example to free up resources if needed
nmcli device set eth0 managed yes

# Create a new connection profile
nmcli connection add type ethernet con-name "StaticEth0" ifname eth0

# Set the static IP, gateway, and DNS
nmcli connection modify "StaticEth0" ipv4.method manual ipv4.addresses 10.0.0.50/24 ipv4.gateway 10.0.0.1 ipv4.dns "8.8.8.8"

# Bring the connection up
nmcli connection up "StaticEth0"

This approach is declarative. You tell nmcli the desired state (static IP, gateway, DNS), and NetworkManager handles the underlying configuration and ensures it’s applied persistently. The configuration is stored in /etc/NetworkManager/system-connections/.

The real power of nmcli comes from its ability to manage complex network setups, including Wi-Fi, VPNs, bridges, and bonds, all through a consistent interface. It abstracts away the differences between various network configuration backends.

One subtle point often missed is how nmcli handles connection profiles. When you use nmcli connection add, you’re creating a profile that NetworkManager will use to configure a device. If you have multiple profiles attempting to configure the same device, or if a device is already configured by another service (like systemd-networkd or the older ifupdown scripts), NetworkManager might refuse to manage it, or conflicts can arise. The nmcli device set <ifname> managed yes|no command is crucial for explicitly telling NetworkManager whether to take control of a device. If a device is marked as "unmanaged," nmcli will ignore it, and you’ll need to configure it using other tools.

The next step is understanding how to configure more advanced network features like bonding and bridging using nmcli.

Want structured learning?

Take the full Linux & Systems Programming course →