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?
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?
Tested on a Raspberry Pi 4B with
Raspbian Buster Lite 2020-02-13 updated on 2020-04-11.
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.
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
. Please also note that NetworkManager isn't supported by Raspbian out of the box.
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).
Disable the old stuff. Don't stop any service, only disable them! So it will take effect only on next boot. How to do it just follow to
pi@raspberrypi: ~$ sudo -Es # if not already done
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:~ # 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
Setup wpa_supplicant with this file and your settings for country=
, 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
proto=RSN WPA
}
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:~ # rfkill unblock 0
root@raspberrypi:~ # exit
root@raspberrypi:~ $
Reboot and good luck ;-)
It is possible that the RasPi gets a new ip addresses so you may have to look at it for the next connection with ssh.
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
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
But this is not the whole story. systemd-networkd checks if all interfaces are up before proceeding with startup depending services. With bonding we have slave interfaces (eth0, wlan0) that never signal that they are up. Its only the bond interface that comes up if at least one of its slaves is connected. So the check will fail with errors and long waiting on bootup. To manage this you have to modifiy the systemd-networkd-wait-online.service
. How to do it, please follow the instructions at
If finished that, 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): 0
Down Delay (ms): 0
Slave Interface: eth0
MII Status: up
Speed: 1000 Mbps
Duplex: full
Link Failure Count: 0
Permanent HW addr: dc:a6:32:4c:08:1b
Slave queue ID: 0
Slave Interface: wlan0
MII Status: up
Speed: Unknown
Duplex: Unknown
Link Failure Count: 1
Permanent HW addr: dc:a6:32:4c:08:1c
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 response.
For a more in-depth review of bonding you may have a look at Dynamic network failover prioritize wifi over ethernet.
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
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.
DNS=192.168.1.1
to/etc/systemd/network/04-eth.network
. (I am using an setup with static IP)… – user5950 Jul 17 '19 at 19:20