16

systemd-networkd can be used to replace the existing networking system on Raspbian.

How can I use it for general purposes for networking like DHCP server, name resolution, link-local addresses, mDNS and so on?

2 Answers 2

40

Tested on a Raspberry Pi 4B with
Raspbian Buster Lite 2020-02-13 updated on 2020-05-05.
For reference I use a fresh flashed SD Card with the tested version. Updates done with sudo apt update && sudo apt full-upgrade && sudo reboot.
Here you will find the last tested revision for Raspbian Stretch Lite.


♦ Abstract

Using systemd-networkd instead of default dhcpcd it is not meaningful in all cases.

networkd is a small and lean service to configure network interfaces, designed mostly for server use cases in a world with hotplugged and virtualized networking. Its configuration is similar in spirit and abstraction level to ifupdown, but you don't need any extra packages to configure bridges, bonds, vlan etc. It is not very suitable for managing WLANs yet; NetworkManager is still much more appropriate for such Desktop use cases. (5)

But for a RasPi laying near by a TV or amplifier and doing its work 24/7 for streaming audio or video or for a camera etc., systemd-networkd is a good choice.

But you have to do a complete switch. There is no way to mix up with Debian networking and/or dhcpcd.

For this tutorial I assume you have setup an installation from the image with a network connection either wired (works out of the box) or using a wireless connection so you can connect to it with ssh but haven't done any further configuration.


♦ Quick Step

Those who have already read the details and know how it works and only want to quick enable systemd-networkd will just do this here. But don't forget to configure the network interfaces with files in /etc/systemd/network/.

Please read at least the "♦ Abstract" section above and make a backup of your running system if you modify it!

# deinstall classic networking
pi@raspberrypi:~ $ sudo -Es   # if not already done
root@raspberrypi:~ # systemctl daemon-reload
root@raspberrypi:~ # systemctl disable --now ifupdown dhcpcd dhcpcd5 isc-dhcp-client isc-dhcp-common rsyslog
root@raspberrypi:~ # apt --autoremove purge ifupdown dhcpcd dhcpcd5 isc-dhcp-client isc-dhcp-common rsyslog
root@raspberrypi:~ # rm -r /etc/network /etc/dhcp

# setup/enable systemd-resolved and systemd-networkd
root@raspberrypi:~ # systemctl disable --now avahi-daemon libnss-mdns
root@raspberrypi:~ # apt --autoremove purge avahi-daemon
root@raspberrypi:~ # apt install libnss-resolve
root@raspberrypi:~ # ln -sf /run/systemd/resolve/stub-resolv.conf /etc/resolv.conf
root@raspberrypi:~ # apt-mark hold avahi-daemon dhcpcd dhcpcd5 ifupdown isc-dhcp-client isc-dhcp-common libnss-mdns openresolv raspberrypi-net-mods rsyslog
root@raspberrypi:~ # systemctl enable systemd-networkd.service systemd-resolved.service
root@raspberrypi:~ # exit
pi@raspberrypi:~ $

Return to your setup.


♦ Create interface file for a wired connection

I will have attention to a headless installation only with ssh. If you are also headless, double check typos or so otherwise you are lost with a broken connection. Deinstalling services does not effect the current network connection as long as you don't restart or reboot the network. So only do it if you are sure to have finished all needed configuration to have a working network.

First enable systemd-networkd by following section "♦ Quick Step". Then come back here.

If you are connected wired then create this interface file but with only one option enabled (uncommented). Most common is to use DHCP.

pi@raspberrypi:~ $ sudo -Es   # if not already done
root@raspberrypi:~ # cat > /etc/systemd/network/04-wired.network <<EOF
[Match]
Name=e*

[Network]
## Uncomment only one option block
# Option: using a DHCP server and multicast DNS
LLMNR=no
LinkLocalAddressing=no
MulticastDNS=yes
DHCP=ipv4

# Option: using link-local ip addresses and multicast DNS
#LLMNR=no
#LinkLocalAddressing=yes
#MulticastDNS=yes

# Option: using static ip address and multicast DNS
# (example, use your settings)
#Address=192.168.50.60/24
#Gateway=192.168.50.1
#DNS=84.200.69.80 1.1.1.1
#MulticastDNS=yes
EOF

Reboot.

If you connect using the ip address it is possible that this has also changed so you have to search for the new ip address.


♦ Create interface file for a WiFi connection

I will have attention to a headless installation only with ssh. If you are also headless, double check typos or so otherwise you are lost with a broken connection. Deinstalling services does not effect the current network connection as long as you don't restart or reboot the network. So only do it if you are sure to have finished all needed configuration to have a working network.

First enable systemd-networkd by following section ♦ Quick Step. Then come back here.

Create this file for wpa_supplicant with your settings for country=, ssid= and psk=:

pi@raspberrypi:~ $ sudo -Es   # if not already done
root@raspberrypi:~ # cat > /etc/wpa_supplicant/wpa_supplicant-wlan0.conf <<EOF
country=DE
ctrl_interface=DIR=/run/wpa_supplicant GROUP=netdev
update_config=1
p2p_disabled=1

network={
    ssid="TestNet"
    psk="testingPassword"
}
EOF

root@raspberrypi: ~# chmod 600 /etc/wpa_supplicant/wpa_supplicant-wlan0.conf
root@raspberrypi: ~# systemctl disable wpa_supplicant.service
root@raspberrypi: ~# systemctl enable wpa_su[email protected]
root@raspberrypi: ~# rfkill unblock wlan

Create an interface file with only one option enabled (uncommented). Most common is to use DHCP.

root@raspberrypi:~ # cat > /etc/systemd/network/08-wifi.network <<EOF
[Match]
Name=wl*

[Network]
## Uncomment only one option block
# Option: using a DHCP server and multicast DNS
LLMNR=no
LinkLocalAddressing=no
MulticastDNS=yes
DHCP=ipv4

# Option: using link-local ip addresses and multicast DNS
#LLMNR=no
#LinkLocalAddressing=yes
#MulticastDNS=yes

# Option: using static ip address and multicast DNS
# (example, use your settings)
#Address=192.168.50.61/24
#Gateway=192.168.50.1
#DNS=84.200.69.80 1.1.1.1
#MulticastDNS=yes
EOF

Reboot.

If you connect using the ip address it is possible that this has also changed so you have to search for the new ip address.


♦ Details to enable systemd-networkd

This is a detailed setup that you also have in short in section "♦ Quick Step".

To simplify commands we will work as root:

pi@raspberrypi:~ $ sudo -Es   # if not already done

Deinstall classic Debian networking that is managed with file /etc/network/interfaces and deinstall default Raspbian dhcpcd network management.

root@raspberrypi:~ # apt --autoremove purge ifupdown
root@raspberrypi:~ # rm -r /etc/network
root@raspberrypi:~ # apt --autoremove purge dhcpcd5
root@raspberrypi:~ # apt --autoremove purge isc-dhcp-client isc-dhcp-common
root@raspberrypi:~ # rm -r /etc/dhcp
root@raspberrypi:~ # apt --autoremove purge rsyslog

We will set this programs to hold so they are not authomatically installed with other programs later and conflict with systemd-networkd.

root@raspberrypi:~ # apt-mark hold ifupdown dhcpcd5 isc-dhcp-client isc-dhcp-common rsyslog raspberrypi-net-mods openresolv

And enable systemd-networkd:

root@raspberrypi:~ # systemctl enable systemd-networkd.service

♦ Details to enable systemd-resolved

This is a detailed setup that you also have in short in section "♦ Quick Step".

An important part of systemd networking is its network name resolution. systemd-resolved provides name services by Domain Name System (DNS) (including DNSSEC and DNS over TLS), Multicast DNS (mDNS) and Link-Local Multicast Name Resolution (LLMNR).(1)

systemd-resolved provides this to local applications via a D-Bus interface, the resolve NSS service (libnss-resolve), and a local DNS stub listener on 127.0.0.53 (1), (2). For all three software interfaces there are also traditional services installed which may conflict with systemd-resolved. On my tests I have seen problems in the order of name resolution: long response time depending on the amount of DNS server to use, queries for the .local domain going to DNS server, no responses to local host names if the internet connection was down and so on. So I will deinstall not needed services instead of only disable them. This should ensure that entries in common used static config files like /etc/nsswitch.conf will also cleaned up.

At first please follow section ♦ Details to enable systemd-networkd.

Then enable systemd-resolved and configure its three interfaces:

pi@raspberrypi:~ $ sudo -Es   # if not already done
root@raspberrypi:~ # systemctl enable systemd-resolved.service

Check D-Bus software interface

I haven't found any conflicting issues. The D-Bus should be installed by default and running. Check with:

root@raspberrypi:~ # systemctl status dbus.service

Configure NSS software interface

There is the avahi service together with the mdns service definitely conflicting, so we have to deinstall them. This will also clean up /etc/nsswitch.conf:

root@raspberrypi:~ # apt --autoremove purge avahi-daemon
root@raspberrypi:~ # apt-mark hold avahi-daemon

Now install the systemd-resolved software interface:

root@raspberrypi:~ # apt install libnss-resolve

For troubleshooting you may have a look at /etc/nsswitch.conf. It should contain a line like this:

hosts:          files resolve [!UNAVAIL=return] dns

Configure DNS stub listener interface

Here we have to symlink /etc/resolv.conf to the stub listener:

root@raspberrypi:~ # ln -sf /run/systemd/resolve/stub-resolv.conf /etc/resolv.conf

Don't Reboot! Before doing that you must have created an interface file for a wired or WiFi connection.

Check name resolution

Now you can check the status of name resolution. Depending on your settings it could look similar to this with a wireless connection:

pi@raspberrypi:~ $ resolvectl status
Global
       LLMNR setting: yes
MulticastDNS setting: yes
  DNSOverTLS setting: no
      DNSSEC setting: allow-downgrade
    DNSSEC supported: yes
--- snip ---

Link 3 (wlan0)
      Current Scopes: DNS LLMNR/IPv4 LLMNR/IPv6
DefaultRoute setting: yes
       LLMNR setting: yes
MulticastDNS setting: no
  DNSOverTLS setting: no
      DNSSEC setting: allow-downgrade
    DNSSEC supported: yes
  Current DNS Server: 84.200.69.80
         DNS Servers: 84.200.69.80
                      1.1.1.1

Link 2 (eth0)
      Current Scopes: none
DefaultRoute setting: no
       LLMNR setting: yes
MulticastDNS setting: no
  DNSOverTLS setting: no
      DNSSEC setting: allow-downgrade
    DNSSEC supported: yes

♦ Quirks and troubleshooting

Problem with DNSSEC

It should be said that there is a known bug. If you get error messages like:

DNSSEC validation failed for question google.com IN A: no-signature

then you hit Sporadic "DNSSEC validation failed" — "no-signature" #12388. You can workaround this with adding option DNSSEC=no to /etc/systemd/resolved.conf and reboot to disable DNS record signing.

DNS-name domain search trouble

According to a comment from @lbt there was a bug with the name search option given by the DHCP server. This option completes not full qualified DNS names. For example if you

rpi ~$ ping harley
PING harley.home.hoeft-online.de (192.168.30.121) 56(84) bytes of data.
64 bytes from harley.home.hoeft-online.de (192.168.30.121): icmp_seq=1 ttl=64 time=0.932 ms
--- snip ---

the domain search will complete the DNS name harley to harley.home.hoeft-online.de to get the ip address, where the domain home.hoeft-online.de is given by the DHCP-server (received together with the dynamic ip address). According to https://superuser.com/questions/1490670/does-systemd-networkd-systemd-resolved-add-search-domains-specified-in-dhcp there was a problem which was fixed with systemd v243. I have noticed that there was a problem with older systemd versions but was able to find a solution, because I have full access to my own powerful isc-dhcp-server. Here are the settings on a test client to get domain search working as you can see with the ping above:

rpi ~$ systemd --version
systemd 241 (241)
+PAM +AUDIT +SELINUX +IMA +APPARMOR +SMACK +SYSVINIT +UTMP +LIBCRYPTSETUP +GCRYPT +GNUTLS +ACL +XZ +LZ4 +SECCOMP +BLKID +ELFUTILS +KMOD -IDN2 +IDN -PCRE2 default-hierarchy=hybrid

rpi ~$ cat /etc/systemd/network/04-wired.network
[Match]
Name=e*

[Network]
LLMNR=no
MulticastDNS=yes
LinkLocalAddressing=no
DHCP=ipv4

[DHCP]
UseDomains=true

rpi ~$ ls -l /etc/resolv.conf
lrwxrwxrwx 1 root root 37 2020-12-18 16:52 /etc/resolv.conf -> /run/systemd/resolve/stub-resolv.conf

rpi ~$ cat /etc/resolv.conf
--- snip ---
nameserver 127.0.0.53
options edns0
search home.hoeft-online.de

The search line is received from the DHCP server. The essential is the setting on the ISC DHDP-server. Here the subnet setting from its /etc/dhcp/dhcpd.conf:

# My settings
subnet 192.168.30.0 netmask 255.255.255.0 {
    range 192.168.30.65 192.168.30.126;
    option routers 192.168.30.1;
    option domain-name "home.hoeft-online.de";
#    option domain-search "home.hoeft-online.de";
}

As you can see there are two options available. option domain-search doesn't work but I successful use option domain-name. The only restriction is, that you can only give one domain name. It is not possible to search for e.g. home.hoeft-online.de and hoeft-online.de.


references:
(1) - archlinux - systemd-resolved
(2) - freedesktop - systemd-resolved — Network Name Resolution manager
(3) - freedesktop - What is D-Bus?
(4) - archlinux - Domain name resolution
(5) - /usr/share/doc/systemd/README.Debian

18
  • 1
    This is a very good "how-to" for systemd-networkd. Reading your answer again has reminded me that it should be mentioned as an alternative to dhcpcd in some situations. In other words, dhcpcd would be for most users, and systemd-networkd for those with use-cases described in your abstract. Do you agree?
    – Seamus
    Sep 3, 2020 at 3:49
  • 1
    @Seamus Yes, I completely agree. Except with mobile using you have much more possibilities to do sophisticated things out of the box by just configuring it, or well integrated like VPN with wireguard, also just configurable by systemd-networkd. All this is well structured and straight forward without the need to fit different helpers together and without possible problems on its (different?) APis.
    – Ingo
    Sep 3, 2020 at 9:08
  • 1
    @JaromandaX Yes, you are right. Haven't thought of it but will make it next time now.
    – Ingo
    Feb 6, 2021 at 20:34
  • 1
    thanks @Ingo - lots of good info there Feb 7, 2021 at 22:17
  • 1
    Hi - name resolution broke, and apt install libnss-resolve failed. My hack fix was to add a couple of addresses to hosts. But I think it needs to be pre-downloaded for this to work well
    – mksteve
    Apr 7, 2021 at 8:37
2

Thanks @ingo for this guide and the other one to add the AP on the same wifi. Incredibly well written and useful.

I would like to emphase the DNSSEC=allow-downgrade issue as it took me a week and 3 complete re-install of my PI before I finally understood why I was getting more and more DNS errors, hour after hour to the point I was unable to do an apt update or apt install. On my x86 Ubuntu 20.04, resolved.conf come with DSSEC=no by default.

This bug seems to be present for quite some time in resolved: https://github.com/systemd/systemd/issues/10579.

2
  • Good comment - Do you know if this issue is triggered by the RPi's rather imprecise SNTP time-keeping mechanism - or is it something else?
    – Seamus
    Mar 16, 2021 at 21:30
  • @Seamus No idea. But the fact that the issue have been opened for 2.5 years and Ubuntu decided to package systemd-resoved with DNSSEC=no by default even on x86 may be a clue that this is a deep problem not easy to solve what ever the platform is. Probably not related to PI time management.
    – Barbudor
    Mar 17, 2021 at 22:45

Not the answer you're looking for? Browse other questions tagged or ask your own question.