Skip to content
Français
Account: not signed in, sync available My learning
Select theme
Français

Configure the network with Netplan

By updated

Improve this page

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 (networkd or NetworkManager) 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 try and its automatic rollback.
  • Check each action with ip, resolvectl and netplan 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:

Terminal window
ip -br link

The 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.112

Each 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, networkd on a server.
  • ethernets: the family of physical interfaces; the enp3s0 key is the name of the interface.
  • addresses: the IP address and its mask in CIDR notation (/24).
  • routes with to: 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.

Terminal window
sudo chown root:root /etc/netplan/99-static.yaml
sudo chmod 600 /etc/netplan/99-static.yaml
ls -l /etc/netplan/99-static.yaml

The 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.

Terminal window
sudo netplan try

The 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:

Terminal window
sudo netplan try --timeout 60

Once 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.

Terminal window
sudo netplan apply

Check 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:

Terminal window
ip -br addr show enp3s0

The 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:

Terminal window
ip route show default

You 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:

Terminal window
resolvectl status enp3s0

The 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.

CommandWhat it doesWhen to use it
netplan generateTranslates the YAML into backend files under /run/Validate the syntax outside any try sequence (see the warning below)
netplan tryApplies with automatic rollbackAny remote change
netplan applyApplies for good, with no netLocal console, trivial change
netplan getShows the merged configuration of all filesUnderstand which of two files wins
netplan statusShows the real state of the interfacesCheck after applying

netplan generate parses your YAML and fails on a syntax error without reconfiguring a single interface. It is a convenient dry run.

Terminal window
sudo netplan generate

No 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:

Terminal window
systemctl is-active systemd-networkd NetworkManager

The 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:

Terminal window
sudo netplan get

The 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: true

After 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::9

Netplan 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: 100

Check 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/24

The 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:
- enp3s0

The 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 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: 100

The 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:

Terminal window
cat /proc/net/bonding/bond0

The 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: true

The 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.

SymptomProbable causeFix
netplan generate returns a parsing errorTab or invalid indentation in the YAMLReplace every tab with spaces, run sudo netplan generate again
Permissions for /etc/netplan/... are too openFile readable by other userssudo chmod 600 /etc/netplan/*.yaml
The configuration applies without error but the IP does not changeA file with a higher alphabetical name (often 50-cloud-init.yaml) redefines the interfacesudo netplan get to see the merge, rename your file with 99-
netplan apply fails on Unit NetworkManager.service not foundrenderer: NetworkManager on a machine without NetworkManagersystemctl is-active systemd-networkd NetworkManager, align the renderer
Neighbour ping OK, Internet KODefault route missing or wrong gatewayip route show default, fix routes: - to: default
Deprecation warning at applygateway4 or gateway6 still presentMigrate to routes: - to: default, via: ...
SSH access lost after a changenetplan apply used instead of netplan tryTake 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 nmcli on RHEL, nor /etc/network/interfaces on a classically installed Debian.
  • Netplan configures nothing itself: it generates the configuration of systemd-networkd (servers) or of NetworkManager (workstations), named by the renderer key.
  • netplan try rolls back automatically after 120 seconds without confirmation: it is the only safe move remotely. netplan apply has no rollback.
  • Never run netplan generate right before netplan try: it rewrites /run/systemd/network/, that is what the rollback restores, and the net then brings nothing back.
  • netplan generate validates the YAML syntax without touching the network, and writes under /run/systemd/network/ or /run/NetworkManager/system-connections/, never under /etc/NetworkManager/system-connections/.
  • gateway4 and gateway6 are deprecated since Netplan 0.103: use routes: - 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 with netplan 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 default and resolvectl 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

6 questions
6 min
70% to pass

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

Is this project useful to you?

The guides, courses, quizzes and labs stay free. If you use them regularly, you can contribute to their upkeep and development.

Become a supporting member (new tab) One-time support (new tab) Learn more

Follow the project on LinkedIn