On a laptop, per-distribution network tools like ifupdown
,
network-scripts and netcfg are a bit limiting. NetworkManager is a
reasonable solution to roaming and using multiple networks, but for
those of us who don’t run environments like GNOME, it’s a little opaque,
even now that it has nmcli.
Systemd includes a component systemd-networkd to manage network connections. It turns out it’s simple, light, fast and pretty easy to configure. The trick is mostly making sure that the correct components are started, and components that might interfere are disabled.
This post takes you through this setup on a Debian machine, with support for wired and wireless adapters in a roaming DHCP configuration. You may need to adapt these configurations to match the interface names your machine has, and of course make sure your network interfaces actually operate properly! You might need to sort out firmware, etc.
Install and remove software
I recommend enabling backports and installing the most recent version of systemd. The version in Jessie (215) will not allow you to specify metrics per interface, and its IPv6 support seemed a little flaky in my experiments.
echo 'deb http://httpredir.debian.org/debian jessie-backports main' \
> /etc/apt/sources.list.d/jessie-backports.list
apt-get update
If you have NetworkManager or rdnssd installed, I recommend just removing them. Bear in mind that removing NetworkManager might stop your network connections! Regarding rdnssd, see Caveats below.
This should fetch everything you will need:
apt-get install -t jessie-backports systemd wpasupplicant
apt-get autoremove --purge network-manager rdnssd
Update ifupdown configuration
You should remove any interfaces you want to manage with systemd-networkd from ifupdown management. In this example, those are eth0 and wlan0. First, take down the interfaces:
ifdown eth0
ifdown wlan0
Then edit /etc/network/interfaces
and comment out or remove the
configuration for these interfaces.
Configure systemd-networkd
You will be using another systemd component, systemd-resolved, to manage resolv.conf. For that to work, you must remove the existing file and make a link:
rm /etc/resolv.conf
ln -s /run/systemd/resolve/resolv.conf /etc/resolv.conf
Set up two network configurations as follows.
/etc/systemd/network/wired.network
[Match]
Name=eth0
[Network]
DHCP=both
[DHCP]
RouteMetric=10
/etc/systemd/network/wireless.network
[Match]
Name=wlan0
[Network]
DHCP=both
[DHCP]
RouteMetric=20
The only difference between these is the route metric. With this configuration, wired connections will be prioritised above wireless connections, which in my case is usually what I want.
Enable and start services
A nice simple part! Enable the services so they start on next boot and then start them:
systemctl enable systemd-resolved.service
systemctl enable systemd-networkd.service
systemctl start systemd-resolved.service
systemctl start systemd-networkd.service
At this point your wired interface should simply work if it’s connected.
You can see logs from systemd-networkd using journalctl -f
.
Get wireless working
You have now configured the IP setup for the wireless interface, but it won’t do anything until the interface actually connects to a wireless network. You can do this part using wpa_supplicant.
Create a systemd service for your interface:
/etc/systemd/system/wpa_supplicant@wlan0.service
[Unit]
Description=WPA supplicant for %i
[Service]
ExecStart=/sbin/wpa_supplicant -i%i -c/etc/wpa_supplicant/wpa_supplicant.conf
[Install]
WantedBy=multi-user.target
Set up your wpa_supplicant.conf with credentials for the networks you want to use. You should consult the wpa_supplicant manual for details. Here’s an example with the open network NSB use on their trains in Norway, and a sample office network.
/etc/wpa_supplicant/wpa_supplicant.conf
ctrl_interface=DIR=/run/wpa_supplicant GROUP=netdev
network={
ssid="NSB_INTERAKTIV"
key_mgmt=NONE
}
network={
ssid="MyOfficeNetwork"
psk="a very secret key indeed"
}
You can add update_config=1
to this file if you want to be able to
experiment with wpa_cli
or wpa_gui
and save the results.
Enable and start services for wireless
Also stop any existing wpa_supplicant, just to be on the safe side.
systemctl stop wpa_supplicant
systemctl disable wpa_supplicant
systemctl enable wpa_supplicant@wlan0
systemctl start wpa_supplicant@wlan0
Your wireless network should now associate, and then systemd-networkd
will pick it up and assign an address. You can query wpa_supplicant
using wpa_cli
, and again you can see what systemd-networkd is up to with
journalctl -f
.
Caveats
- IPv6 RDNSS doesn’t work properly with this setup for the moment, but if you have rdnssd running it will constantly stomp your resolv.conf with settings which may be stale (actually, it has the same problem with NetworkManager). If you rely on RDNSS in your network, you can try using rdnssd instead of systemd-resolved.