This solution (re-)adds VLAN (802.1Q) support to Debian installer's network configuration (netcfg), enabling automated installations on VLAN-tagged networks using both DHCP and static IP configurations.
Key Features:
- ✅ DHCP on VLAN interfaces
- ✅ Static IP on VLAN interfaces
- ✅ Works with standard Debian installer (bookworm/stable)
- ✅ Minimal overhead (~1.3KB addon initrd)
- ✅ No modifications to upstream Debian installer required
Debian's netcfg component apparantly still lacks native VLAN support:
• The official Debian netcfg repository master branch has NO vlan.c file
• The debian/netcfg-common.templates file has NO netcfg/use_vlan or netcfg/vlan_id templates
When you try to configure networking on a VLAN interface during installation:
- VLAN interface doesn't exist - The installer doesn't create VLAN interfaces from kernel parameters
- Parent interface not brought up - Even if you manually create the VLAN interface,
netcfgbrings down all interfaces during initialization and doesn't properly bring up the parent interface when configuring the VLAN interface - DHCP fails - The
udhcpcDHCP client is called without ensuring interfaces are UP - Static IP fails - The
ipcommand is used to configure static IPs, but the parent interface isn't brought up first
VLAN support was proposed for Debian's netcfg in 2012 (commit 63d72aa9 by YunQiang Su, staged by Philipp Kern), but was never merged into the master branch. The patch exists only on the origin/people/pkern/vlan branch in the official Debian repository.
Why it was never merged: The commit message states: "I seems that 8021q module is not included in d-i (Linux).". This blocker is no longer relevant - and as such the 8021q module is now included in modern Debian installer kernels. However, the patch was never revisited or merged after the module became available, and remains only on the origin/people/pkern/vlan branch."
Ubuntu's approach: Ubuntu cherry-picked this patch and included it in Ubuntu 16.04-18.04. However, Ubuntu 20.04+ removed debian-installer entirely, replacing it with subiquity.
Current state: The netcfg/use_vlan and netcfg/vlan_id parameters never worked in official Debian releases (and no longer work in modern Ubuntu).
References:
- Debian netcfg repository: https://salsa.debian.org/installer-team/netcfg.git
- VLAN patch branch:
origin/people/pkern/vlan - VLAN patch commit:
63d72aa9(December 6, 2012)
This solution uses a small addon initrd (~1.3KB) that patches the Debian installer environment with three wrapper scripts:
Purpose: Creates the VLAN interface early in the boot process, before netcfg runs.
What it does:
- Parses the
vlan=kernel parameter (format:vlan=<interface>.<vlan_id>:<parent_interface>) - Loads the
8021qkernel module for VLAN support - Waits for the parent interface to appear
- Creates the VLAN interface using
ip link add
Why it's needed: netcfg doesn't create VLAN interfaces, so we must create them before netcfg runs.
Purpose: Ensures both parent and VLAN interfaces are UP before running DHCP.
What it does:
- Intercepts calls to
udhcpc(BusyBox DHCP client) - Detects if the device/interface is a VLAN interface (contains a dot)
- Brings up the parent interface first
- Brings up the VLAN interface
- Passes all arguments unchanged to the real
udhcpc
Why it's needed: netcfg brings down all interfaces during initialization and calls udhcpc without bringing them back up. The Linux kernel does NOT automatically bring up the parent interface when you bring up a VLAN interface.
Purpose: Ensures the parent interface is UP before configuring static IP on the VLAN interface.
What it does:
- Intercepts calls to the
ipcommand - Parses arguments looking for
dev <interface>patterns - If the interface is a VLAN interface (contains a dot), brings up the parent interface first
- Passes all arguments unchanged to the real
ipcommand
Why it's needed: When netcfg calls netcfg_interface_up() for static IP configuration, it only brings up the VLAN interface itself. The parentif field is NULL in the master branch (only set in the unmerged VLAN patch), so the parent interface is never brought up. Without the parent interface being UP, the VLAN interface cannot communicate.
Important: The wrapper does NOT modify any commands - it only adds a side effect (bringing up the parent interface) before passing the original command through unchanged. This ensures all other uses of the ip command work normally.
For DHCP:
vlan=eth0.100:eth0 interface=eth0.100
For Static IP:
vlan=eth0.100:eth0 interface=eth0.100 netcfg/disable_autoconfig=true netcfg/get_ipaddress=192.168.1.100 netcfg/get_netmask=255.255.255.0 netcfg/get_gateway=192.168.1.1 netcfg/get_nameservers=192.168.1.1 netcfg/confirm_static=true
Parameter explanation:
vlan=<interface>.<vlan_id>:<parent>- Tells S29vlan-setup to create the VLAN interfaceinterface=<interface>.<vlan_id>- Tellsnetcfgwhich interface to configure- Standard
netcfgparameters for static IP configuration
the testing environment utilizes iPXE to load over hte network the linux kernel, as well as the upstream initrd, but it also "stacks" on top of that (concatenate) an add-on initrd, which containers the scripts
#!ipxe
kernel http://deb.debian.org/debian/dists/bookworm/main/installer-amd64/current/images/netboot/debian-installer/amd64/linux
initrd http://deb.debian.org/debian/dists/bookworm/main/installer-amd64/current/images/netboot/debian-installer/amd64/initrd.gz
initrd tftp://local-tftp-server/path-to/debian-installer-vlan-support.gz
imgargs linux initrd=initrd.gz vlan=eth0.100:eth0 interface=eth0.100 auto=true priority=critical
boot
Note: iPXE is used as it supports loading multiple initrd files. They are concatenated, and later files can overwrite earlier files.
mkdir -p vlan-support-initrd/lib/debian-installer-startup.d
mkdir -p vlan-support-initrd/sbinCreate the three scripts (see the separate script files in this gist):
S29vlan-setup.sh→vlan-support-initrd/lib/debian-installer-startup.d/S29vlan-setupudhcpc.shwrapper →vlan-support-initrd/sbin/udhcpcip.sh wrapper →vlan-support-initrd/sbin/ip
mv S29vlan-setup.sh vlan-support-initrd/lib/debian-installer-startup.d/S29vlan-setup
mv udhcpc.sh vlan-support-initrd/sbin/udhcpc
mv ip.sh vlan-support-initrd/sbin/ipMake them executable:
chmod +x vlan-support-initrd/lib/debian-installer-startup.d/S29vlan-setup
chmod +x vlan-support-initrd/sbin/udhcpc
chmod +x vlan-support-initrd/sbin/ipVerify with find vlan-support-initrd/ -type f -ls, you should see:
135584887 4 -rwxr-xr-x 1 user group 1155 Jan 22 17:08 vlan-support-initrd/lib/debian-installer-startup.d/S29vlan-setup
135584881 4 -rwxr-xr-x 1 user group 776 Jan 22 17:07 vlan-support-initrd/sbin/udhcpc
135584879 4 -rwxr-xr-x 1 user group 1338 Jan 22 17:07 vlan-support-initrd/sbin/ipcd vlan-support-initrd
find . | cpio -o -H newc | gzip -c > ../debian-installer-vlan-support.gz
cd ..This creates a ~1.3KB gzipped cpio archive.
Load both the standard Debian installer initrd and your addon initrd. The addon initrd will patch the installer environment.
With iPXE:
initrd http://deb.debian.org/debian/dists/bookworm/main/installer-amd64/current/images/netboot/debian-installer/amd64/initrd.gz
initrd tftp://local-tftp-server/path-to/debian-installer-vlan-support.gz # or use http
How it works: When multiple cpio archives are concatenated, later files overwrite earlier files with the same path. Our wrapper scripts overwrite the BusyBox symlinks in the original initrd.
From netcfg-common.c:
netcfg_get_interface()(line 798): Brings down ALL interfaces when building the interface selection listdeconfigure_network()(line 1191): Brings down the loopback and specified interfaceinterface_down()(line 1331): Uses ioctl to clear the IFF_UP flagnetcfg_interface_up()(line 1347): Would bring up the parent interface IFiface->parentifwas set, but it's NULL in master branch (line 1591)
From dhcp.c:
start_dhcp_client()(line 142): Directly only executesudhcpc(without bringing the parent interface up first)
From static.c:
netcfg_activate_static()(line 348): Callsnetcfg_interface_up(interface)before configuring static IPnetcfg_interface_up()would bring up the parent interface IFinterface->parentifwas set- But
parentifis explicitly set to NULL (line 1591 in netcfg-common.c) in the master branch - Only the VLAN interface itself is brought up, not the parent interface (but is fixed by the wrapper for
/sbin/ip)
-
S29vlan-setup: Creates the VLAN interface because
netcfgdoesn't parse thevlan=/proc/cmdline parameter nor create VLAN interfaces -
udhcpc wrapper: Brings up both parent and VLAN interfaces because:
netcfgbrings down all interfaces during initializationnetcfgcallsudhcpcwithout bringing interfaces back up- The Linux kernel does NOT automatically bring up the parent interface when you bring up a VLAN interface
-
ip wrapper wrapper: Brings up the parent interface for static IP configuration because:
netcfgcallsnetcfg_interface_up()which only brings up the VLAN interface (not the parent)- The
parentiffield is NULL in the master branch (only set in the unmerged VLAN patch) - Without the parent interface being UP, the VLAN interface cannot communicate
- The wrapper only adds a side effect (bringing up parent) and passes all commands through unchanged
All three wrappers are designed to be safe and non-intrusive:
- S29vlan-setup: Only runs once at startup, before
netcfgruns - udhcpc wrapper: Only brings up interfaces, then passes all arguments unchanged to the real
udhcpc - ip wrapper: Only triggers on
dev <vlan_interface>.<parent_interface>patterns, brings up parent as a side effect, then passes all arguments unchanged to the realipcommand
The wrappers do NOT modify any commands or arguments - they only add side effects (creating VLAN interface, bringing up interfaces) before executing the original commands normally.
- ✅ Debian 12 (Bookworm) installer
- ✅ DHCP configuration on VLAN interfaces
- ✅ Static IP configuration on VLAN interfaces
- ✅ All standard
ipcommand uses work normally (wrapper passes commands through unchanged)
These scripts are provided as-is for use with Debian installer. They implement functionality that was proposed but never merged into Debian's netcfg.