Antoine Beaupré: Kernel-only network configuration on Linux
What if I told you there is a way to configure the network on any
Linux server that:
- works across all distributions
- doesn’t require any software installed apart from the kernel and a
boot loader (nosystemd-networkd,ifupdown,NetworkManager,
nothing) - is backwards compatible all the way back to Linux 2.0, in 1996
It has literally 8 different caveats on top of that, but is still
totally worth your time.
Known options in Debian
People following Debian development might have noticed there are now
four ways of configuring the network Debian system. At least that is
what the Debian wiki claims, namely:
-
ifupdown(/etc/network/interfaces): traditional static
configuration system, mostly for workstations and servers that has
been there forever in Debian (since at least 2000), documented
in the Debian wiki -
NetworkManager: self-proclaimed “standard Linux network
configuration”, mostly used on desktops but technically supports
servers as well, see the Debian wiki page (introduced in 2004) -
systemd-network: used more for servers, see Debian reference Doc
Chapter 5 (introduced some time around Debian 8 “jessie”, in
2015) -
Netplan: latest entry (2018), YAML-based configuration
abstraction layer on top of the above two, see also Debian
reference Doc Chapter 5 and the Debian wiki
At this point, I feel ifupdown is on its way out, possibly replaced
by systemd-networkd. NetworkManager already manages most desktop
configurations.
A “new” network configuration system
The method is this:
ip=on the Linux kernel command line: for servers with a
single IPv4 or IPv6 address, no software required other than the
kernel and a boot loader (since 2002 or older)
So by “new” I mean “new to me”. This option is really old. The
nfsroot.txtwhere it is documented predates the git import of the
Linux kernel: it’s part of the 2005 git import of 2.6.12-rc2. That’s
already 20+ years old already.The oldest trace I found is in this 2002 commit, which imports
the whole file at once, but the option might goes back as far as
1996-1997, if the copyright on the file is correct and the option
was present back then.
What are you doing.
The trick is to add an ip= parameter to the kernel’s
command-line. The syntax, as mentioned above, is in nfsroot.txt
and looks like this:
ip=<client-ip>:<server-ip>:<gw-ip>:<netmask>:<hostname>:<device>:<autoconf>:<dns0-ip>:<dns1-ip>:<ntp0-ip>
Most settings are pretty self-explanatory, if you ignore the useless
ones:
<client-ip>: IP address of the server<gw-ip>: address of the gateway<netmask>: netmask, in quad notation<device>: interface name, if multiple available<autoconf>: how to configure the interface, namely:offornone: no autoconfiguration (static)onorany: use any protocol (default)dhcp, essentially likeonfor all intents and purposes
<dns0-ip>,<dns1-ip>: IP address of primary and secondary name
servers, exported to/proc/net/pnp, can by symlinked to
/etc/resolv.conf
We’re ignoring the options:
<server-ip>: IP address of the NFS server, exported to/proc/net/pnp<hostnname>: Name of the client, typically sent over the DHCP
requests, which may lead to a DNS record to be created in some
networks<ntp0-ip>: exported to/proc/net/ipconfig/ntp_servers, unused by
the kernel
Note that the Red Hat manual has a different opinion:
ip=[<server-id>]:<gateway-IP-number>:<netmask>:<client-hostname>:inteface:[dhcp|dhcp6|auto6|on|any|none|off]
It’s essentially the same (although server-id is weird), and the
autoconf variable has other settings, so that’s a bit odd.
Examples
For example, this command-line setting:
ip=192.0.2.42::192.0.2.1:255.255.255.0:::off
… will set the IP address to 192.0.2.42/24 and the gateway to
192.0.2.1. This will properly guess the network interface if there’s a
single one.
A DHCP only configuration will look like this:
ip=::::::dhcp
Of course, you don’t want to type this by hand every time you boot the
machine. That wouldn’t work. You need to configure the kernel
commandline, and that depends on your boot loader.
GRUB
With GRUB, you need to edit (on Debian), the file /etc/default/grub
(ugh) and find a line like:
GRUB_CMDLINE_LINUX=
and change it to:
GRUB_CMDLINE_LINUX=ip=::::::dhcp
systemd-boot and UKI setups
For systemd-boot UKI setups, it’s simpler: just add the setting to
the /etc/kernel/cmdline file. Don’t forget to include anything
that’s non-default from /proc/cmdline.
This assumes that is the Cmdline=@ setting in
/etc/kernel/uki.conf. See 2025-08-20-luks-ukify-conversion for
my minimal documentation on this.
Other systems
This is perhaps where this is much less portable than it might first
look, because of course each distribution has its own way of
configuring those options. Here are some that I know of:
- Arch (11 options, mostly
/etc/default/grub,
/boot/loader/entries/arch.confforsystemd-bootor
/etc/kernel/cmdlinefor UKI) - Fedora (mostly
/etc/default/grub, may be more RHEL mentions
grubby, possibly somesystemd-bootthings here as well) - Gentoo (5 options, mostly
/etc/default/grub,
/efi/loader/entries/gentoo-sources-kernel.confforsystemd-boot,
or/etc/kernel/install.d/95-uki-with-custom-opts.install)
It’s interesting that /etc/default/grub is consistent across all
distributions above, while the systemd-boot setups are all over the
place (except for the UKI case), while I would have expected those be
more standard than GRUB.
dropbear-initramfs
If dropbear-initramfs is setup, it already requires you to have
such a configuration, and it might not work out of the box.
This is because, by default, it disables the interfaces configured
in the kernel after completing its tasks (typically unlocking the
encrypted disks).
To fix this, you need to disable that “feature”:
IFDOWN="none"
This will keep dropbear-initramfs from disabling the configured
interface.
Why?
Traditionally, I’ve always setup my servers with ifupdown on servers
and NetworkManager on laptops, because that’s essentially the
default. But on some machines, I’ve started using systemd-networkd
because ifupdown has … issues, particularly with reloading network
configurations. ifupdown is a old hack, feels like legacy, and is
Debian-specific.
Not excited about configuring another service, I figured I would try
something else: just configure the network at boot, through the kernel
command-line.
I was already doing such configurations for dropbear-initramfs
(see this documentation), which requires the network the be up
for unlocking the full-disk encryption keys.
So in a sense, this is a “Don’t Repeat Yourself” solution.
Caveats
Also known as: “wait, that works?” Yes, it does! That said…
-
This is useful for servers where the network configuration will
not change after boot. Of course, this won’t work on laptops or
any mobile device. -
This only works for configuring a single, simple, interface. You
can’t configure multiple interfaces, WiFi, bridges, VLAN, bonding,
etc. -
It does support IPv6 and feels like the best way to configure IPv6
hosts: true zero configuration. -
It likely does not work with a dual-stack IPv4/IPv6 static
configuration. It might work with a dynamic dual stack
configuration, but I doubt it. -
I don’t know what happens when a DHCP lease expires. No daemon
seems to be running so I assume leases are not renewed, so this is
more useful for static configurations, which includes server-side
reserved fixed IP addresses. (A non-renewed lease risks getting
reallocated to another machine, which would cause an addressing
conflict.) -
It will not automatically reconfigure the interface on link
changes, butifupdowndoes not either. -
It will not write
/etc/resolv.conffor you but thedns0-ip
anddns1-ipdo end up in/proc/net/pnpwhich has a compatible
syntax, so a common configuration is:ln -s /proc/net/pnp /etc/resolv.conf -
I have not really tested this at scale: only a single, test
server at home.
Yes, that’s a lot of caveats, but it happens to cover a lot of
machines for me, and it works surprisingly well. My main doubts are
about long-term DHCP behaviour, but I don’t see why that would be a
problem with a statically defined lease.
Cleanup
Once you have this configuration, you don’t need any “user” level
network system, so you can get rid of everything:
apt purge systemd-networkd ifupdown network-manager netplan.io
Note that ifupdown (and probably others) leave stray files in (e.g.)
/etc/network which you might want to cleanup, or keep in case all
this fails and I have put you in utter misery. Configuration files for
other packages might also be left behind, I haven’t tested this, no
warranty.
Credits
This whole idea came from the A/I folks (not to be confused with
AI) who have been doing this forever, thanks!
