How to Configure VLAN Tagging with 802.1Q on RHEL 7

VLANs (Virtual Local Area Networks) allow a single physical network interface to participate in multiple logically isolated network segments simultaneously. The 802.1Q standard defines how Ethernet frames are tagged with a 12-bit VLAN ID, enabling switches and hosts to segregate traffic without requiring dedicated physical hardware for each network. On RHEL 7, the kernel’s 802.1Q module (8021q) provides this capability, and NetworkManager exposes it through both nmcli and traditional ifcfg configuration files. This tutorial covers loading the 802.1Q kernel module, creating VLAN sub-interfaces using nmcli, configuring static IP addresses on each VLAN, persisting the configuration across reboots, creating multiple VLANs on a single NIC, and verifying connectivity between VLAN segments.

Prerequisites

  • RHEL 7 system with root or sudo access
  • At least one physical network interface (e.g., ens33)
  • A managed switch with 802.1Q VLAN support, or a hypervisor virtual switch configured in trunk mode
  • Basic knowledge of IP subnetting
  • The upstream switch port connected to the RHEL host must be configured as a trunk port carrying the desired VLAN IDs

Step 1: Understand Trunk vs Access Ports

Before touching the Linux configuration it is important to understand how the upstream switch must be configured, because a misconfigured switch port is the most common reason VLAN tagging appears to work on the host but produces no connectivity.

  • Access port — carries traffic for a single VLAN. The switch strips the 802.1Q tag before delivering frames to the connected device. The device has no knowledge of the VLAN ID. Use this for end-user workstations and single-purpose servers.
  • Trunk port — carries traffic for multiple VLANs simultaneously, with 802.1Q tags preserved end-to-end. The connected device must handle the tagged frames itself. Use this for server NICs hosting multiple VLAN sub-interfaces, uplinks between switches, and hypervisor physical NICs.

To use VLAN tagging on RHEL 7, the switch port connecting to the server must be a trunk port that allows all required VLAN IDs to pass. On a Cisco switch this is configured with switchport mode trunk and switchport trunk allowed vlan 10,20,30.

Step 2: Load the 8021q Kernel Module

The 802.1Q VLAN module is included in the RHEL 7 kernel but may not be loaded by default. Load it manually and then configure it to load automatically on every boot.

# Load the 8021q module into the running kernel
modprobe 8021q

# Confirm the module is loaded
lsmod | grep 8021q

# Expected output:
# 8021q                  29022  0
# garp                   14384  1 8021q
# mrp                    18542  1 8021q

# Persist the module load across reboots
echo "8021q" > /etc/modules-load.d/8021q.conf

# Verify the file was created correctly
cat /etc/modules-load.d/8021q.conf

Step 3: Create a VLAN Interface with nmcli

NetworkManager’s nmcli command creates VLAN sub-interfaces with the correct kernel and ifcfg configuration in a single step. The naming convention for VLAN sub-interfaces is typically parent.vlan-id (e.g., ens33.10), though you can choose any valid interface name.

# Create VLAN 10 on top of the ens33 physical interface
nmcli con add type vlan 
    con-name ens33.10 
    dev ens33 
    id 10 
    ip4 192.168.10.1/24 
    gw4 192.168.10.254

# Bring up the VLAN interface
nmcli con up ens33.10

# Verify the interface was created
ip link show type vlan
ip addr show ens33.10

The ip link show type vlan command filters the interface list to show only 802.1Q tagged interfaces, making it easy to audit all active VLANs on a system.

Step 4: Inspect the Generated ifcfg File

When nmcli creates a VLAN connection, it writes a corresponding ifcfg file under /etc/sysconfig/network-scripts/. Knowing the file format allows you to create or edit VLAN configurations directly when NetworkManager is not available or when deploying via automation tools such as Ansible.

# View the generated ifcfg file
cat /etc/sysconfig/network-scripts/ifcfg-ens33.10

A correctly generated ifcfg file for VLAN 10 looks like the following:

VLAN=yes
TYPE=Vlan
PHYSDEV=ens33
VLAN_ID=10
VLAN_PLUS_VID_NO_PAD=no
REORDER_HDR=yes
GVRP=no
MVRP=no
NAME=ens33.10
DEVICE=ens33.10
ONBOOT=yes
BOOTPROTO=none
IPADDR=192.168.10.1
PREFIX=24
GATEWAY=192.168.10.254
NM_CONTROLLED=yes

The key fields are VLAN=yes, PHYSDEV (the parent interface), and VLAN_ID. You can create additional VLAN interfaces by duplicating this file, adjusting the VLAN ID, IP address, and file name, then running nmcli con reload.

Step 5: Configure Multiple VLANs on One NIC

A single physical NIC can host as many VLAN sub-interfaces as required. Each sub-interface is independent and can have its own IP address, routing table entries, and firewall rules. In this example, three VLANs are created: VLAN 10 for management, VLAN 20 for application traffic, and VLAN 30 for database traffic.

# VLAN 10 — Management (already created above)
# Verify: ip addr show ens33.10

# VLAN 20 — Application
nmcli con add type vlan 
    con-name ens33.20 
    dev ens33 
    id 20 
    ip4 192.168.20.1/24

nmcli con up ens33.20

# VLAN 30 — Database
nmcli con add type vlan 
    con-name ens33.30 
    dev ens33 
    id 30 
    ip4 192.168.30.1/24

nmcli con up ens33.30

# List all active VLAN interfaces
ip link show type vlan

# Show IP addresses for all three VLANs
ip addr show ens33.10
ip addr show ens33.20
ip addr show ens33.30

# Show all NetworkManager connections
nmcli con show

Step 6: Configure Firewalld Zones for VLAN Interfaces

Each VLAN sub-interface can be placed in a separate firewalld zone, enabling fine-grained traffic policies per VLAN — for example, allowing SSH only on the management VLAN and HTTP/HTTPS only on the application VLAN.

# Assign ens33.10 (management) to the 'trusted' zone
firewall-cmd --permanent --zone=trusted --add-interface=ens33.10

# Assign ens33.20 (application) to the 'public' zone with HTTP/HTTPS
firewall-cmd --permanent --zone=public --add-interface=ens33.20
firewall-cmd --permanent --zone=public --add-service=http
firewall-cmd --permanent --zone=public --add-service=https

# Assign ens33.30 (database) to a restricted 'internal' zone
firewall-cmd --permanent --zone=internal --add-interface=ens33.30

# Reload firewalld to apply changes
firewall-cmd --reload

# Verify zone assignments
firewall-cmd --get-active-zones

Step 7: Test VLAN Connectivity

# Confirm all three VLAN interfaces are UP with correct IPs
ip -br addr show type vlan

# Verify the kernel VLAN table
cat /proc/net/vlan/config

# Expected output:
# VLAN Dev name     | VLAN ID
# --------          |-----
# ens33.10          | 10  | ens33
# ens33.20          | 20  | ens33
# ens33.30          | 30  | ens33

# Show VLAN-specific statistics
cat /proc/net/vlan/ens33.10

# Ping across VLANs to a router or another host on each segment
ping -c3 -I ens33.10 192.168.10.254
ping -c3 -I ens33.20 192.168.20.254
ping -c3 -I ens33.30 192.168.30.254

# If VLANs need to route between each other, a Layer 3 device
# (router or Layer 3 switch) must handle inter-VLAN routing.
# On this host, you can enable IP forwarding for router-on-a-stick:
echo "net.ipv4.ip_forward = 1" >> /etc/sysctl.conf
sysctl -p

Step 8: Persist Configuration and Verify After Reboot

# Confirm all VLAN connections are set to auto-connect on boot
nmcli con show | grep ens33.

# Set autoconnect if not already enabled
nmcli con modify ens33.10 connection.autoconnect yes
nmcli con modify ens33.20 connection.autoconnect yes
nmcli con modify ens33.30 connection.autoconnect yes

# Simulate a reboot by restarting NetworkManager
systemctl restart NetworkManager

# Verify all VLAN interfaces come back up automatically
ip link show type vlan
nmcli con show --active

Step 9: Removing a VLAN Interface

# Bring down and delete a VLAN connection (non-destructive — just removes config)
nmcli con down ens33.30
nmcli con delete ens33.30

# Confirm removal
nmcli con show
ip link show type vlan

Conclusion

You have loaded the 8021q kernel module and configured it for persistent loading via /etc/modules-load.d/8021q.conf, created VLAN sub-interfaces using nmcli con add type vlan, inspected the corresponding ifcfg files under /etc/sysconfig/network-scripts/, deployed three independent VLANs on a single physical NIC, assigned each VLAN to an appropriate firewalld zone, and verified the configuration with ip link show type vlan and /proc/net/vlan/config. VLAN tagging is a foundational skill for Linux server administration, enabling server consolidation, network segmentation, and multi-tenant environments without the cost of additional physical hardware. The configuration demonstrated here is production-ready and integrates cleanly with bonding or teaming — simply use the bond or team interface as the dev parameter in the nmcli con add type vlan command to combine link aggregation and VLAN tagging on the same physical uplinks.