12

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

How does it work with Raspbian on a Raspberry Pi with two interfaces for ethernet and wlan? Can I also realize dynamic failover for them?

20

Tested on a Raspberry Pi 4B with
Raspbian Buster Lite 2019-07-10 updated on 2019-08-15.
Updates done with sudo apt update && sudo apt full-upgrade && sudo reboot.

It will not work with Raspbian Stretch!
Here you will find the last tested revision for Raspbian Stretch Lite.


Using systemd-networkd instead of default dhcpcd is of course possible. But 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. [1]

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 networking and/or dhcpcd.


♦ Step 1: Preparation

For reference I use a fresh flashed SD Card from Raspbian Buster Lite 2019-07-10.

I will have attention to a headless installation only with ssh. If you are using this, double check typos or so otherwise you are lost with a broken connection. If you want a headless installation then look at SSH (Secure Shell) and follow section 3. Enable SSH on a headless Raspberry Pi (add file to SD card on another machine).

For troubleshooting on shutdown or to check messages from previous boots you can enable persistent logging in journald for messages from systemd [1]. Because it produces big log files and storage place may be an issue I suggest to enable it only if needed. systemd-networkd does not need it and logging of the current session is always available.

pi@raspberrypi: ~$ sudo mkdir -p /var/log/journal
pi@raspberrypi: ~$ sudo systemd-tmpfiles --create --prefix /var/log/journal

Disable the old stuff. Don't stop any service, only disable them! So it will take effect only on next boot.

pi@raspberrypi: ~$ sudo -Es

In /etc/resolvconf.conf insert these lines.

# Set to NO to disable resolvconf from running any subscribers. Defaults to YES.
resolvconf=NO

Then disable classic Debian networking that is managed with file /etc/network/interfaces and disable default Raspbian dhcpcd network management. We mask it so they are completely disabled and cannot be started by other services.

root@raspberrypi: ~# systemctl mask networking.service
root@raspberrypi: ~# mv /etc/network/interfaces /etc/network/interfaces~
root@raspberrypi: ~# systemctl mask dhcpcd.service

And enable systemd-networkd:

root@raspberrypi: ~# systemctl enable systemd-networkd.service
root@raspberrypi: ~# systemctl enable systemd-resolved.service
root@raspberrypi: ~# ln -sf /run/systemd/resolve/resolv.conf /etc/resolv.conf

♦ Step 2: Setup the wired ethernet interface (eth0)

Create this file with your settings. You can just copy and paste this in one block to your command line beginning with cat and including both EOF (delimiter EOF will not get part of the file):

root@raspberrypi: ~# cat >/etc/systemd/network/04-eth.network <<EOF
[Match]
Name=e*
[Network]
# to use static IP (with your settings) toggle commenting the next 8 lines.
#Address=192.168.50.60/24
#DNS=84.200.69.80 1.1.1.1
#[Route]
#Gateway=192.168.50.1
#Metric=10
DHCP=yes
[DHCP]
RouteMetric=10
EOF

root@raspberrypi: ~# exit
pi@raspberrypi: ~$

Reboot, but only if you have an ethernet cord attached ;-)

It is possible that the RasPi gets a new ip address so you may have to look at it for the next connection with ssh.


♦ Step 3: Setup wlan interface (wlan0)

Create this file with your settings:

pi@raspberrypi:~ $ sudo -Es
root@raspberrypi:~ # cat >/etc/systemd/network/08-wifi.network <<EOF
[Match]
Name=wl*
[Network]
# to use static IP (with your settings) toggle commenting the next 8 lines.
#Address=192.168.50.61/24
#DNS=84.200.69.80 1.1.1.1
#[Route]
#Gateway=192.168.50.1
#Metric=20
DHCP=yes
[DHCP]
RouteMetric=20
EOF

root@raspberrypi:~ #

Setup wpa_supplicant with this file and your settings for ssid= and psk= and enable it:

root@raspberrypi:~ # cat >/etc/wpa_supplicant/wpa_supplicant-wlan0.conf <<EOF
ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev
update_config=1
country=DE

network={
    ssid="TestNet"
    psk="realyNotMyPassword"
    key_mgmt=WPA-PSK
}
EOF

root@raspberrypi:~ # chmod 600 /etc/wpa_supplicant/wpa_supplicant-wlan0.conf
root@raspberrypi:~ # systemctl disable wpa_supplicant.service
root@raspberrypi:~ # systemctl enable wpa_supplicant@wlan0.service
root@raspberrypi:~ # exit
root@raspberrypi:~ $

Reboot if you have a wifi connection. Most of you will have. Good luck ...

It is possible that the RasPi gets a new ip address so you may have to look at it for the next connection with ssh.


♦ Step 4: Bonding wired and wifi interface for failover

You should have both interfaces setup and running as described above. It is no problem when both interfaces are up. The kernel will use the interface with the lowest metric first. Here the ethernet interface will be used first. But this has a great disadvantage. As you can see with ~$ ip addr each interface has it's own ip-address. If the kernel switches the interface because one is gone down it also uses its new source ip-address. This will break any established statefull TCP communication, e.g. ssh, streaming, login sessions and so on. You can use a new connection from the changed source ip address but the old connections are stuck. That isn't really what we want.

The solution of this problem is bonding. We create an interim interface bond0 that does not change its settings. The wired and wifi interface will switch to bond0.

First disable the single ethernet and wifi network files:

pi@raspberrypi:~ $ sudo -Es
root@raspberrypi:~ # cd /etc/systemd/network/
root@raspberrypi:~ # mv 04-eth.network 04-eth.network~
root@raspberrypi:~ # mv 08-wifi.network 08-wifi.network~

Then setup bonding with these four files:

root@raspberrypi:~ # cat >/etc/systemd/network/02-bond0.netdev <<EOF
[NetDev]
# status: cat /proc/net/bonding/bond0
Name=bond0
Kind=bond
[Bond]
Mode=active-backup
# primary slave is defined in *eth.network
MIIMonitorSec=500ms
UpDelaySec=1000ms
DownDelaySec=1000ms
MinLinks=1
EOF

root@raspberrypi:~ # cat >/etc/systemd/network/12-bond0-add-eth.network <<EOF
[Match]
Name=e*
[Network]
Bond=bond0
PrimarySlave=yes
EOF

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

root@raspberrypi:~ # cat >/etc/systemd/network/20-bond0-up.network <<EOF
[Match]
Name=bond0
[Network]
# to use static IP (with your settings) toggle commenting the next 4 lines.
DHCP=yes
#Address=192.168.50.60/24
#Gateway=192.168.50.1
#DNS=84.200.69.80 1.1.1.1
EOF

root@raspberrypi:~ # exit
pi@raspberrypi:~ $

Now it's time to reboot.

It is possible that the RasPi gets a new ip address so you may have to look at it for the next connection with ssh.

Then you can check the bonding status:

pi@raspberrypi:~ $ cat /proc/net/bonding/bond0
Ethernet Channel Bonding Driver: v3.7.1 (April 27, 2011)

Bonding Mode: fault-tolerance (active-backup)
Primary Slave: eth0 (primary_reselect always)
Currently Active Slave: eth0
MII Status: up
MII Polling Interval (ms): 500
Up Delay (ms): 1000
Down Delay (ms): 1000

Slave Interface: eth0
MII Status: up
Speed: 1000 Mbps
Duplex: full
Link Failure Count: 0
Permanent HW addr: b8:27:eb:53:bd:de
Slave queue ID: 0

Slave Interface: wlan0
MII Status: up
Speed: Unknown
Duplex: Unknown
Link Failure Count: 0
Permanent HW addr: b8:27:eb:06:e8:8b
Slave queue ID: 0

Test bonding: with the bonding status above you will see that the Currently Active Slave: will change and the MII Status: is down.

If your are headless, don't down both interfaces together ;-)

pi@raspberrypi:~ $ ip addr
pi@raspberrypi:~ $ sudo ip link set eth0 down
pi@raspberrypi:~ $ sudo ip link set eth0 up
pi@raspberrypi:~ $ sudo ip link set wlan0 down
pi@raspberrypi:~ $ sudo ip link set wlan0 up

Be patient after setting wlan0 up. I may take some time to reconnect to the router and manage bonding. This time ssh will not work.


♦ Step 5: Clean up

Purge the old stuff:

pi@raspberrypi:~ $ sudo apt --autoremove purge openresolv
pi@raspberrypi:~ $ sudo apt --autoremove purge ifupdown
pi@raspberrypi:~ $ sudo apt --autoremove purge dhcpcd5
pi@raspberrypi:~ $ sudo apt --autoremove purge isc-dhcp-client isc-dhcp-common


references:
[1] /usr/share/doc/systemd/README.Debian.gz
[2] man systemd.netdev
[3] man systemd.network
[4] https://wiki.debian.org/Bonding
[5] https://www.kernel.org/doc/Documentation/networking/bonding.txt

  • Note with regard to the first quote up top: Raspbian never used NetworkManager. It is more an artifact of Fedora and derived systems (which was the first place that systemd, a Redhat supported project, was deployed). – goldilocks Feb 10 '18 at 12:49
  • Also applicable to other Debian based systems not necessarily running on ARM :) Thank you for the concise explanation. – TCB13 Jun 29 at 16:29
  • This worked for my on stretch but on buster I encountered the problem, that my device cant resolve any domain. Any ideas what could be the cause? – user5950 Jul 17 at 12:40
  • @user5950 Maybe there has something changed with buster? I will look at it. Just a moment please. – Ingo Jul 17 at 12:46
  • @Ingo Thank you for the fast replay. I could resolve the problem by adding the line DNS=192.168.1.1 to /etc/systemd/network/04-eth.network. (I am using an setup with static IP)… – user5950 Jul 17 at 19:20
1

To elaborate the answer from @Ingo: please consider using the link

ln -s /run/systemd/resolve/stub-resolv.conf resolv.conf

instead of the link to /run/systemd/resolve/resolv.conf. This enable the "integrated" DNS stub and enables things like per-interface DNS server which could be important if you use VPNs that provide their own DNS server with non-public entries.

New contributor
Robert James is a new contributor to this site. Take care in asking for clarification, commenting, and answering. Check out our Code of Conduct.
  • Very interesting, thank you for feedback. Is there any documentation and/or sources of this? If so please edit your answer (using the link below it) and add it there. – Ingo Nov 11 at 9:18

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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