Netplan describes the network configuration of an Ubuntu machine in a YAML file placed under /etc/netplan/, then translates it for the service that actually drives the interfaces: systemd-networkd on a server, NetworkManager on a workstation. This guide shows you how to set a static IP address, a VLAN, a bridge, a bond or a static route, how to apply them without losing your SSH session thanks to netplan try, and how to check each step. It is written for administrators comfortable with the Linux command line.
What you will learn
- Identify the active backend (
networkdorNetworkManager) before writing a single line of configuration. - Write a valid Netplan file: static address, DHCP, routes, DNS servers.
- Apply a change without cutting your remote access, with
netplan tryand its automatic rollback. - Check each action with
ip,resolvectlandnetplan status. - Adapt the configuration to the common cases: VLAN, bridge, LACP bonding, Wi-Fi.
- Diagnose the classic failures: invalid YAML, overridden file, permissions too open.
First example: a static IP address
The most frequent case on a server: replace the DHCP address inherited from the installation with a static address. Start by noting the real name of your interface, because Ubuntu's modern names (enp3s0, ens18) no longer look like the old eth0 of tutorials:
ip -br linkThe output lists the interfaces and their state (UP or DOWN). Remember the name of the one that connects you to the network, it will serve as the YAML key.
Then create /etc/netplan/99-static.yaml. The 99- prefix guarantees that it is read after the 50-cloud-init.yaml file written by the installer, so that its values win:
network: version: 2 renderer: networkd ethernets: enp3s0: dhcp4: false addresses: - 192.168.1.100/24 routes: - to: default via: 192.168.1.1 nameservers: addresses: - 9.9.9.9 - 149.112.112.112Each block has a precise role, and it is this grammar you will reuse everywhere afterwards:
version: 2: the version of the Netplan format, the only one in use today.renderer: the backend that will run the configuration,networkdon a server.ethernets: the family of physical interfaces; theenp3s0key is the name of the interface.addresses: the IP address and its mask in CIDR notation (/24).routeswithto: default: the default gateway, that is the route taken by all traffic leaving the local network.nameservers: the DNS resolvers queried by the machine.
Protect the file before anything else: sooner or later it will contain a Wi-Fi password or a key, and Netplan flags permissions that are too broad every time it reads the file.
sudo chown root:root /etc/netplan/99-static.yamlsudo chmod 600 /etc/netplan/99-static.yamlls -l /etc/netplan/99-static.yamlThe output must show -rw------- 1 root root. Any other value triggers the warning Permissions for /etc/netplan/... are too open. Netplan configuration should NOT be accessible by others. at every netplan generate or netplan apply. It is only a warning: the configuration is applied anyway, and the file stays readable by everyone until you fix it.
Apply without cutting your SSH access
This is the critical point of this page. A gateway error or a badly set mask and your SSH session dies on the spot, on a machine sometimes located hundreds of kilometres away. Netplan provides exactly the safeguard that prevents this: netplan try.
sudo netplan tryThe command applies the configuration, then waits for your confirmation. If you do not press Enter within the allotted time, it automatically restores the previous configuration: your SSH session being dead, you confirm nothing, and the machine comes back to a reachable state on its own. The default delay is 120 seconds, adjustable with --timeout:
sudo netplan try --timeout 60Once the new configuration is confirmed through netplan try, it is already active and persistent. netplan apply is for the cases where you are on the local console or sure of yourself: it applies immediately, with no rollback net.
sudo netplan applyCheck the result
Applying is not enough: you must prove that the desired state is in place. Three commands cover the essentials, from the interface up to name resolution. First check the address and the state of the interface:
ip -br addr show enp3s0The output must contain UP and the address 192.168.1.100/24. If the expected address is missing, the configuration was not taken into account, or another file of /etc/netplan/ overrode it.
Then check the default route, the one that conditions any exit to the Internet:
ip route show defaultYou must read default via 192.168.1.1 dev enp3s0. A missing or wrong gateway gives a machine that pings its neighbour but nothing beyond.
Finally check DNS resolution, managed by systemd-resolved when the renderer is networkd:
resolvectl status enp3s0The DNS Servers: line must list your resolvers. On Ubuntu 24.04 LTS, the netplan status --all command offers a summary view (interfaces, addresses, routes, DNS) and netplan status --diff reports the differences between the real state of the system and your YAML files.
The Netplan commands to know
Netplan exposes few commands, and knowing which one does what spares you manipulating files blindly. They fall into two families: those that transform your YAML into backend configuration, and those that help you read the current state.
| Command | What it does | When to use it |
|---|---|---|
netplan generate | Translates the YAML into backend files under /run/ | Validate the syntax outside any try sequence (see the warning below) |
netplan try | Applies with automatic rollback | Any remote change |
netplan apply | Applies for good, with no net | Local console, trivial change |
netplan get | Shows the merged configuration of all files | Understand which of two files wins |
netplan status | Shows the real state of the interfaces | Check after applying |
netplan generate parses your YAML and fails on a syntax error without reconfiguring a single interface. It is a convenient dry run.
sudo netplan generateNo output means the syntax is valid. The produced files land in volatile directories, regenerated at every boot.
When you debug, know where to look. The generated files live under /run/, never under /etc/: /run/systemd/network/ for systemd-networkd, and /run/NetworkManager/system-connections/ for NetworkManager. The /etc/NetworkManager/system-connections/ directory holds the connections specific to NetworkManager, created outside Netplan: looking for your generated files there would send you down a false trail. Nothing under /run/ must be edited by hand, everything there is overwritten at the next netplan generate.
Understand the two backends
Netplan configures nothing itself: it generates the configuration of another service, called the renderer (backend). Two exist, and picking the wrong one breaks the network the moment you apply.
systemd-networkd is the backend of servers, Ubuntu Server in particular. Minimalist and integrated into systemd, it suits static interfaces that do not change between two reboots. It is the renderer: networkd value.
NetworkManager is the backend of workstations (Ubuntu Desktop and graphical derivatives). It handles Wi-Fi, VPNs, mobile networks and interfaces that come and go. It is the renderer: NetworkManager value, the natural choice for wifis: configurations on a desktop.
Check which one really runs before writing your renderer:
systemctl is-active systemd-networkd NetworkManagerThe command returns one line per service: active for the one that drives the network, inactive for the other. Declaring renderer: NetworkManager on a server where NetworkManager is not installed makes netplan apply fail with Failed to start NetworkManager.service: Unit NetworkManager.service not found. followed by a Python traceback, and the interface loses its configuration along the way: networkd let go of the interface, and nobody picks it up. Over SSH, the cut is guaranteed; netplan try, on the other hand, brings you back to the previous state.
File layout and order of application
Every file of /etc/netplan/ ending with .yaml is read, then merged in the alphabetical order of their names. Hence the convention of numeric prefixes: 50-cloud-init.yaml (written by the installer or cloud-init, in French) is read before 99-static.yaml, and for an identical key, the last one read wins.
This rule explains the most baffling outage for a beginner: a correct configuration, applied without error, and yet with no effect, because a file with a higher name redefines the same interface. To see the configuration actually retained after merging:
sudo netplan getThe output is the consolidated YAML, all files together. If the address you read there is not yours, another file takes precedence: rename yours with a higher prefix, or fix the faulty file.
Typical configurations
The following blocks reuse the same grammar, simply changing the family of interfaces declared under network:. Adapt the interface names to those noted with ip -br link: enp3s0 is an example, not a universal value. Each example is followed by its check command.
DHCP, the minimal configuration
On a network where a DHCP server hands out addresses, the declaration fits in one useful line. It is the case of client workstations and of many virtual machines:
network: version: 2 renderer: networkd ethernets: enp3s0: dhcp4: trueAfter sudo netplan try, check that the DHCP lease was obtained with ip -br addr show enp3s0: an address must appear, and ip route show default must display the gateway announced by the DHCP server.
IPv6, dynamic and static
IPv6 follows exactly the same grammar as IPv4, which limits the learning effort. In dynamic mode, dhcp6: true asks the network for an address; in static mode, you set the address and its prefix length (/64), then the default route:
network: version: 2 renderer: networkd ethernets: enp3s0: dhcp6: false addresses: - 2001:db8:85a3::8a2e:370:7334/64 routes: - to: default via: 2001:db8:85a3::1 nameservers: addresses: - 2620:fe::fe - 2620:fe::9Netplan infers the address family from the value of via: the same routes: key serves IPv4 and IPv6. Check with ip -6 route show default, which must display the IPv6 gateway on the right interface.
Additional static routes
A static route sends a precise network to a gateway other than the default one, typically an internal network reachable through a dedicated router. You then stack several entries under routes:, the metric key setting the priority when two routes overlap (the lowest wins):
network: version: 2 renderer: networkd ethernets: enp3s0: addresses: - 192.168.1.100/24 routes: - to: default via: 192.168.1.1 - to: 10.20.0.0/16 via: 192.168.1.254 metric: 100Check with ip route show, which must list both the default route and the 10.20.0.0/16 via 192.168.1.254 line. A missing route almost always comes from a gateway outside the subnet of the interface: via must be directly reachable.
VLAN
A VLAN (virtual local area network, 802.1Q standard) carries several logical networks over a single cable, each frame bearing a numbered tag. On the Netplan side, you declare the physical interface, then a virtual interface with its id and its link:
network: version: 2 renderer: networkd ethernets: enp3s0: dhcp4: false vlans: vlan30: id: 30 link: enp3s0 addresses: - 192.168.30.10/24The id key carries the VLAN tag (from 0 to 4094, netplan generate refuses 4095 with allowed values are 0 to 4094) and link names the carrying physical interface, which deliberately stays without an address. The switch port on the other side must be configured in "tagged" mode for this VLAN, otherwise the frames are dropped. Check with ip -d link show vlan30: the output must mention vlan protocol 802.1Q id 30.
Network bridge
A bridge makes several interfaces behave like a single software switch. It is the foundation of virtualisation: virtual machines plug into it and appear directly on the physical network. The physical interface is declared without an address, because the bridge carries the IP:
network: version: 2 renderer: networkd ethernets: enp3s0: dhcp4: false dhcp6: false bridges: br0: dhcp4: true interfaces: - enp3s0The enp3s0 interface is added to the bridge through the interfaces: list, and br0 gets the address over DHCP. Leaving an address on enp3s0 is the classic mistake: traffic then leaves through the wrong interface. Check with ip -br addr show br0 (the address must be on br0, not on enp3s0) then bridge link show, which must list enp3s0 as a member.
Bonding (link aggregation)
Bonding aggregates several network cards into a single logical link, for fault tolerance or to add up bandwidth. The choice of mode is the structuring decision, because it determines what must be configured on the switch side:
network: version: 2 renderer: networkd ethernets: eno1: dhcp4: false eno2: dhcp4: false bonds: bond0: interfaces: - eno1 - eno2 addresses: - 192.168.1.100/24 routes: - to: default via: 192.168.1.1 nameservers: addresses: [9.9.9.9, 149.112.112.112] parameters: mode: 802.3ad lacp-rate: fast mii-monitor-interval: 100The 802.3ad mode is LACP aggregation: both links are active at the same time, which adds up their throughput and provides failover if one of them drops. It requires the switch to be configured for LACP on the other side, otherwise the link does not come up. The active-backup mode, on the contrary, keeps a single interface active and fails over to the other one on a fault: it needs no switch configuration, but does not add up throughput. mii-monitor-interval: 100 sets the frequency (in milliseconds) at which the physical links are monitored.
Check the real state of the bond in the kernel:
cat /proc/net/bonding/bond0The output must show the negotiated mode and the up status of each slave. With LACP badly configured on the switch side, you will see the ports stay inactive.
Wi-Fi
On a workstation, the Wi-Fi configuration is declared with the NetworkManager renderer, which already manages the Wi-Fi of the graphical interface. On a server without NetworkManager, renderer: networkd works too: Netplan then generates a netplan-wpa-wlan0.service service that starts wpa_supplicant (package to install). In both cases, you declare the SSID and its key under access-points::
network: version: 2 renderer: NetworkManager wifis: wlan0: access-points: "MySSID": password: "wifipassword" dhcp4: trueThe access-points key associates the network name with its parameters, here a simple WPA password. That password is stored in clear text in the file: the 600 permissions seen above are not a whim. Check the association with nmcli device wifi list, where your SSID must appear with an asterisk, then ip -br addr show wlan0 for the obtained address.
Security and points of attention
The network configuration is an exposure point: it decides what the machine can reach and what can reach it. Three reflexes reduce the risk at no cost. First the permissions: chmod 600 on every file of /etc/netplan/, because they carry Wi-Fi secrets and reveal your addressing plan to any local user.
Next the rollback: before any remote change, keep a fallback access (cloud console, KVM over IP) and go through netplan try. This pair is what separates a reversible change from an on-site trip.
Finally persistence: a Netplan change must survive a reboot. Since the configuration lives under /etc/netplan/, it is replayed at boot, but nothing replaces the real check. After a reboot of the machine, run ip -br addr show and ip route show default again: you must find exactly the expected state. A server that loses its address at reboot most often comes from an unsaved /etc/netplan/ file or a conflict with 50-cloud-init.yaml.
Troubleshooting
Netplan failures look very much alike and are diagnosed quickly, provided you know where to look. This table covers the most frequent symptoms in production; read it from top to bottom, from the most common to the most subtle.
| Symptom | Probable cause | Fix |
|---|---|---|
netplan generate returns a parsing error | Tab or invalid indentation in the YAML | Replace every tab with spaces, run sudo netplan generate again |
Permissions for /etc/netplan/... are too open | File readable by other users | sudo chmod 600 /etc/netplan/*.yaml |
| The configuration applies without error but the IP does not change | A file with a higher alphabetical name (often 50-cloud-init.yaml) redefines the interface | sudo netplan get to see the merge, rename your file with 99- |
netplan apply fails on Unit NetworkManager.service not found | renderer: NetworkManager on a machine without NetworkManager | systemctl is-active systemd-networkd NetworkManager, align the renderer |
| Neighbour ping OK, Internet KO | Default route missing or wrong gateway | ip route show default, fix routes: - to: default |
| Deprecation warning at apply | gateway4 or gateway6 still present | Migrate to routes: - to: default, via: ... |
| SSH access lost after a change | netplan apply used instead of netplan try | Take back control from the console, then apply the netplan try rule |
When the table is not enough, the system logs give the exact cause. Query the backend concerned, journalctl -u systemd-networkd or journalctl -u NetworkManager, and run sudo netplan --debug apply to see each step of the rendering and the faulty file.
Where Netplan comes from
Netplan appeared in Ubuntu 17.10, at a time when the network configuration was split between /etc/network/interfaces (with the ifup and ifdown tools), NetworkManager and systemd-networkd, each with its own syntax. Canonical wanted a single description of the network, independent of the service that runs it, which greatly helped the rise of cloud images: cloud-init produces Netplan YAML, without caring about the backend of the target machine. That is the whole point of the tool, and also its limit, since this unification stops at Ubuntu's borders.
Put it into practice
Configure yourself a persistent static IP and route with netplan on a VM, then check the connectivity. A drill under exam conditions takes up the exercise again without hints, on RHEL or Ubuntu.
Key points
- Netplan is the default tool of Ubuntu: it replaces neither
nmclion RHEL, nor/etc/network/interfaceson a classically installed Debian. - Netplan configures nothing itself: it generates the configuration of systemd-networkd (servers) or of NetworkManager (workstations), named by the
rendererkey. netplan tryrolls back automatically after 120 seconds without confirmation: it is the only safe move remotely.netplan applyhas no rollback.- Never run
netplan generateright beforenetplan try: it rewrites/run/systemd/network/, that is what the rollback restores, and the net then brings nothing back. netplan generatevalidates the YAML syntax without touching the network, and writes under/run/systemd/network/or/run/NetworkManager/system-connections/, never under/etc/NetworkManager/system-connections/.gateway4andgateway6are deprecated since Netplan 0.103: useroutes: - to: default, identical in IPv4 and IPv6.- The files of
/etc/netplan/are merged in alphabetical order: for a configuration with no effect, look for the file that overrides yours withnetplan get. - Permissions 600 and owner root are a must: these files contain Wi-Fi passwords in clear text.
- After each change, check with
ip -br addr,ip route show defaultandresolvectl status, then test again after a reboot.
Knowledge check
Check that the essentials of this guide stuck. The questions cover only what has just been explained here.
Knowledge check
Check what you have learned with this interactive quiz
How it works
- The timer starts when you click Start
- Multiple choice, true/false and short answer questions
- You can move between questions
- Detailed results are shown at the end
Starts the quiz and the timer
Review
(0/0)Score by domain
A domain groups several guides and gets several questions, so its score is more reliable than a per-topic score, which often rests on a single question.
Summary
Strengths
No topic passed at 80% on at least two questions yet.
Weak areas
No topic below the pass mark.
Recommended next
Hints before you try again?
Continue the course: Configure the network with NetworkManager
A new full quiz with random questions
Work again only on the questions you missed