Fixing Proxmox SDN: missing 'source /etc/network/interfaces.d/sdn' directive
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
Option 1: wildcard source (recommended)
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:
-
Check the generated file exists and is not empty:
cat /etc/network/interfaces.d/sdnFor a VLAN zone you will see an
auto/ifaceblock for the bridge and its VLAN tags. -
Confirm the bridge is running:
ip link show type bridge -
If you enabled the optional DHCP integration, the dnsmasq instance is a systemd template service per zone:
systemctl status dnsmasq@testzoneThe
Created symlink ... dnsmasq@testzone.serviceline in the warning output is evidence that this part of the pipeline is working. -
For fabrics, verify FRR is running and loaded the generated config:
systemctl status frr cat /etc/frr/frr.conf -
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.