Fixing Proxmox SDN: missing 'source /etc/network/interfaces.d/sdn' directive

Page content

If you have ever applied a Proxmox VE Software-Defined Network configuration and seen this warning pop up in the task view, you are not alone:

WARN: missing 'source /etc/network/interfaces.d/sdn' directive for SDN support!
Created symlink /etc/systemd/system/multi-user.target.wants/dnsmasq@testzone.service -> /lib/systemd/system/dnsmasq@.service.

TASK WARNINGS: 1

It looks harmless, and in most cases it is. But if you want SDN-generated networks to actually come up on the node, that one line is the difference between a pending configuration and a running one. This post explains where the warning comes from in the Proxmox source code, why the fix is a single source directive, and how to verify the whole pipeline works afterwards.

What the warning actually means

Proxmox VE SDN does not generate network interfaces the way you would write them by hand. The cluster-wide SDN state lives in /etc/pve/sdn, which is shared across all nodes through the pmxcfs cluster filesystem. When you apply changes from the SDN panel, the manager translates that state into per-node files:

  • /etc/network/interfaces.d/sdn - the generated ifupdown2 configuration for zones and fabrics
  • /etc/frr/frr.conf - the routing configuration, when a fabric is in use
  • /etc/wireguard/proxmox/*.conf - the WireGuard interface files, when a WireGuard fabric is in use

The generated /etc/network/interfaces.d/sdn file is only picked up by ifupdown2 if the main /etc/network/interfaces file sources the interfaces.d directory. Without that line, ifupdown2 never reads the file, so the bridges, VLANs and tunnels that SDN wrote to disk are never brought up.

The check itself is a grep over the parsed options of /etc/network/interfaces. From the pve-network source (PVE/Network/SDN.pm):

log_warn("missing 'source /etc/network/interfaces.d/sdn' directive for SDN support!\n")
    if !grep { $_->[1] =~ m!^source /etc/network/interfaces.d/(:?sdn|\*)! } @$opts;

Two things are worth noting about that regex. First, it accepts either an explicit source /etc/network/interfaces.d/sdn or the wildcard source /etc/network/interfaces.d/*. Second, the check runs on every node where a configuration is generated - the fix must be present on all of them.

Why this happens

On a fresh Proxmox VE installation the problem does not exist. The installer writes the wildcard line at the end of /etc/network/interfaces automatically, so a clean install is SDN-ready from day one.

The warning shows up in specific situations:

Situation Why the directive is missing
Manual edit of /etc/network/interfaces The source line was removed or overwritten
Node created before the SDN packages were present Older installations did not get the line
File rewritten by a script or config management tool The tool wrote the file without the trailing line
Upgraded node with a customized interfaces file The custom file never contained the line

If you run a fleet where configuration is managed by Ansible, Terraform or Puppet, treat that file as managed content: make sure the template ends with the source directive, or the warning will come back on every node after the next run.

The fix

Add this line at the bottom of /etc/network/interfaces on every node in the cluster:

echo "source /etc/network/interfaces.d/*" >> /etc/network/interfaces

This is the same line the Proxmox installer adds, and it is the most future-proof choice: any file in /etc/network/interfaces.d/ is picked up, not just the SDN one. If you prefer an editor, open the file with nano /etc/network/interfaces and add the line at the end before saving.

Option 2: explicit file source

If you prefer to be strict about what gets sourced, you can target the SDN file directly:

source /etc/network/interfaces.d/sdn

The Proxmox warning accepts both forms, so either one clears it. The wildcard is the default and the one I recommend.

Reload networking

The SDN panel applies the change for you, but you can also reload from the shell:

ifreload -a

On a live node, verify the generated bridge is up after reloading:

ip link show
ip addr show

You should see the SDN-generated interface (for example a vmbr0 VLAN sub-interface or a WireGuard tunnel) in the list.

Verify the SDN pipeline end to end

Fixing the warning is the easy part. Confirming the pipeline works is what saves you later. After applying the source directive and the SDN configuration:

  1. Check the generated file exists and is not empty:

    cat /etc/network/interfaces.d/sdn
    

    For a VLAN zone you will see an auto/iface block for the bridge and its VLAN tags.

  2. Confirm the bridge is running:

    ip link show type bridge
    
  3. If you enabled the optional DHCP integration, the dnsmasq instance is a systemd template service per zone:

    systemctl status dnsmasq@testzone
    

    The Created symlink ... dnsmasq@testzone.service line in the warning output is evidence that this part of the pipeline is working.

  4. For fabrics, verify FRR is running and loaded the generated config:

    systemctl status frr
    cat /etc/frr/frr.conf
    
  5. Test from a guest: attach a vNIC to a VNet, start the VM, and ping another VM on the same VNet on a different node. Cross-node connectivity is the real proof that the SDN bridge, VLAN tagging and fabric routing all came up.

The rest of the SDN installation

The source directive is a prerequisite, not the whole feature. According to the official documentation, the SDN core has been installed by default since Proxmox VE 8.1. If you are upgrading from an older version, the libpve-network-perl package must be present on every node:

apt update
apt install libpve-network-perl

Two features are opt-in and require extra packages:

Feature Package Notes
DHCP for VNets dnsmasq Installs a per-zone template service; disable the default instance first
Fabric routing frr-pythontools Enables BGP/EVPN via FRRouting
# DHCP
apt install dnsmasq
systemctl disable --now dnsmasq

# FRR
apt install frr-pythontools
systemctl enable frr

SDN changes are recorded as pending first and applied atomically from the main SDN panel. The rolled-out state is tracked in .running-config and .version files under /etc/pve/sdn, which is what makes cluster-wide rollouts and rollbacks predictable.

A quick look at what SDN gives you

Since this is the moment you are enabling the feature, a short tour of the pieces that consume that generated file helps frame the warning in context:

  Datacenter SDN state (/etc/pve/sdn, shared via pmxcfs)
              |
              v
  +-------------------------------------+
  | Zones: VLAN, QinQ, VXLAN, EVPN,     |
  | WireGuard, Simple                   |
  +-------------------------------------+
              |
              v
  +-------------------------------------+
  | VNets + subnets (+ optional DHCP,   |
  | IPAM, DNS via dnsmasq plugin)       |
  +-------------------------------------+
              |
              v
  +-------------------------------------+
  | Fabrics: WireGuard / BGP / EVPN     |
  | routing between nodes (FRR)         |
  +-------------------------------------+
              |
              v
  /etc/network/interfaces.d/sdn  -->  ifupdown2 (needs the source line)
  /etc/frr/frr.conf              -->  FRR
  /etc/wireguard/proxmox/*.conf  -->  WireGuard

A typical VLAN setup: create a VLAN zone backed by vmbr0, create a VNet with a VLAN tag, apply it, then attach VMs to the VNet. The warning you fixed is exactly the step that turns the generated per-node file into a live interface.

Troubleshooting

The warning keeps coming back

The check reads /etc/network/interfaces every time a configuration is generated. If it comes back, the file was modified after your fix - usually by a config management run. Check the file tail and make the source line part of the managed template.

No warning, but the bridge is not up

The warning is absent but the interface never appears. In that case ifupdown2 read the file and something else failed:

ifup --test vmbr0
journalctl -u ifupdown --since "10 minutes ago"

A common cause is a stale auto/iface block in /etc/network/interfaces itself that conflicts with the generated one.

DHCP leases not appearing

The per-zone dnsmasq service failed to start:

systemctl status dnsmasq@testzone
journalctl -u dnsmasq@testzone

Leases are stored in /var/lib/misc/dnsmasq.<zone>.leases.

Fabric routes missing

Verify FRR is running and actually loaded the generated configuration. The SDN fabric generates /etc/frr/frr.conf; if FRR is not enabled, the file exists but nothing acts on it.

Summary

The WARN: missing 'source /etc/network/interfaces.d/sdn' directive for SDN support! message is Proxmox telling you that the main /etc/network/interfaces file does not include the directory where SDN writes its generated configuration. Add source /etc/network/interfaces.d/* at the bottom of the file on every node, reload networking, and the pipeline is complete. Fresh installs already have the line; it only disappears through manual edits, old upgrades or managed configurations that rewrite the file. Once the directive is in place, verify the generated file, the bridge state, and cross-node guest connectivity - that is where the real value of SDN starts to show.