How to Configure a VLAN Trunk Interface with Netplan on Ubuntu

Written by: Bagus Facsi Aginsa
Published at: 10 Feb 2021


A server often needs to sit in more than one network at once: a public-facing VLAN for application traffic and a private VLAN for storage or management, for example. You could add a physical NIC per network, but switch ports and PCIe slots are finite. The standard answer is a VLAN trunk: a single physical interface that carries multiple VLANs, with the switch tagging each frame (802.1Q) so the server knows which virtual network it belongs to.

In this tutorial you will configure an Ubuntu interface as a VLAN trunk using Netplan, create a tagged VLAN interface for each network, and verify the tagging actually works. The examples use the current routes syntax (the old gateway4 directive is deprecated) and work on Ubuntu 20.04, 22.04, and 24.04.


How VLAN Trunking Works

A normal switch port is an access port: it belongs to exactly one VLAN, and frames travel over it untagged. The connected machine has no idea VLANs exist.

A trunk port carries several VLANs over one cable. Each Ethernet frame gets an 802.1Q tag, four extra bytes containing the VLAN ID, so both ends can tell the traffic apart. For this to work, both sides must agree:

  • The switch port must be configured as a trunk (or “tagged” port) allowing the VLAN IDs you need. This is done on the switch, not on Ubuntu.
  • The server must create one virtual interface per VLAN on top of the physical interface. Each virtual interface sends and receives frames tagged with its VLAN ID and gets its own IP configuration.

On Ubuntu, Netplan handles the server side with a vlans: section. No extra packages are needed, the kernel’s 802.1Q support is built in.


Prerequisites

  • Ubuntu 20.04, 22.04, or 24.04 LTS
  • A user with sudo privileges
  • The switch port connected to your server configured as a trunk, allowing the VLAN IDs you plan to use. Ask your network team for the IDs if you do not manage the switch
  • Console access (or netplan try) in case a network change goes wrong

The Use Case

To keep the examples concrete, this tutorial uses the following setup:

                                  __________________
                                 |______            |
    vlan 110 -----------\        |      |           |
                         |-------|ens18 |  ubuntu   |
    vlan 120 -----------/        |______|  server   |
                                 |__________________|

The server has one physical interface, ens18, connected to a trunk port carrying two VLANs:

  • VLAN 110 is the application network. The server gets 192.168.6.60/24, default gateway 192.168.6.1.
  • VLAN 120 is the private/storage network. The server gets 172.16.100.99/24, no gateway.

Step 1: Find Your Interface Name

Modern Ubuntu does not use eth0. Interface names depend on your hardware and hypervisor. Common names are ens18, enp0s3, or eno1. List yours:

ip link show

Example output:

1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
2: ens18: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP
    link/ether 52:54:00:12:34:56 brd ff:ff:ff:ff:ff:ff

Substitute your real interface name wherever you see ens18 below.


Step 2: Open the Netplan Configuration File

Netplan config files live in /etc/netplan/. Check what is there:

ls /etc/netplan/

You will typically see one YAML file, often 50-cloud-init.yaml or 00-installer-config.yaml. Back it up before editing:

sudo cp /etc/netplan/50-cloud-init.yaml /etc/netplan/50-cloud-init.yaml.bak
sudo nano /etc/netplan/50-cloud-init.yaml

Step 3: Write the VLAN Trunk Configuration

Here is the complete configuration for the use case above, using current Netplan syntax:

network:
  version: 2
  ethernets:
    ens18:
      dhcp4: false
  vlans:
    vlan110:
      id: 110
      link: ens18
      addresses:
        - 192.168.6.60/24
      routes:
        - to: default
          via: 192.168.6.1
      nameservers:
        addresses:
          - 8.8.8.8
    vlan120:
      id: 120
      link: ens18
      addresses:
        - 172.16.100.99/24

What each part does:

The physical interface carries no IP. ens18 is defined with dhcp4: false and no addresses. On a trunk, the physical interface is just a carrier: all IP configuration lives on the VLAN interfaces. (Untagged traffic on the port would arrive on ens18 itself; on a pure trunk there should not be any.)

The vlans: section creates one virtual interface per VLAN. Each entry needs two keys: id (the 802.1Q VLAN ID, matching the switch config) and link (the physical interface it rides on). Everything else, like addresses, routes, and nameservers, works exactly like on a normal interface. Need more VLANs? Add more entries under vlans:.

Only one VLAN gets a default route. VLAN 110 has to: default via 192.168.6.1; VLAN 120 has addresses only. A machine should have exactly one default gateway, because defining one per VLAN creates an ambiguous routing table. If you need to reach other subnets through VLAN 120, add specific routes there instead; see How to Add Static Route Using Netplan on Ubuntu.

A note on gateway4

Older tutorials (including the previous version of this one) used gateway4: 192.168.6.1. That directive has been deprecated since Ubuntu 22.04 and misbehaves on 24.04. Always use the routes form:

# Old (deprecated, do not use):
gateway4: 192.168.6.1

# Current syntax:
routes:
  - to: default
    via: 192.168.6.1

A note on interface naming

The VLAN interface name is up to you: vlan110, ens18.110, and mgmt are all valid. The id: field is what determines the actual 802.1Q tag, not the name. The name.ID convention (ens18.110) is common in other distros; this tutorial uses vlan110 for readability.


Step 4: Apply the Configuration Safely

On a remote server, use netplan try instead of netplan apply:

sudo netplan try

netplan try applies the new configuration and starts a 120-second countdown. If the change works and you still have connectivity, press Enter to keep it. If you lose access (easy to do when re-homing the server’s IP onto a VLAN interface), the configuration reverts automatically and you are not locked out.

If you are on the console (physical, VNC, or KVM), you can apply directly:

sudo netplan apply

Step 5: Verify the VLAN Interfaces

Check that the VLAN interfaces exist and have their addresses:

ip addr show vlan110
4: vlan110@ens18: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP
    link/ether 52:54:00:12:34:56 brd ff:ff:ff:ff:ff:ff
    inet 192.168.6.60/24 brd 192.168.6.255 scope global vlan110

The vlan110@ens18 notation confirms the virtual interface is bound to the physical one. To see the actual 802.1Q tagging details:

ip -d link show vlan110
4: vlan110@ens18: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 ...
    vlan protocol 802.1Q id 110 <REORDER_HDR>

The vlan protocol 802.1Q id 110 line is the proof that frames on this interface are tagged with VLAN ID 110.

Now test actual connectivity on each VLAN:

ping -c 3 -I vlan110 192.168.6.1
ping -c 3 -I vlan120 172.16.100.1

And confirm the routing table looks sane, with exactly one default route via VLAN 110:

ip route list
default via 192.168.6.1 dev vlan110 proto static
192.168.6.0/24 dev vlan110 proto kernel scope link src 192.168.6.60
172.16.100.0/24 dev vlan120 proto kernel scope link src 172.16.100.99

Common Problems and Troubleshooting

The VLAN interface is up but nothing responds to ping.

Nine times out of ten, this is the switch side: the port is not configured as a trunk, or the VLAN ID is not in the port’s allowed list. Verify the switch config first. You can watch for tagged frames arriving with sudo tcpdump -i ens18 -e vlan. If you see no tagged traffic at all, the switch is not sending any.

ip link shows the VLAN interface in state DOWN.

If the physical interface is down, every VLAN riding on it is down too. Check ip link show ens18 and look for NO-CARRIER (cable/port problem) before debugging the VLAN config.

YAML indentation errors.

Netplan is whitespace-sensitive: spaces only, no tabs, consistent indentation per level. If netplan try fails with a parse error, compare your file line by line against the example above.

The config applies but the address landed on the wrong VLAN.

Double-check the id: values. The interface name is cosmetic; the id: is what sets the tag. A copy-paste error that leaves two VLANs with the same id produces confusing, intermittent behaviour.

Lost SSH access after netplan apply.

If you applied a config that moved the server’s IP to a VLAN the switch does not carry, you need console access to restore the backup you made in Step 2. This is exactly the scenario netplan try exists for, so make it a habit.


Best Practices

Always use netplan try on remote machines. Re-homing IPs from a physical interface onto VLAN interfaces is one of the easiest ways to lock yourself out of a server. The 120-second auto-revert costs nothing.

Keep the physical interface address-free. Mixing an untagged address on ens18 with tagged VLANs on top of it works, but it makes the switch config (native VLAN) load-bearing and failure modes confusing. On a trunk, put all IPs on VLAN interfaces.

Exactly one default gateway. Pick the VLAN that faces the internet (or your core router) and define to: default there only. Use specific static routes on the other VLANs.

Restrict config file permissions. Netplan warns when its config is world-readable. Fix it with:

sudo chmod 600 /etc/netplan/50-cloud-init.yaml

Conclusion

You have turned a single physical interface into a VLAN trunk with Netplan: the physical interface carries tagged frames, each vlans: entry gives you a separate virtual interface with its own IP configuration, and ip -d link show proves the 802.1Q tagging is in place.

From here, a few related setups build on the same Netplan skills. If you also need a fixed address on a regular (non-VLAN) interface, see How to Set a Static IP Address with Netplan on Ubuntu. If the single physical link is now a bottleneck or a single point of failure, combine two NICs into one logical link with How to Set Up LACP Bonding Interfaces on Ubuntu. VLANs stack on top of a bond the same way they stack on a plain interface. And for routing between the VLANs’ subnets, How to Add Static Route Using Netplan on Ubuntu covers the routes syntax in depth.