Using systemd-networkd to work your net

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.

James McDonald

Senior Systems Consultant at Redpill Linpro

James just recently started at Redpill Linpro. He's been working with FOSS since the late 90s, and tinkering with it for rather longer. His background is in system administration and architecture. He has recently been experimenting with beards.