↓ Skip to main content
  1. Linux Articles/
  2. Ubuntu 26.04 LTS Server/

Configuring the Network on Ubuntu 26.04 LTS Server (Netplan)

Table of Contents

Configuring the Network with Netplan

Ubuntu configures networking with Netplan. It reads YAML files from /etc/netplan/ and hands the work to a backend (the renderer).

The renderers are systemd-networkd and NetworkManager. The Server edition defaults to systemd-networkd and the Desktop edition to NetworkManager. This article covers the Server edition.

Static addresses, DHCP, IPv6 autoconfiguration from router advertisements and DHCPv6 are each explained together with the result of talking to a real router.

Reading the Current Settings

The ip command shows interfaces and addresses. -br (brief) prints one line each.

Commands to read the addresses
ip -br a
ip a show [INTERFACE]
Example: reading the addresses
kazulog@sv1:~$ ip -br a
lo               UNKNOWN        127.0.0.1/8 ::1/128
ens2             UP             10.19.12.11/16 fe80::5054:ff:fedc:e2c5/64 
ens3             UP             192.168.100.100/24 metric 1024 2001:db8:100:0:5054:ff:feba:7498/64 fe80::5054:ff:feba:7498/64 
kazulog@sv1:~$ ip a show ens3
3: ens3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether 52:54:00:ba:74:98 brd ff:ff:ff:ff:ff:ff
    altname enp0s3
    altname enx525400ba7498
    inet 192.168.100.100/24 metric 1024 brd 192.168.100.255 scope global dynamic ens3
       valid_lft 2319sec preferred_lft 2319sec
    inet6 2001:db8:100:0:5054:ff:feba:7498/64 scope global dynamic mngtmpaddr noprefixroute 
       valid_lft 2591997sec preferred_lft 604797sec
    inet6 fe80::5054:ff:feba:7498/64 scope link proto kernel_ll 
       valid_lft forever preferred_lft forever
kazulog@sv1:~$

Routes and name resolution come from ip route and resolvectl status.

Example: reading the routes
kazulog@sv1:~$ ip route
default via 10.19.0.1 dev ens2 proto static
default via 192.168.100.1 dev ens3 proto dhcp src 192.168.100.100 metric 1024 
10.19.0.0/16 dev ens2 proto kernel scope link src 10.19.12.11 
192.168.100.0/24 dev ens3 proto kernel scope link src 192.168.100.100 metric 1024 
192.168.100.1 dev ens3 proto dhcp scope link src 192.168.100.100 metric 1024 
kazulog@sv1:~$ ls -l /etc/netplan/
total 4
-rw------- 1 root root 243 Sep 11 11:59 50-cloud-init.yaml
kazulog@sv1:~$

netplan status shows the state as Netplan sees it, including where each address came from (static, DHCP or a router advertisement).

Command to read Netplan's view
sudo netplan status --all
Example: Netplan's view
kazulog@sv1:~$ sudo netplan status --all 2>&1 | head -30
     Online state: online
    DNS Addresses: 127.0.0.53 (stub)
       DNS Search: kazulog.example

●  1: lo ethernet UNKNOWN/UP (unmanaged)
      MAC Address: 00:00:00:00:00:00
        Addresses: 127.0.0.1/8
                   ::1/128

●  2: ens2 ethernet UP (networkd: ens2)
      MAC Address: 52:54:00:dc:e2:c5 (Red Hat, Inc.)
        Addresses: 10.19.12.11/16
                   fe80::5054:ff:fedc:e2c5/64 (link)
    DNS Addresses: 10.1.0.1
                   10.1.0.2
           Routes: default via 10.19.0.1 (static)
                   10.19.0.0/16 from 10.19.12.11 (link)
                   fe80::/64 metric 256

●  3: ens3 ethernet UP (unmanaged)
      MAC Address: 52:54:00:ba:74:98 (Red Hat, Inc.)
        Addresses: 192.168.100.100/24 (dynamic, dhcp)
                   2001:db8:100:0:5054:ff:feba:7498/64 (dynamic, ra)
                   fe80::5054:ff:feba:7498/64 (link)
    DNS Addresses: 192.168.100.1
                   2001:db8:100::1
       DNS Search: kazulog.example
           Routes: default via 192.168.100.1 from 192.168.100.100 metric 1024 (dhcp)
                   192.168.100.0/24 from 192.168.100.100 metric 1024 (link)
                   192.168.100.1 from 192.168.100.100 metric 1024 (dhcp, link)

An interface Netplan does not manage may still hold an address. Above, ens3 is marked (unmanaged) yet has a DHCP address, because a fallback configuration created during early boot (initramfs) is still in place. What you see depends on the environment.

Example: the fallback configuration
kazulog@sv1:~$ networkctl status ens3 | head -20
● 3: ens3
                   Link File: /usr/lib/systemd/network/99-default.link
                Network File: /run/systemd/network/zzzz-dracut-default.network
                       State: routable (configured)
                Online state: online
                        Type: ether
                        Path: pci-0000:00:03.0
                      Driver: virtio_net
                      Vendor: Red Hat, Inc.
                       Model: Virtio network device
           Alternative Names: enp0s3
                              enx525400ba7498
            Hardware Address: 52:54:00:ba:74:98
                         MTU: 1500 (min: 68, max: 65535)
                       QDisc: pfifo_fast
IPv6 Address Generation Mode: eui64
    Number of Queues (Tx/Rx): 1/1
            Auto negotiation: no
                     Address: 192.168.100.100 (DHCPv4 via 192.168.100.1)
                              2001:db8:100:0:5054:ff:feba:7498
kazulog@sv1:~$ ls /run/systemd/network/
10-netplan-ens2.network  zzzz-dracut-default.network
kazulog@sv1:~$

Network File points at /run/systemd/network/zzzz-dracut-default.network. Once Netplan configures the interface, it generates 10-netplan-*.network and that file is used instead.

How the Configuration Files Are Organised

Configuration lives in /etc/netplan/. A file created by the installer or by cloud-init is usually there already, and when several files exist they are read in name order, with later files winning.

FileOrigin
50-cloud-init.yamlWritten by cloud-init (cloud images)
00-installer-config.yamlWritten by the installer (normal installations)
60-*.yaml and similarAdded by the administrator
Example: the existing configuration file
kazulog@sv1:~$ sudo cat /etc/netplan/50-cloud-init.yaml
network:
  version: 2
  ethernets:
    ens2:
      addresses:
      - "10.19.12.11/16"
      nameservers:
        addresses:
        - 10.1.0.1
        - 10.1.0.2
      dhcp4: false
      routes:
      - to: "default"
        via: "10.19.0.1"
kazulog@sv1:~$

Set the permissions of configuration files to 600. Netplan warns otherwise, because these files may contain passwords.

Example: the warning for loose permissions
kazulog@sv1:~$ sudo chmod 644 /etc/netplan/60-ens3.yaml
kazulog@sv1:~$ sudo netplan generate
** (configure:3014): WARNING **: 13:00:58.443: Permissions for /etc/netplan/60-ens3.yaml are too open. Netplan configuration should NOT be accessible by others.
kazulog@sv1:~$ sudo chmod 600 /etc/netplan/60-ens3.yaml

Setting a Static IPv4 Address

Create a new file for your settings.

Commands to create the configuration file
sudo vi /etc/netplan/60-[NAME].yaml
sudo chmod 600 /etc/netplan/60-[NAME].yaml
A static IPv4 configuration
network:
  version: 2
  ethernets:
    ens3:
      dhcp4: false
      addresses:
        - 192.168.100.10/24
      routes:
        - to: default
          via: 192.168.100.1
          metric: 200
      nameservers:
        addresses: [192.168.100.1]
        search: [kazulog.example]
KeyMeaning
ethernetsSection for wired interfaces
ens3The interface being configured
dhcp4Whether to obtain an address by DHCP
addressesAddress and prefix length (CIDR notation)
routesRoutes. to: default is the default route and via the next hop
metricRoute preference. Lower wins
nameservers.addressesDNS servers
nameservers.searchSearch domain, so ping www resolves www.kazulog.example

routes takes per-destination entries as well as the default route. Selection by metric, on-link, IPv6 routes and policy routing are covered in Static Routes (Netplan).

Applying the Configuration

Check the syntax with netplan generate first. Errors are reported with a line number.

Commands to check and apply
sudo netplan generate
sudo netplan apply
Example: a syntax error
kazulog@sv1:~$ sudo netplan generate
/etc/netplan/99-broken.yaml:5:18: Error in network definition: expected sequence
      addresses: 192.168.100.10/24
                 ^
kazulog@sv1:~$ echo exit=$?
exit=1
kazulog@sv1:~$

When it is clean, apply it with netplan apply.

Example: creating and applying the configuration
kazulog@sv1:~$ sudo cp /tmp/60-ens3.yaml /etc/netplan/60-ens3.yaml && sudo chmod 600 /etc/netplan/60-ens3.yaml
kazulog@sv1:~$ sudo cat /etc/netplan/60-ens3.yaml
network:
  version: 2
  ethernets:
    ens3:
      dhcp4: false
      addresses:
        - 192.168.100.10/24
      routes:
        - to: default
          via: 192.168.100.1
          metric: 200
      nameservers:
        addresses: [192.168.100.1]
        search: [kazulog.example]
kazulog@sv1:~$ sudo netplan generate
kazulog@sv1:~$ echo $?
0
kazulog@sv1:~$ sudo netplan apply
kazulog@sv1:~$ ip a show ens3
3: ens3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether 52:54:00:ba:74:98 brd ff:ff:ff:ff:ff:ff
    altname enp0s3
    altname enx525400ba7498
    inet 192.168.100.10/24 brd 192.168.100.255 scope global ens3
       valid_lft forever preferred_lft forever
    inet6 fe80::5054:ff:feba:7498/64 scope link proto kernel_ll 
       valid_lft forever preferred_lft forever
kazulog@sv1:~$ ip route
default via 10.19.0.1 dev ens2 proto static
default via 192.168.100.1 dev ens3 proto static metric 200 
10.19.0.0/16 dev ens2 proto kernel scope link src 10.19.12.11 
192.168.100.0/24 dev ens3 proto kernel scope link src 192.168.100.10 

A mistake made over a remote session can lock you out. netplan try rolls back automatically unless you confirm within a time limit. Check that your connection survives, then press Enter to keep the change.

Command to apply safely
sudo netplan try

Checking Connectivity

Confirm that the new address reaches the router and another server.

Example: checking connectivity
kazulog@sv1:~$ ping -c 3 192.168.100.1
PING 192.168.100.1 (192.168.100.1) 56(84) bytes of data.
64 bytes from 192.168.100.1: icmp_seq=1 ttl=255 time=1.42 ms
64 bytes from 192.168.100.1: icmp_seq=2 ttl=255 time=1.62 ms
64 bytes from 192.168.100.1: icmp_seq=3 ttl=255 time=1.59 ms

--- 192.168.100.1 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2004ms
rtt min/avg/max/mdev = 1.417/1.544/1.622/0.090 ms
kazulog@sv1:~$ ping -c 3 192.168.100.20
PING 192.168.100.20 (192.168.100.20) 56(84) bytes of data.
64 bytes from 192.168.100.20: icmp_seq=1 ttl=64 time=1.61 ms
64 bytes from 192.168.100.20: icmp_seq=2 ttl=64 time=1.86 ms
64 bytes from 192.168.100.20: icmp_seq=3 ttl=64 time=1.73 ms

--- 192.168.100.20 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2003ms
rtt min/avg/max/mdev = 1.612/1.734/1.862/0.102 ms
kazulog@sv1:~$

Afterwards netplan status also changes, showing that the interface is now managed by Netplan (networkd: ens3).

Obtaining an Address by DHCP

A DHCP configuration
network:
  version: 2
  ethernets:
    ens3:
      dhcp4: true
      dhcp6: true
      accept-ra: true
Example: obtaining an address by DHCP
kazulog@sv1:~$ sudo cat /etc/netplan/60-ens3.yaml
network:
  version: 2
  ethernets:
    ens3:
      dhcp4: true
      dhcp6: true
      accept-ra: true
kazulog@sv1:~$ sudo netplan apply
kazulog@sv1:~$ ip a show ens3
3: ens3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether 52:54:00:ba:74:98 brd ff:ff:ff:ff:ff:ff
    altname enp0s3
    altname enx525400ba7498
    inet 192.168.100.102/24 metric 100 brd 192.168.100.255 scope global dynamic ens3
       valid_lft 3584sec preferred_lft 3584sec
    inet6 2001:db8:100:0:5054:ff:feba:7498/64 scope global dynamic mngtmpaddr noprefixroute 
       valid_lft 2591998sec preferred_lft 604798sec
    inet6 fe80::5054:ff:feba:7498/64 scope link proto kernel_ll 
       valid_lft forever preferred_lft forever
kazulog@sv1:~$ ip route show dev ens3
default via 192.168.100.1 proto dhcp src 192.168.100.102 metric 100
192.168.100.0/24 proto kernel scope link src 192.168.100.102 metric 100 
192.168.100.1 proto dhcp scope link src 192.168.100.102 metric 100 
kazulog@sv1:~$ resolvectl status ens3 | head -8
Link 3 (ens3)
    Current Scopes: DNS
         Protocols: +DefaultRoute -LLMNR -mDNS -DNSOverTLS DNSSEC=no/unsupported
       DNS Servers: 192.168.100.1 2001:db8:100::1
        DNS Domain: kazulog.example
     Default Route: yes

Besides the address, the default route, the DNS servers and the search domain all come from DHCP. ip a marks the address dynamic and shows a valid_lft.

The router that handed it out can be inspected as well.

The lease on the router (IOS XE)
R1#show ip dhcp binding
Bindings from all pools not associated with VRF:
IP address      Client-ID/ 		Lease expiration 	Type       State      Interface
		Hardware address/
		User name
192.168.100.102 ffb5.5e67.ff00.0200.    Sep 11 2026 05:03 AM    Automatic  Active     GigabitEthernet2
                00ab.114a.b5bc.4a7e.
                5a3d.87

A capture shows the four DHCP messages (Discover, Offer, Request, ACK).

The DHCP exchange (tshark)
   11   1.688958      0.0.0.0 → 255.255.255.255 DHCP 333 DHCP Discover - Transaction ID 0xb6d08892
   12   1.692413 192.168.100.1 → 192.168.100.102 DHCP 366 DHCP Offer    - Transaction ID 0xb6d08892
   13   1.693148      0.0.0.0 → 255.255.255.255 DHCP 343 DHCP Request  - Transaction ID 0xb6d08892
   14   1.697570 192.168.100.1 → 192.168.100.102 DHCP 366 DHCP ACK      - Transaction ID 0xb6d08892
Download the pcap of the packet in the tshark output above (No.14 DHCP ACK)

Autoconfiguring IPv6 from Router Advertisements (SLAAC)

With IPv6, a host can build its address and default route from the router advertisements (RAs) a router sends periodically. Netplan controls this with accept-ra, which is enabled by default.

Accepting router advertisements
network:
  version: 2
  ethernets:
    ens3:
      dhcp4: false
      dhcp6: false
      accept-ra: true
      addresses:
        - 192.168.100.10/24
Example: autoconfiguration from a router advertisement
kazulog@sv1:~$ ip -6 a show ens3
3: ens3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    altname enp0s3
    altname enx525400ba7498
    inet6 2001:db8:100:0:5054:ff:feba:7498/64 scope global dynamic mngtmpaddr noprefixroute 
       valid_lft 2591995sec preferred_lft 604795sec
    inet6 fe80::5054:ff:feba:7498/64 scope link proto kernel_ll 
       valid_lft forever preferred_lft forever
kazulog@sv1:~$ ip -6 route show dev ens3
2001:db8:100::/64 proto ra metric 1024 expires 2591994sec pref medium
fe80::/64 proto kernel metric 256 pref medium
default nhid 3108948397 via fe80::5054:ff:fe92:855c proto ra metric 1024 expires 1794sec pref medium
kazulog@sv1:~$
What to look atMeaning
inet6 2001:db8:100:0:5054:ff:feba:7498/64An address built from the advertised prefix. The lower 64 bits come from the MAC address (52:54:00:ba:74:98)
dynamicMarks an autoconfigured address
valid_lft / preferred_lftThe lifetimes carried in the advertisement
2001:db8:100::/64 proto raRoute to the advertised prefix
default ... via fe80::... proto raThe default route, pointing at the router’s link-local address

networkctl status also reports how the address was built (IPv6 Address Generation Mode: eui64).

Example: the address generation mode
kazulog@sv1:~$ networkctl status ens3 | grep -A6 'Address:'
            Hardware Address: 52:54:00:ba:74:98
                         MTU: 1500 (min: 68, max: 65535)
                       QDisc: pfifo_fast
IPv6 Address Generation Mode: eui64
    Number of Queues (Tx/Rx): 1/1
            Auto negotiation: no
                     Address: 192.168.100.10
                              2001:db8:100:0:5054:ff:feba:7498
                              fe80::5054:ff:feba:7498
                     Gateway: 192.168.100.1
                              fe80::5054:ff:fe92:855c
                         DNS: 192.168.100.1
                              2001:db8:100::1
kazulog@sv1:~$ resolvectl status ens3 | head -8
Link 3 (ens3)
    Current Scopes: DNS
         Protocols: +DefaultRoute -LLMNR -mDNS -DNSOverTLS DNSSEC=no/unsupported
Current DNS Server: 2001:db8:100::1
       DNS Servers: 192.168.100.1 2001:db8:100::1
        DNS Domain: kazulog.example
     Default Route: yes

Inside a Router Advertisement

Capturing an advertisement shows everything the host needs.

A router advertisement (tshark -V), abridged
Internet Control Message Protocol v6
    Type: Router Advertisement (134)
    Code: 0
    Cur hop limit: 64
    Flags: 0x40, Other configuration, Prf (Default Router Preference): Medium
        0... .... = Managed address configuration: Not set
        .1.. .... = Other configuration: Set
    Router lifetime (s): 1800
    Reachable time (ms): 0
    Retrans timer (ms): 0
    ICMPv6 Option (Source link-layer address : 52:54:00:92:85:5c)
    ICMPv6 Option (MTU : 1500)
    ICMPv6 Option (Prefix information : 2001:db8:100::/64)
        Type: Prefix information (3)
        Length: 4 (32 bytes)
        Prefix Length: 64
        Flag: 0xc0, On-link Flag (L), Autonomous Address Configuration Flag (A)
            1... .... = On-link Flag (L): Set
            .1.. .... = Autonomous Address Configuration Flag (A): Set
        Valid Lifetime: 2592000 (30 days)
        Preferred Lifetime: 604800 (7 days)
        Prefix: 2001:db8:100::
Download the pcap of the packet in the tshark output above (No.1 Router Advertisement)
FieldMeaning
Autonomous Address Configuration Flag (A)Addresses may be built from this prefix. SLAAC works because this is set
Valid Lifetime / Preferred LifetimeBecome the valid_lft and preferred_lft of the address
Router lifetimeHow long the router may serve as a default route; shown as expires on the route
Managed address configuration (M)Whether to obtain the address from DHCPv6. Not set here
Other configuration (O)Obtain DNS and similar information from DHCPv6. Set here

Refusing Router Advertisements

With accept-ra: false, neither an address nor a default route is configured.

Example: with router advertisements refused
kazulog@sv1:~$ sudo cp /tmp/60-ens3-nora.yaml /etc/netplan/60-ens3.yaml && sudo chmod 600 /etc/netplan/60-ens3.yaml
kazulog@sv1:~$ sudo netplan apply
kazulog@sv1:~$ ip -6 a show ens3
3: ens3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    altname enp0s3
    altname enx525400ba7498
    inet6 fe80::5054:ff:feba:7498/64 scope link proto kernel_ll 
       valid_lft forever preferred_lft forever
kazulog@sv1:~$ ip -6 route show dev ens3
fe80::/64 proto kernel metric 256 pref medium

Only the link-local address remains.

Obtaining Information over DHCPv6

The advertisement above had Other configuration (O) set. In that case the address comes from SLAAC and only the extra information, such as DNS, comes from DHCPv6 (stateless DHCPv6).

The DHCPv6 exchange (tshark)
   18   3.156809 fe80::5054:ff:feba:7498 → ff02::1:2    DHCPv6 114 Information-request XID: 0xd2fc29
   20   3.162109 fe80::5054:ff:fe92:855c → fe80::5054:ff:feba:7498 DHCPv6 139 Reply XID: 0xd2fc29
Download the pcap of the packet in the tshark output above (No.20 DHCPv6 Reply)

The reply carries the DNS server and the search domain.

Inside the DHCPv6 Reply (tshark -V), abridged
    DNS recursive name server
        Option: DNS recursive name server (23)
        Length: 16
         1 DNS server address: 2001:db8:100::1
    Domain Search List
        Option: Domain Search List (24)
        Length: 17
        Domain name suffix search list
            List entry: kazulog.example.

To have DHCPv6 assign the address itself (stateful DHCPv6), set Managed address configuration (M) on the router and give the DHCPv6 server an address pool.

Setting a Static IPv6 Address

IPv6 addresses go in the same addresses list, and the default route is written as to: "::/0".

A static IPv6 configuration
network:
  version: 2
  ethernets:
    ens3:
      dhcp4: false
      dhcp6: false
      accept-ra: false
      addresses:
        - 192.168.100.10/24
        - 2001:db8:100::10/64
      routes:
        - to: default
          via: 192.168.100.1
          metric: 200
        - to: "::/0"
          via: 2001:db8:100::1
          metric: 200
      nameservers:
        addresses: [192.168.100.1, "2001:db8:100::1"]
        search: [kazulog.example]
Example: static IPv6 and connectivity
kazulog@sv1:~$ sudo cp /tmp/60-ens3-v6.yaml /etc/netplan/60-ens3.yaml && sudo chmod 600 /etc/netplan/60-ens3.yaml
kazulog@sv1:~$ sudo netplan apply
kazulog@sv1:~$ ip -6 a show ens3
3: ens3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    altname enp0s3
    altname enx525400ba7498
    inet6 2001:db8:100::10/64 scope global 
       valid_lft forever preferred_lft forever
    inet6 fe80::5054:ff:feba:7498/64 scope link proto kernel_ll 
       valid_lft forever preferred_lft forever
kazulog@sv1:~$ ip -6 route show dev ens3
2001:db8:100::/64 proto kernel metric 256 pref medium
fe80::/64 proto kernel metric 256 pref medium
default via 2001:db8:100::1 proto static metric 200 pref medium
kazulog@sv1:~$ ping6 -c 3 2001:db8:100::1
PING 2001:db8:100::1 (2001:db8:100::1) 56 data bytes
64 bytes from 2001:db8:100::1: icmp_seq=1 ttl=64 time=21.6 ms
64 bytes from 2001:db8:100::1: icmp_seq=2 ttl=64 time=3.29 ms
64 bytes from 2001:db8:100::1: icmp_seq=3 ttl=64 time=2.23 ms

--- 2001:db8:100::1 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2005ms
rtt min/avg/max/mdev = 2.226/9.040/21.606/8.895 ms
kazulog@sv1:~$ ping6 -c 2 2001:db8:100::20
PING 2001:db8:100::20 (2001:db8:100::20) 56 data bytes
64 bytes from 2001:db8:100::20: icmp_seq=1 ttl=64 time=3.53 ms
64 bytes from 2001:db8:100::20: icmp_seq=2 ttl=64 time=1.57 ms

--- 2001:db8:100::20 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1002ms
rtt min/avg/max/mdev = 1.573/2.553/3.534/0.980 ms

When the gateway lies outside the interface’s prefix (a VPS handing out a /128, for example), add on-link: true to the route to state that it is on the same link.

A gateway outside the prefix
      addresses:
        - "2001:db8::200/128"
      routes:
        - to: "::/0"
          via: "2001:db8::1"
          on-link: true

When the gateway is given as a link-local address (starting with fe80::), on-link is unnecessary because such a route always exists on the link.

Stopping cloud-init from Overwriting the Configuration

On cloud images cloud-init generates 50-cloud-init.yaml at boot, and it can overwrite what an administrator edited. Create the following file to stop it.

Command to disable cloud-init networking
printf 'network: {config: disabled}\n' | sudo tee /etc/cloud/cloud.cfg.d/99-disable-network-config.cfg
Example: the state after disabling it and rebooting
kazulog@sv1:~$ uptime -p
up 0 minutes
kazulog@sv1:~$ ls -l /etc/netplan/
total 8
-rw------- 1 root root 243 Sep 11 11:59 50-cloud-init.yaml
-rw------- 1 root root 449 Sep 11 13:05 60-ens3.yaml
kazulog@sv1:~$ ip -br a show ens3
ens3             UP             192.168.100.10/24 2001:db8:100::10/64 fe80::5054:ff:feba:7498/64
kazulog@sv1:~$

The added file and the address both survive the reboot. Configuring the network through cloud-init itself is covered in Automating the Initial Setup with cloud-init.

Test Environment and Session Logs

The examples were captured on the following topology in CML. sv1 is the machine being configured; R1 is the DHCP server and the source of the router advertisements.

The test topology
  sv1 (Ubuntu 26.04)     sv2 (Ubuntu 26.04)      R1 (IOS XE)
   ens3                   ens3                    Gi2
   192.168.100.10/24      192.168.100.20/24       192.168.100.1/24
   2001:db8:100::10/64    2001:db8:100::20/64     2001:db8:100::1/64
      |                      |                       |
      +----------------------+------- LAB-SW --------+
StepSession log
The initial statelog
Investigating the unmanaged interfacelog
Setting a static IPv4 addresslog
Checking connectivitylog
Syntax error and permission warninglog
Obtaining an address by DHCPlog
Autoconfiguration from router advertisementslog
The address generation modelog
With router advertisements refusedlog
Static IPv6 and connectivitylog
Disabling cloud-init and rebootinglog

On the router (R1), a set of show output, syslog and running-config was captured at each change. The running-config files are the configuration under test.

State of R1show outputsyslogrunning-config
While the static IPv4 address was setshowlogrun
While handing out an address by DHCPshowlogrun
While RA and DHCPv6 were in useshowlogrun

Each ..._show.txt contains:

show version / show interfaces description / show ip interface brief / show ipv6 interface brief /
show ip route / show ipv6 route / show ipv6 interface GigabitEthernet2 /
show ip dhcp pool / show ip dhcp binding / show ip dhcp server statistics / show ip dhcp conflict /
show ipv6 dhcp pool / show ipv6 dhcp binding / show ipv6 dhcp interface / show ipv6 neighbors
The configuration under test does not include SSH key generation: crypto key generate rsa is an exec command rather than configuration, so it never appears in show running-config. Generate the key after boot if you want to reach the router over SSH.

The complete captures can be downloaded here.

Download the full router advertisement capture

Download the full DHCP and DHCPv6 capture

Related topics

References

Related articles

Ubuntu official pages