Linux Server Networking with Netplan
Linux Server Networking with Netplan
Section titled “Linux Server Networking with Netplan”A practical guide to configuring multi-port networking on Ubuntu servers using Netplan. Covers static IPs, DHCP, multi-homing (dual ISP + LAN), bonding, VLANs, interface migration, and troubleshooting.
How Netplan Works
Section titled “How Netplan Works”Netplan is a YAML-based network configuration abstraction layer for Ubuntu (18.04+). It doesn’t configure networking directly — it generates configuration for a backend renderer:
systemd-networkd(default on Ubuntu Server) — lightweight, no GUI dependencies, ideal for serversNetworkManager(default on Ubuntu Desktop) — full-featured, handles WiFi/VPN/GUI integration
You can set the renderer explicitly:
network: version: 2 renderer: networkd # or NetworkManagerNetplan Basics
Section titled “Netplan Basics”Config files live in /etc/netplan/ as YAML, processed in lexicographic order (so 01-netcfg.yaml is applied before 99-override.yaml). Multiple files can coexist — later files override earlier ones for the same interface.
# View current configcat /etc/netplan/01-netcfg.yaml
# List all config files (processed in order)ls -la /etc/netplan/
# Apply changessudo netplan apply
# Test changes (auto-reverts after timeout)sudo netplan try --timeout 120
# Show current network state (netplan 0.106+, Ubuntu 23.04+)netplan statusIdentifying Interfaces
Section titled “Identifying Interfaces”# List all interfaces with link statusfor iface in $(ls /sys/class/net/ | grep -v lo); do link=$(ethtool $iface 2>/dev/null | grep "Link detected:" | awk '{print $3}') speed=$(ethtool $iface 2>/dev/null | grep "Speed:" | awk '{print $2}') driver=$(ethtool -i $iface 2>/dev/null | grep driver | awk '{print $2}') mac=$(ip link show $iface | grep ether | awk '{print $2}') echo "$iface: link=$link speed=$speed driver=$driver mac=$mac"done
# See NIC hardwarelspci | grep -i ethernet
# Check max supported speedethtool <interface> | grep "Supported link modes"Predictable Interface Naming
Section titled “Predictable Interface Naming”Linux uses systemd’s Predictable Network Interface Names instead of the old eth0/eth1 scheme. The prefix tells you the hardware type and bus location:
| Prefix | Type | Naming Basis | Example |
|---|---|---|---|
eno* | Onboard ethernet | Firmware/BIOS index | eno16495np0 |
enp* | PCIe ethernet | PCI bus + slot | enp3s0 |
ens* | PCIe ethernet | PCI hotplug slot | ens192 (common in VMs) |
enx* | USB ethernet | MAC address | enx9c69d37c9c17 |
ib* | InfiniBand | PCI bus + slot | ibp23s0 |
wl* | Wireless | Same scheme as en* | wlp2s0 |
Static IP Configuration
Section titled “Static IP Configuration”network: version: 2 ethernets: eno16495np0: addresses: - 192.168.1.100/24 routes: - to: default via: 192.168.1.1 nameservers: addresses: - 1.1.1.1 - 8.8.8.8 search: [] dhcp4: false dhcp6: falseDHCP Configuration
Section titled “DHCP Configuration”network: version: 2 ethernets: eno16495np0: dhcp4: true optional: true # Don't block boot if no cableMulti-Port Server (All Ports Active)
Section titled “Multi-Port Server (All Ports Active)”On servers with many ethernet ports, enable all of them so any cable plugged in auto-configures:
network: version: 2 ethernets: # Primary — static IP eno16495np0: addresses: - 192.168.1.19/24 routes: - to: default via: 192.168.1.1 nameservers: addresses: - 1.1.1.1 - 8.8.8.8 dhcp4: false
# All other ports — DHCP, auto-configure when plugged in eno16505np1: dhcp4: true optional: true eno16695: dhcp4: true optional: true eno16705: dhcp4: true optional: trueImportant: optional: true prevents the port from blocking boot when no cable is present. Without it, systemd-networkd waits for a DHCP lease and delays startup by minutes.
Keeping Ports Ready for Cable Detection
Section titled “Keeping Ports Ready for Cable Detection”Netplan sets uncabled ports to DOWN, which prevents link detection. Create a systemd service to keep them administratively UP:
#!/bin/bashfor iface in eno16495np0 eno16505np1 eno16695 eno16705; do ip link set "$iface" up 2>/dev/nulldone[Unit]Description=Bring all ethernet interfaces UPAfter=network.target
[Service]Type=oneshotExecStart=/root/all-nics-up.shRemainAfterExit=yes
[Install]WantedBy=multi-user.targetsudo systemctl enable --now all-nics-up.serviceDual Network (ISP + LAN) on Same Server
Section titled “Dual Network (ISP + LAN) on Same Server”Running a public ISP connection alongside a private LAN requires policy-based routing to keep traffic on the correct interface.
The Problem
Section titled “The Problem”With two default gateways, the kernel sends all traffic through whichever has the lower metric — even traffic sourced from the other interface’s IP. This breaks connectivity on the second interface.
The Solution: Source-Based Routing
Section titled “The Solution: Source-Based Routing”This uses Linux’s policy routing database (ip rule + ip route table) to route packets based on their source address rather than just the destination. This is documented in detail in the LARTC HOWTO — Routing Policy Database, with a specific multiple uplinks example. Also see Netplan’s own source_routing.yaml example for the YAML-native approach using routing-policy: keys.
# Add a custom routing tableecho "100 isp" >> /etc/iproute2/rt_tables
# Route traffic FROM the ISP IP through the ISP interfaceip rule add from 46.110.152.202 table isp priority 100ip route add default via 46.110.152.201 dev eno16495np0 table ispip route add 46.110.152.200/29 dev eno16495np0 table ispCloudflare WARP / Tunnel Conflicts
Section titled “Cloudflare WARP / Tunnel Conflicts”Cloudflare WARP (and similar VPN software) installs a catch-all routing table that hijacks ALL traffic — including traffic meant for your ISP interface. Symptoms:
ip route get 1.1.1.1 from <ISP_IP>showsdev CloudflareWARPinstead of your interface- Pings from the ISP IP fail with “Operation not permitted”
- Traffic works fine through the tunnel but not directly
Fix: Disconnect WARP when testing direct ISP connectivity, or configure WARP split tunneling to exclude your ISP subnet:
warp-cli disconnect # Temporarywarp-cli set-mode proxy # Or switch to proxy-only modeFor permanent fixes, configure split tunnel exclusions in the Zero Trust Dashboard (Settings → WARP Client → Device Settings → Split Tunnels) to exclude your ISP subnet.
Example: ISP on eno16495np0, LAN on eno16695
Section titled “Example: ISP on eno16495np0, LAN on eno16695”network: version: 2 ethernets: # Public ISP — static eno16495np0: addresses: - 46.110.152.202/29 routes: - to: default via: 46.110.152.201 nameservers: addresses: - 206.225.75.225 - 1.1.1.1 dhcp4: false
# Private LAN — static or DHCP eno16695: addresses: - 192.168.1.19/24 routes: - to: default via: 192.168.1.1 metric: 200 # Higher metric = lower priority dhcp4: falseSafe Network Changes (Auto-Revert)
Section titled “Safe Network Changes (Auto-Revert)”When changing network config remotely, always set up an auto-revert so you don’t get locked out.
Using netplan try
Section titled “Using netplan try”# Applies config, reverts after 120s unless you press Entersudo netplan try --timeout 120Manual Auto-Revert with at
Section titled “Manual Auto-Revert with at”# Backup current configcp /etc/netplan/01-netcfg.yaml /etc/netplan/01-netcfg.yaml.backup
# Schedule revert in 5 minutesecho "cp /etc/netplan/01-netcfg.yaml.backup /etc/netplan/01-netcfg.yaml && netplan apply" | at now + 5 minutes
# Apply new configsudo netplan apply
# If it works, cancel the revertatrm $(atq | awk '{print $1}')Live Interface Migration (Move Cable Without Losing SSH)
Section titled “Live Interface Migration (Move Cable Without Losing SSH)”When you need to move your LAN cable to a different port while staying connected:
- Don’t assign the same IP to multiple interfaces — causes ARP confusion
- Use a watchdog script that detects link loss on the primary and migrates:
#!/bin/bash# Watches for cable migration between portsPRIMARY="eno16495np0"SECONDARY_PORTS="eno16505np1 eno16695 eno16705"LAN_IP="192.168.1.19/24"GW="192.168.1.1"
while true; do PRIMARY_LINK=$(ethtool $PRIMARY 2>/dev/null | grep "Link detected: yes") if [ -z "$PRIMARY_LINK" ]; then # Primary lost cable — find where it went for iface in $SECONDARY_PORTS; do ip link set $iface up 2>/dev/null link=$(ethtool $iface 2>/dev/null | grep "Link detected: yes") if [ -n "$link" ]; then # Remove from dead primary ip addr del $LAN_IP dev $PRIMARY 2>/dev/null ip route del default via $GW dev $PRIMARY 2>/dev/null # Assign to new port ip addr add $LAN_IP dev $iface 2>/dev/null ip route replace default via $GW dev $iface 2>/dev/null break fi done fi sleep 3doneBonding (Link Aggregation)
Section titled “Bonding (Link Aggregation)”Bonding combines multiple NICs into a single logical interface for redundancy or throughput. This is the natural next step when you have a multi-port server. Netplan supports all Linux bonding modes.
Active-Backup (Mode 1) — Failover
Section titled “Active-Backup (Mode 1) — Failover”The simplest and most common mode. Only one NIC is active; the other takes over if the primary fails. Works with any switch — no special configuration required.
network: version: 2 ethernets: eno16495np0: {} eno16505np1: {} bonds: bond0: interfaces: - eno16495np0 - eno16505np1 parameters: mode: active-backup primary: eno16495np0 mii-monitor-interval: 100 # Check link every 100ms addresses: - 192.168.1.19/24 routes: - to: default via: 192.168.1.1 nameservers: addresses: - 1.1.1.1 - 8.8.8.8802.3ad / LACP (Mode 4) — Aggregated Throughput
Section titled “802.3ad / LACP (Mode 4) — Aggregated Throughput”Requires a managed switch with LACP (Link Aggregation Control Protocol) enabled. Provides both redundancy and increased bandwidth for multi-stream workloads.
network: version: 2 bonds: bond0: interfaces: - eno16495np0 - eno16505np1 parameters: mode: 802.3ad lacp-rate: fast mii-monitor-interval: 100 transmit-hash-policy: layer3+4 # Hash on IP+port for better distribution addresses: - 192.168.1.19/24 routes: - to: default via: 192.168.1.1Bonding Mode Reference
Section titled “Bonding Mode Reference”| Mode | Name | Switch Support | Use Case |
|---|---|---|---|
| 0 | balance-rr | Needs EtherChannel | Testing only (causes packet reordering) |
| 1 | active-backup | Any switch | Simple failover |
| 2 | balance-xor | Needs EtherChannel | Static load distribution |
| 3 | broadcast | Needs EtherChannel | Fault tolerance (sends on all) |
| 4 | 802.3ad | Needs LACP | Production aggregation |
| 5 | balance-tlb | Any switch | Outbound load balancing |
| 6 | balance-alb | Any switch | Bi-directional load balancing |
VLANs let you segment traffic on a single physical NIC into isolated virtual networks. Common uses: separating management traffic from data, isolating IoT devices, or running multiple subnets on one NIC.
network: version: 2 ethernets: eno16495np0: dhcp4: false vlans: vlan100: id: 100 link: eno16495np0 addresses: - 10.100.0.10/24 routes: - to: 10.100.0.0/24 via: 10.100.0.1 vlan200: id: 200 link: eno16495np0 addresses: - 10.200.0.10/24VLANs on a Bond
Section titled “VLANs on a Bond”You can stack VLANs on top of a bond for both redundancy and segmentation:
network: version: 2 bonds: bond0: interfaces: [eno16495np0, eno16505np1] parameters: mode: 802.3ad vlans: vlan100: id: 100 link: bond0 addresses: - 10.100.0.10/24Ethernet Speed Negotiation
Section titled “Ethernet Speed Negotiation”Check Current Speed
Section titled “Check Current Speed”ethtool is the primary tool for querying and configuring NIC hardware settings:
ethtool eno16495np0 | grep -E "Speed|Duplex|Auto-negotiation|Supported link modes"Common Speed Issues
Section titled “Common Speed Issues”| Symptom | Cause | Fix |
|---|---|---|
| 1 Gbps on a 10G NIC | Other end only offers 1G | Check switch/ISP port, cable category |
| Half duplex | Bad cable or USB adapter | Replace cable, avoid USB hubs |
| Link flapping | Cable too long or damaged | Max 100m for Cat6a at 10G |
| ”Speed: Unknown” | No cable detected | Check physical connection |
Cable Requirements by Speed
Section titled “Cable Requirements by Speed”| Speed | Min Cable | Max Distance |
|---|---|---|
| 1 GbE | Cat5e | 100m |
| 2.5 GbE | Cat5e | 100m |
| 5 GbE | Cat6 | 100m |
| 10 GbE | Cat6a | 100m |
| 25/40 GbE | DAC/Fiber | Varies |
SFP+ and High-Speed Ports
Section titled “SFP+ and High-Speed Ports”Servers with Mellanox ConnectX or Broadcom BCM57414 NICs have SFP+/QSFP ports for 10G+ speeds. These require:
- SFP+ transceiver (10GBase-T for copper, 10GBase-SR for fiber)
- DAC cable (Direct Attach Copper — cheap, short range, no transceiver needed)
- Check compatibility:
ethtool -m <interface>shows transceiver info
USB/Type-C Ethernet Adapters
Section titled “USB/Type-C Ethernet Adapters”USB ethernet adapters work but have caveats:
- Often limited to 1 Gbps (USB 3.0 bandwidth)
- May use generic
cdc_ncmdriver instead of vendor driver — can cause half-duplex, no traffic - USB hubs add latency and may not pass ethernet reliably
- Interface names are MAC-based:
enx9c69d37c9c17
For servers: always prefer built-in NIC ports over USB adapters.
UFW Firewall with Multiple Interfaces
Section titled “UFW Firewall with Multiple Interfaces”When adding a second network interface, UFW may block traffic on the new interface.
# Allow SSH on the new interfacesudo ufw allow in on eno16495np0 to any port 22 proto tcp
# Allow all outbound (default)sudo ufw default allow outgoing
# Check statussudo ufw status verboseTroubleshooting
Section titled “Troubleshooting”Can’t Reach Gateway
Section titled “Can’t Reach Gateway”# Check ARP — can you resolve the gateway MAC?ip neigh show dev <interface>
# Check routing — is traffic going to the right interface?ip route get <gateway> from <your_ip>
# Check firewallsudo iptables -L -n -v | head -20sudo ufw status
# Check for VPN/tunnel hijacking routesip rule listip route show table all | grep -v "local\|broadcast"Lost SSH After Config Change
Section titled “Lost SSH After Config Change”- Wait for auto-revert (if you set one up)
- Try alternate access: Cloudflare tunnel, IPMI/iDRAC console, physical console
- If physically on-site:
sudo cp /etc/netplan/*.backup /etc/netplan/01-netcfg.yaml && sudo netplan apply
Multiple Interfaces with Same IP
Section titled “Multiple Interfaces with Same IP”Never assign the same IP to two active interfaces on the same subnet. The kernel sends ARP replies from both MACs, confusing the switch/router. Traffic randomly goes to the wrong port and connections drop.
Security Considerations
Section titled “Security Considerations”Interface Isolation
Section titled “Interface Isolation”When running a server with both public (ISP) and private (LAN) interfaces, isolate them:
# Only allow SSH from the LAN, not the ISP-facing interfacesudo ufw allow in on eno16695 to any port 22 proto tcpsudo ufw deny in on eno16495np0 to any port 22 proto tcp
# Allow specific services on the public interfacesudo ufw allow in on eno16495np0 to any port 443 proto tcpsudo ufw allow in on eno16495np0 to any port 80 proto tcpKernel Hardening for Multi-Homed Servers
Section titled “Kernel Hardening for Multi-Homed Servers”Add to /etc/sysctl.d/99-network-hardening.conf:
# Reverse path filtering — drop packets arriving on wrong interfacenet.ipv4.conf.all.rp_filter = 1net.ipv4.conf.default.rp_filter = 1
# Don't act as a router (unless you intend to)net.ipv4.ip_forward = 0
# Ignore ICMP redirects (prevents route injection attacks)net.ipv4.conf.all.accept_redirects = 0net.ipv4.conf.all.send_redirects = 0
# Log packets with impossible source addressesnet.ipv4.conf.all.log_martians = 1sudo sysctl --system # ReloadQuick Reference
Section titled “Quick Reference”# Apply configsudo netplan apply
# Safe apply with auto-revertsudo netplan try --timeout 120
# Show all IPsip -br addr
# Show routesip route
# Show link statusip -br link
# Show policy routing rulesip rule list
# Flush interface configip addr flush dev <interface>
# Bring interface up/downip link set <interface> upip link set <interface> down
# Check NIC speed capabilityethtool <interface> | grep "Supported link modes"
# Check cable/linkethtool <interface> | grep "Link detected"
# Show network state (netplan 0.106+)netplan status
# Show systemd-networkd managed interfacesnetworkctl status
# Debug netplan config generationnetplan generate # Writes backend config, shows errorsReferences and Further Reading
Section titled “References and Further Reading”Official Netplan Documentation
Section titled “Official Netplan Documentation”- Netplan.io — Official site (redirects to ReadTheDocs for reference docs)
- netplan(5) YAML Reference — Ubuntu Noble 24.04 — Complete YAML key reference for netplan 1.1.2 (ethernets, bonds, bridges, vlans, routes, routing-policy)
- netplan(8) man page — Ubuntu Noble 24.04 — Command reference including
netplan trytimeout/rollback semantics - Netplan on GitHub — Source code (v1.2.1), issue tracker, and changelog
- Netplan Examples (37 YAML files) — Bonding, bridging, VLANs, source routing, WireGuard, Open vSwitch, and more
- Netplan source_routing.yaml — Working example of
routing-policy:+table:keys for policy routing
Ubuntu Server Networking
Section titled “Ubuntu Server Networking”- Ubuntu Server — About Netplan — Introductory explanation of Netplan architecture
- Ubuntu Server — Networking How-To Index — Index page for all Ubuntu server networking guides
- Ubuntu Server — UFW Firewall — UFW setup including IP masquerading for multi-interface routing
Linux Networking Deep Dives
Section titled “Linux Networking Deep Dives”- Linux Advanced Routing & Traffic Control (LARTC) HOWTO — The definitive guide to iproute2, policy routing, and traffic shaping
- Section 4: Routing Policy Database —
ip rule, routing tables, simple source routing - Section 4.2: Multiple Uplinks — Per-provider routing tables (the technique used in the dual-ISP section above)
- Section 4: Routing Policy Database —
- ip-rule(8) man page — Authoritative RPDB reference covering rule types and priorities
- iproute2 Task-Centered User Guide — Practical guide covering
ip rule,ip route, VRF, and namespaces (CC-BY-SA) - Linux Kernel Bonding Documentation — Official kernel docs covering all 7 bonding modes, MII/ARP monitoring, and VLAN support
- Predictable Network Interface Names — systemd.io — Explains
eno*/ens*/enp*/enx*naming schemes, history, and rationale
- ethtool(8) man page — Reference for querying NIC speed, driver info, link status, offload features, and transceiver details (v6.15)
- systemd.net-naming-scheme(7) — Versioned naming scheme details (v238–v260) explaining how each kernel/systemd version assigns interface names
Cloudflare (for tunnel/WARP users)
Section titled “Cloudflare (for tunnel/WARP users)”- Cloudflare WARP Split Tunnels — Configure which traffic bypasses WARP (Exclude/Include modes). Note: DNS still resolves via Gateway unless Local Domain Fallback is also configured
- Cloudflare WARP Route Traffic Overview — Top-level routing config including split tunnels and local domain fallback
- Cloudflare Tunnel Documentation — Zero Trust tunnels as an alternative to port-forwarding
Community Resources
Section titled “Community Resources”- ServeTheHome Forums — Community discussions on server NIC compatibility, SFP+ transceivers, and homelab networking
- r/homelab — Community for self-hosted infrastructure discussions