On Ubuntu Server 26.04, a fresh NetworkManager install saves every nmcli profile and activates none of them. Every profile we created landed as its own YAML file in /etc/netplan, and the first nmcli connection up failed with “the device is unmanaged”. On a Debian 13 cloud image the same install does the opposite and grabs the primary NIC, which ended with two DHCP addresses on eth0 within a minute.
This guide covers both distributions side by side. It installs NetworkManager, fixes the default that bites on each one, then builds static, VLAN, bridge, bond and WiFi profiles with nmcli and reads the result back from the kernel. Every write runs on dummy interfaces, so the NIC carrying your SSH session stays untouched until the last step, which hands it over on purpose.
Tested October 2026 on NetworkManager 1.54 (Ubuntu 26.04) and 1.52 (Debian 13).
Ubuntu 26.04 and Debian 13 compared
The two distributions ship different defaults for the same package, and that difference decides which fix you need first. We installed network-manager on a fresh cloud image of each and recorded what changed before touching any configuration:
| Measured after install | Ubuntu 26.04 LTS | Debian 13 (trixie) |
|---|---|---|
| NetworkManager version | 1.54.3 | 1.52.1 |
| Packages pulled in | 13 | 34 |
State of eth0 right after install | unmanaged | connected as “Wired connection 1” |
| New profiles you create | refused until devices are managed | activate immediately |
| Where nmcli saves a profile | /etc/netplan/90-NM-<uuid>.yaml | /etc/NetworkManager/system-connections/ |
Addresses on eth0 after install | 1 (systemd-networkd) | 2 (networkd and NetworkManager) |
The same package therefore needs a different first fix depending on how the machine was installed, and the table only covers the two cloud images we measured. Read your own nmcli device status against these four cases before you create a profile:
- Ubuntu Server 26.04: safe by default, because nothing changes hands, but every new profile fails to activate until you apply Step 2.
- Debian 13 cloud image: usable at once, but NetworkManager starts a second DHCP client on
eth0, so apply Step 3 first. - Debian 13 from the netinst ISO:
eth0lives in/etc/network/interfaces, and theifupdownplugin in NetworkManager leaves interfaces listed there alone, so neither fix is needed. - Desktop installs of either distribution: NetworkManager already owns every device, and the profile steps work as written.
We did not install from the netinst ISO for this test. The netinst behaviour comes from the [ifupdown] managed=false setting that the Debian package ships in NetworkManager.conf, which our Debian VM showed as well.
Prerequisites
Any of these will do as a test machine. The dummy interfaces used below exist only in the kernel, so a VM with one NIC is enough:
- Ubuntu 26.04 LTS server or Debian 13 with a sudo user
- Console access (Proxmox, IPMI or a cloud serial console) for the last step
- Nothing else listening on 10.99.99.0/24, 10.100.0.0/24, 10.88.0.0/24 or 10.77.0.0/24
Run the profile commands from SSH, but keep the console open before Step 3 on Debian and Step 9 on Ubuntu. Both steps change who owns the NIC your session runs on, and on our Debian VM that dropped the SSH connection.
Step 1: Install NetworkManager
The package name is the same on both distributions, and the service starts on its own after the install. On Ubuntu 26.04 it pulled 13 packages, including wpasupplicant and dnsmasq-base:
sudo apt-get update
sudo apt-get install -y network-manager
Confirm the version and that the daemon is running before going further. A stopped daemon makes every later nmcli command fail, so this check rules out the simplest cause before you read anything into the errors further down:
nmcli --version
systemctl is-active NetworkManager
Ubuntu 26.04 reports 1.54.3 and Debian 13 reports 1.52.1, and both answer active. We ran every command in this guide on Ubuntu 26.04 and the install, dummy, VLAN and bond steps on Debian 13 as well, and none needed a different spelling on the older release:
nmcli tool, version 1.54.3
active
Now look at what NetworkManager decided to manage. This one command tells you which of the next two steps applies to your machine:
nmcli device status
On Ubuntu Server every wired device shows unmanaged, and nmcli general status reads disconnected even though the machine is online through systemd-networkd. That is not a fault. NetworkManager reports only on devices it controls, so a server you are logged into over SSH can still look offline here:
DEVICE TYPE STATE CONNECTION
eth0 ethernet unmanaged --
lo loopback unmanaged --
On the Debian 13 cloud image the same command shows eth0 already connected through an automatic profile called “Wired connection 1”. If you see that, skip to Step 3 before creating anything.
Step 2: Unblock managed devices on Ubuntu
The Ubuntu package ships /usr/lib/NetworkManager/conf.d/10-globally-managed-devices.conf, which marks every device unmanaged except WiFi and mobile modems. It exists so that installing NetworkManager on a server never takes the NIC away from netplan and systemd-networkd. The side effect is that nmcli accepts new profiles and then refuses to bring them up:
[keyfile]
unmanaged-devices=*,except:type:wifi,except:type:gsm,except:type:cdma
A file with the same name in /etc/NetworkManager/conf.d takes precedence over the packaged one, so an empty file there lifts the rule. It also survives package upgrades, because the package never touches its copy in /etc:
sudo touch /etc/NetworkManager/conf.d/10-globally-managed-devices.conf
sudo systemctl restart NetworkManager
We checked the order on a fresh 26.04 VM. After the restart eth0 still reads unmanaged, and that is correct:
DEVICE TYPE STATE CONNECTION
lo loopback connected (externally) lo
eth0 ethernet unmanaged --
On Ubuntu, netplan marks every NIC it assigns to systemd-networkd as unmanaged for NetworkManager through a generated udev rule, so lifting the global rule does not touch eth0. Only devices that nmcli creates, or that you hand over in Step 9, become managed, and your SSH session is safe through Steps 4 to 8. The Debian package has no such netplan integration, which is why the next step exists.
Step 3: Keep eth0 out of NetworkManager on Debian
The Debian 13 cloud image configures eth0 through netplan and systemd-networkd, and NetworkManager on Debian has no rule like the Ubuntu one to stay away from it. It saw an unconfigured ethernet device, created “Wired connection 1” for it and started its own DHCP client. A minute after the install the NIC carried two leases:
ip -4 addr show eth0 | grep inet
The first address came from systemd-networkd, which netplan configured at boot. The second carries noprefixroute because NetworkManager installs prefix routes itself with its own metric, and that flag is the quickest way to tell which daemon added an address:
inet 10.0.1.50/24 metric 100 brd 10.0.1.255 scope global dynamic eth0
inet 10.0.1.51/24 brd 10.0.1.255 scope global secondary dynamic noprefixroute eth0
Two DHCP clients on one interface hold two leases from the same pool and renew them independently, which wastes an address and makes the host answer on an IP nothing documents. Pick one owner. We kept systemd-networkd on eth0, because netplan and cloud-init already manage it, and told NetworkManager to leave it alone and to stop creating automatic wired profiles:
sudo vi /etc/NetworkManager/conf.d/90-leave-eth0.conf
Add these lines, replacing eth0 if your NIC has another name. The first setting stops automatic wired profiles for every device, and the second leaves the named NIC to systemd-networkd, so new hardware will not repeat the problem either:
[main]
no-auto-default=*
[keyfile]
unmanaged-devices=interface-name:eth0
Apply it with a reboot, not with nmcli general reload conf. On our VM the live reload moved eth0 from activated to unmanaged mid-session, NetworkManager cancelled its DHCP transaction, and the SSH connection over that NIC dropped and stayed dead until the VM was reset. From the console, or over SSH if you accept the reconnect, reboot instead:
sudo systemctl reboot
After the reboot each daemon owns its own devices. nmcli device status lists eth0 as unmanaged, networkctl list shows it as configured, and eth0 holds a single address. “Wired connection 1” is gone because it only ever lived in /run.
Step 4: Create a static profile on a dummy interface
A dummy interface behaves like a NIC with no cable, which makes it the right target for practice: addresses, routes and DNS all apply, and nothing on your network sees them. Create one with a static address and IPv6 off:
sudo nmcli connection add type dummy ifname dummy0 con-name demo-static \
ipv4.method manual ipv4.addresses 10.99.99.10/24 ipv6.method disabled
On Ubuntu with the Step 2 override in place, and on Debian straight away, the profile comes up at once. Read the device table rather than the success message from add, because that message only proves the profile was saved:
nmcli device status
ip -br addr show dummy0
Here both tools agree. NetworkManager lists dummy0 as connected under demo-static, and the kernel holds 10.99.99.10/24 on it. A device that reads connected while ip shows no address has a second owner removing it, which is the problem Step 3 fixes on Debian:
DEVICE TYPE STATE CONNECTION
dummy0 dummy connected demo-static
lo loopback connected (externally) lo
eth0 ethernet unmanaged --
dummy0 UNKNOWN 10.99.99.10/24
Where the profile was saved differs between the two distributions, and it matters the first time you back up or edit one by hand. On Debian nmcli writes a keyfile to /etc/NetworkManager/system-connections/demo-static.nmconnection. On Ubuntu it writes netplan YAML instead, and the keyfile NetworkManager reads is generated from it into /run:
nmcli -f NAME,TYPE,DEVICE,FILENAME connection show
The FILENAME column on Ubuntu points into /run:
NAME TYPE DEVICE FILENAME
demo-static dummy dummy0 /run/NetworkManager/system-connections/netplan-dummy0.nmconnection
lo loopback lo /run/NetworkManager/system-connections/lo.nmconnection
The real copy on Ubuntu is a YAML file named after the UUID of the profile. That split catches people later, because the path nmcli reports is neither the file to back up nor the file to edit. On Ubuntu only, print it:
sudo cat /etc/netplan/90-NM-*.yaml
Netplan keeps the address in its own syntax and passes the remaining NetworkManager settings through untouched:
network:
version: 2
dummy-devices:
dummy0:
renderer: NetworkManager
addresses:
- "10.99.99.10/24"
networkmanager:
uuid: "cd45990a-bea4-45f8-b7ad-db3499a41a1f"
name: "demo-static"
passthrough:
dummy._: ""
ipv6.addr-gen-mode: "default"
ipv6.method: "disabled"
ipv6.ip6-privacy: "-1"
proxy._: ""
Never edit the file under /run on Ubuntu. It is regenerated from the YAML at every boot and every netplan generate, so the change disappears silently. Use nmcli, or edit the YAML and run sudo netplan apply. Backups on Ubuntu should cover /etc/netplan, which now holds one file per nmcli profile. The 8 profiles in this guide, WiFi included, produced 8 90-NM-*.yaml files next to 50-cloud-init.yaml, and deleting the profiles in Step 8 removed all of them again.
Step 5: Change addresses, routes and DNS
The connection modify command edits the saved profile only. A plus sign appends to a list property, and a bare property name replaces the whole list, so this command swaps the address for two new ones:
sudo nmcli connection modify demo-static ipv4.addresses 10.99.99.20/24 +ipv4.addresses 10.99.99.21/24
nmcli -g ipv4.addresses connection show demo-static
ip -br addr show dummy0
The profile now lists both addresses while the interface still carries the old one, because modify writes the saved profile and leaves the running device as it was:
10.99.99.20/24, 10.99.99.21/24
dummy0 UNKNOWN 10.99.99.10/24
That gap between profile and device is the most common reason people think nmcli “did nothing”. Re-activate the profile to push the change to the kernel, then add a static route with a metric of 100 while you are at it:
sudo nmcli connection modify demo-static +ipv4.routes "172.20.0.0/16 10.99.99.1 100"
sudo nmcli connection up demo-static
ip route show dev dummy0
The route carries proto static and the metric we set, and the two connected routes come from the two addresses. A route that appears in nmcli -g ipv4.routes but not here means the profile was changed and never re-activated:
10.99.99.0/24 proto kernel scope link src 10.99.99.20 metric 550
10.99.99.0/24 proto kernel scope link src 10.99.99.21 metric 550
172.20.0.0/16 via 10.99.99.1 proto static metric 100
Leave ipv4.gateway empty on a secondary profile like this one. A gateway makes NetworkManager add a default route through that interface, and with two default routes the metric decides which one wins, which is not a choice to leave to defaults on a multi-homed server. If such a profile gets a gateway from DHCP, set ipv4.never-default yes. That stops it from installing any default route at all, so reach the networks behind it with ipv4.routes as above.
DNS works the same way. Both cloud images run systemd-resolved with /etc/resolv.conf pointing at the 127.0.0.53 stub, so NetworkManager hands the servers to resolved per link instead of writing them into resolv.conf. Check the link, not the file:
sudo nmcli connection modify demo-static ipv4.dns "1.1.1.1 9.9.9.9" ipv4.dns-search lab.example.com
sudo nmcli connection up demo-static
resolvectl dns dummy0
resolvectl domain dummy0
Resolved now holds both servers and the search domain for dummy0, while /etc/resolv.conf still lists only the stub. That is the expected split, so an unchanged resolv.conf is not evidence that the DNS change failed:
Link 3 (dummy0): 1.1.1.1 9.9.9.9
Link 3 (dummy0): lab.example.com
A Debian 13 install from the netinst ISO does not ship systemd-resolved. There NetworkManager writes the servers into /etc/resolv.conf itself, and resolvectl is not even installed because it ships in the systemd-resolved package, so read the file on those machines.
We rebooted the Ubuntu VM at this point to check persistence. The profile came back with both addresses and the static route, without any extra command, because the YAML in /etc/netplan is the saved state.
Step 6: Build a VLAN, a bridge and a bond
All three are virtual devices that nmcli creates for you. We ran all three on Ubuntu 26.04, and the VLAN and bond on Debian 13 too, with identical commands. A VLAN needs a parent device and a tag. The dummy from Step 4 serves as the parent here, and on real hardware you would use the trunk NIC:
sudo nmcli connection add type vlan con-name vlan100 ifname dummy0.100 vlan.parent dummy0 vlan.id 100 \
ipv4.method manual ipv4.addresses 10.100.0.10/24 ipv6.method disabled
ip -d link show dummy0.100 | grep -oE 'vlan protocol 802.1Q id [0-9]+'
The kernel confirms the 802.1Q tag on the new device. Check the tag this way, because a wrong VLAN ID still leaves nmcli reporting the profile as connected while the switch drops every frame:
vlan protocol 802.1Q id 100
A bridge is two kinds of profile: the bridge itself, which owns the IP address, and one port profile per member. The port profiles point at the bridge with controller and port-type, the names current documentation uses. Older scripts written with master and slave-type keep running, because we confirmed on 1.52 that nmcli still accepts the old names and stores them as the new ones:
sudo nmcli connection add type bridge con-name br0 ifname br0 bridge.stp no \
ipv4.method manual ipv4.addresses 10.88.0.1/24 ipv6.method disabled
sudo nmcli connection add type dummy ifname dummy2 con-name br0-port1 controller br0 port-type bridge
sudo nmcli connection up br0
bridge link show
The port shows master br0 in the forwarding state. We set bridge.stp no, so the port forwards at once instead of waiting through the STP listening and learning delay:
7: dummy2: <BROADCAST,NOARP,UP,LOWER_UP> mtu 1500 master br0 state forwarding priority 32 cost 100
A bond follows the same pattern, with the bonding mode in bond.options. Active-backup with MII monitoring every 100 ms is the mode that works with any switch, which is why we use it as the default for server uplinks:
sudo nmcli connection add type bond con-name bond0 ifname bond0 bond.options "mode=active-backup,miimon=100" \
ipv4.method manual ipv4.addresses 10.77.0.10/24 ipv6.method disabled
sudo nmcli connection add type dummy ifname dummy3 con-name bond0-port1 controller bond0 port-type bond
sudo nmcli connection add type dummy ifname dummy4 con-name bond0-port2 controller bond0 port-type bond
sudo nmcli connection up bond0
grep -E 'Bonding Mode|Currently Active' /proc/net/bonding/bond0
The first port becomes the active one. In active-backup mode only one port carries traffic, so the second sits idle until the first fails:
Bonding Mode: fault-tolerance (active-backup)
Currently Active Slave: dummy3
A bond you have never failed over is a bond you have not tested. Take the active port down and read the state again:
sudo ip link set dummy3 down
sleep 1
grep 'Currently Active' /proc/net/bonding/bond0
sudo ip link set dummy3 up
The bond switched to the second port within the one second we waited, which fits the 100 ms link check set in miimon:
Currently Active Slave: dummy4
On Ubuntu each of these profiles is again a netplan file, and sudo netplan get bonds prints the bond as netplan sees it, including mode: "active-backup" and mii-monitor-interval: "100". For the netplan-native way to build the same devices without NetworkManager, see our guides to VLAN interfaces on Ubuntu and VLANs on Debian.
Step 7: Connect to WiFi with nmcli
We tested WiFi without a wireless card by loading mac80211_hwsim, the simulated radio driver in the kernel, and running a WPA2 access point with hostapd on one of the two virtual radios. The packaged Ubuntu rule from Step 2 exempts type:wifi, so WiFi devices are managed even on Ubuntu Server. Our first nmcli device wifi list came back empty, and connecting failed with “No network with SSID ‘LabNet’ found”, because the access point came up after the last scan. The list command only rescans when its cached results are older than 30 seconds, so force a scan when a network has just appeared:
sudo nmcli device wifi rescan ifname wlan0
sleep 5
nmcli device wifi list ifname wlan0
The scan runs in the background, which is why the command waits five seconds before listing. The network now shows with its security type:
IN-USE BSSID SSID MODE CHAN RATE SIGNAL BARS SECURITY
02:00:00:00:01:00 LabNet Infra 6 54 Mbit/s 100 ▂▄▆█ WPA2
Connect by SSID. nmcli creates a profile named after the network and sets it to autoconnect:
sudo nmcli device wifi connect LabNet password 'lab-pass-2026' ifname wlan0
nmcli -f GENERAL.STATE,GENERAL.CONNECTION,IP4.ADDRESS device show wlan0
State 100 means the link is up and has an address from the DHCP server behind the access point. A lower state such as 70 means the device is still waiting for an address, which is where an earlier run of ours stopped before the access point had a DHCP server:
Device 'wlan0' successfully activated with '66f9e094-925b-4c8a-81c1-ef5b4bbc3219'.
GENERAL.STATE: 100 (connected)
GENERAL.CONNECTION: LabNet
IP4.ADDRESS[1]: 10.66.0.62/24
That earlier run associated with WPA2 and then failed with “IP configuration could not be reserved”, because the access point had no DHCP server yet. That message means the radio side worked and the problem is addressing, so look at DHCP on that network, not at the password.
Know where the password ends up. On Ubuntu it is stored in plain text in the netplan file of the profile, which netplan creates as mode 600 and owned by root:
sudo grep -h -B1 -A1 'password:' /etc/netplan/90-NM-*.yaml
Anyone with root can read it there, or print it with sudo nmcli -s -g 802-11-wireless-security.psk connection show LabNet:
key-management: "psk"
password: "lab-pass-2026"
networkmanager:
On Debian the keyfile plugin stores the same secret in the profile under /etc/NetworkManager/system-connections. Treat a backup of /etc/netplan or of that directory as a secret, because it holds every WiFi password the host has joined.
Step 8: Delete the test profiles
Every profile above is set to autoconnect, and demo-static came back by itself after a reboot in our lab, so the dummy addresses, VLAN 100, the bridge and the bond stay until you remove them. Delete them by name in one command, ports before the devices they belong to. Drop any name you did not create, such as LabNet on a host without WiFi; nmcli still deletes the rest but prints “unknown connection” for each missing name and exits with code 10:
sudo nmcli connection delete LabNet br0-port1 br0 bond0-port1 bond0-port2 bond0 vlan100 demo-static
ls /etc/netplan/
Each deletion prints one confirmation line, and on Ubuntu the netplan directory is back to the file cloud-init wrote:
Connection 'LabNet' (66f9e094-925b-4c8a-81c1-ef5b4bbc3219) successfully deleted.
Connection 'br0-port1' (85882ed4-05da-44dd-a221-28cde1a16b33) successfully deleted.
Connection 'br0' (72f11d7c-a721-41fe-a424-5934393503e6) successfully deleted.
Connection 'bond0-port1' (ef9cff46-8c84-4916-9a62-b8513918f97c) successfully deleted.
Connection 'bond0-port2' (aecc9d89-00df-4c16-a054-33b1bced895d) successfully deleted.
Connection 'bond0' (62733264-4bf6-45a7-a6b4-1638ca9280be) successfully deleted.
Connection 'vlan100' (08bab9fa-2e11-4600-9165-2b13d282c375) successfully deleted.
Connection 'demo-static' (cd45990a-bea4-45f8-b7ad-db3499a41a1f) successfully deleted.
50-cloud-init.yaml
Run this before Step 9 if you plan to hand eth0 over, so the only NetworkManager profile left on the host is the one for the real NIC.
Step 9: Hand eth0 to NetworkManager on Ubuntu
Only take this step if you want nmcli to manage the NIC your session runs on, for example on a lab host that moves between networks. On Ubuntu the handover goes through netplan: change the renderer and netplan generates a NetworkManager profile for eth0 instead of a systemd-networkd one. On the 26.04 cloud image the full handover took four changes, and the order matters because the third one moves your session:
- Set
renderer: NetworkManagerin the netplan file. - Stop cloud-init from regenerating that file.
- Run
netplan applyfrom the console. - Disable systemd-networkd and reboot.
Skipping the fourth change leaves both daemons configuring eth0, as shown below. Start by opening the cloud-init netplan file:
sudo vi /etc/netplan/50-cloud-init.yaml
Add the renderer line under network. Our file looked like this afterwards, with the MAC address taken from the original:
network:
version: 2
renderer: NetworkManager
ethernets:
eth0:
match:
macaddress: "bc:24:11:97:3a:fc"
dhcp4: true
set-name: "eth0"
Stop cloud-init from rewriting that file on a later boot, then apply. Run netplan apply from the console: our address changed during the handover and the SSH session died with it:
echo "network: {config: disabled}" | sudo tee /etc/cloud/cloud.cfg.d/99-disable-network-config.cfg
sudo netplan apply
NetworkManager now owns eth0 through a profile called netplan-eth0. Netplan generated it into /run from the YAML, the same way as the dummy profiles in Step 4. Our lab host still had demo-static at this point, so after Step 8 your table will not show the dummy0 row:
DEVICE TYPE STATE CONNECTION
eth0 ethernet connected netplan-eth0
dummy0 dummy connected demo-static
lo loopback connected (externally) lo
Check systemd-networkd as well, because on the 26.04 cloud image it did not let go. networkctl list still showed eth0 as configured after the apply and after a reboot:
networkctl list
ls /run/systemd/network/
The second command shows why. The initramfs, which Ubuntu 26.04 builds with dracut, leaves a catch-all zzzz-dracut-default.network in /run/systemd/network. It matches every physical NIC and asks for DHCP, and once netplan stops writing its own eth0 file, that fallback is the one networkd uses:
IDX LINK TYPE OPERATIONAL SETUP
1 lo loopback carrier unmanaged
2 eth0 ether routable configured
3 dummy0 ether routable unmanaged
3 links listed.
10-netplan-eth0.link
zzzz-dracut-default.network
With every interface under NetworkManager, systemd-networkd has nothing left to do, so disable it together with its socket and wait-online units. The socket matters, because it can start the service again on demand:
sudo systemctl disable --now systemd-networkd.service systemd-networkd.socket systemd-networkd-wait-online.service
Expect a warning and a non-zero exit code. Two more sockets trigger the service, and systemctl says so, but systemctl list-unit-files showed both as disabled afterwards and the reboot stops whatever is still running:
Removed '/etc/systemd/system/sockets.target.wants/systemd-networkd.socket'.
Removed '/etc/systemd/system/multi-user.target.wants/systemd-networkd.service'.
Removed '/etc/systemd/system/network-online.target.wants/systemd-networkd-wait-online.service'.
Disabling 'systemd-networkd.service', but its triggering units are still active:
systemd-networkd-resolve-hook.socket, systemd-networkd-varlink.socket, systemd-networkd.socket
Job for systemd-networkd.socket canceled.
Reboot from the console so that both daemons start from the new configuration:
sudo systemctl reboot
After the reboot networkd is inactive, networkctl list shows every link as unmanaged, NetworkManager holds eth0, and the host resolved and pinged archive.ubuntu.com with 0% loss. Expect the DHCP address to change at the handover. Our lease moved to a different address, which is why the console matters here, so reserve the new one on your DHCP server or give the profile a static address before you apply.
Edits to the handed-over NIC follow the Ubuntu pattern from Step 4. A nmcli connection modify netplan-eth0 did not touch 50-cloud-init.yaml. It wrote a new 90-NM-<uuid>.yaml file that overrides it, so look in both files when you audit the configuration.
Troubleshooting nmcli errors
These are the messages we hit while building the lab, with the cause each one pointed to. Each heading quotes the line as nmcli printed it, so you can match it against your terminal.
Error: Connection activation failed: Activation failed because the device is unmanaged
This is the Ubuntu Server default from Step 2. The profile saved correctly, which is why nmcli printed “successfully added” a moment earlier, but the global unmanaged rule blocks activation. Create the empty override file in /etc/NetworkManager/conf.d and restart NetworkManager. If the device is a physical NIC that netplan assigns to systemd-networkd, it stays unmanaged by design until you change the netplan renderer.
Error: Device ‘dummy0’ not found
You get this from nmcli device show when a profile for a virtual device exists but has never activated. NetworkManager creates dummy, VLAN, bridge and bond devices only when it brings the profile up, so on Ubuntu this error follows the unmanaged error above. Fix the activation and the device appears.
“Wired connection 1” appears on every new NIC
NetworkManager creates this automatic profile for any ethernet device it manages that has no profile of its own. Deleting it works for that device, because NetworkManager records it in /var/lib/NetworkManager/no-auto-default.state and does not create the profile again. The next NIC gets a fresh one, so on servers where another daemon owns the wired ports, set no-auto-default=* in the [main] section as in Step 3 and mark those NICs unmanaged.
Error: Connection activation failed: IP configuration could not be reserved (no available address, timeout, etc.)
The link came up but no address arrived before the activation timeout. In our case the WPA2 handshake had already succeeded, so the passphrase was fine and the access point simply had no DHCP server. Check the DHCP server on that network, or set a static address on the profile.
Error: No network with SSID ‘LabNet’ found.
The network is not in the cached scan results, either because it is out of range or because it appeared after the last scan. Run sudo nmcli device wifi rescan, wait a few seconds and list again before you suspect the radio. On our lab host the access point started seconds after NetworkManager, and this error went away after one forced rescan.
DNS servers in the profile are ignored
When a profile gets an address over DHCP, the DHCP-supplied servers are added alongside yours. Set ipv4.ignore-auto-dns yes to use only the servers you listed, re-activate the profile and check with resolvectl dns eth0. The /etc/resolv.conf file only ever shows 127.0.0.53, so it cannot answer this question. Our guide to checking the upstream DNS server with systemd-resolved covers the resolver side.
nmcli, netplan or systemd-networkd on a server
After running all three on the same two VMs, the choice comes down to how often the network of the host changes and who else edits it. A server that never moves gains nothing from a second daemon, while a host that joins VPNs and WiFi networks gains a lot from nmcli:
| Situation | What we would run | Why |
|---|---|---|
| Ubuntu server with a fixed address | netplan with systemd-networkd | One YAML file, applied at boot, no extra daemon. See static IP on Ubuntu 26.04 with netplan |
| Ubuntu host that needs VPNs, WiFi or frequent changes | NetworkManager, renderer set in netplan | nmcli changes persist as netplan YAML, so both tools stay in sync |
| Debian server from the netinst ISO | ifupdown, NetworkManager only for extra devices | NetworkManager ignores interfaces listed in /etc/network/interfaces |
| Debian 13 cloud image | systemd-networkd on eth0, NetworkManager for the rest | Avoids the double DHCP lease from Step 3 |
| Fleet managed by Ansible or cloud-init | netplan or keyfiles from templates | Text files diff cleanly; interactive nmcli edits drift |
Whichever you pick, give each interface exactly one owner and check it with nmcli device status and networkctl list together. A device that one tool reports as connected and the other as configured is the misconfiguration that causes most of the problems above. For the other nmcli jobs on the same hosts, see how to change the hostname with nmcli, connect to an OpenVPN server with nmcli and manage Ubuntu and Debian networking with netplan. The nmcli reference lists every property used here.
On Raspberry Pi with network-manager version 1.42.0-1 and wanted to upgrade to this bleeding edge one one.. https://github.com/NetworkManager/NetworkManager but they didn’t explain how to compile/install