An Overview and Cheat Sheet for systemd networkd configurations
2023-09-23
This is a short cheat sheet for things that I often need to do with systemd-networkd, the network configuraton component of systemd. This post assumes some basic knowledge about systemd-networkd and is primarily a collection of examples.
CLI overview
The CLI tool for systemd-networkd is networkctl
.
networkctl
shows a short status over all interfaces
networkctl reload
reloads and applies the configuration of all interfaces.
networkctl status
shows a general status as well as the logs.
Check the logs if something does not work as intended.
Syntax errors and the like are logged here.
The logs can also be accessed via the journal, usually with journalctl -xef -u systemd-networkd
Configuration Files
systemd-networkd is configured via files usually located in /etc/systemd/network/
.
There are 3 kinds of files
.link
-files that are used for renaming interfaces (Documentation).netdev
-files that are creating interfaces (Documentation).network
-files that handle the L3-behaviour of those interfaces (Documentation)
The files are loaded sorted by their name, so it is a good practice to name them starting with numbers to define their order.
Interface renaming
To rename a interface we can first match on some parameters and then give it a new name:
# 00-iface42.link
[Match]
MACAddress=11:22:33:44:55:66
Type=ether
[Link]
Name=iface42
The Type=ether
is important when you want to create VLAN interfaces on the
renamed interface.
By default the VLAN Interfaces would have the same MAC addresses as the main
interface.
If only the MAC address is matched then the main interface and the VLAN interfaces
would all be renamed, leading to hard to find errors.
The Type=ether
matches only on the ethernet interface, because the VLAN interfaces
have vlan
as their type.
Source: systemd-devel mailing list
VLAN Interfaces
First we have to create the VLAN Interface eth1.102 and assign it the VLAN-ID 102
# 10-eth1.102.netdev
[NetDev]
Name=eth1.102
Kind=vlan
[VLAN]
Id=102
Note that the name of the interface can be chosen arbitrarily and does not have to contain the vlan id.
Then we can assign the VLAN to an other interface:
# 10-eth1.network
[Match]
Name=eth1
[Network]
VLAN=eth1.102
VRFs
Each VRF needs a routing table assigned to it. In this example it is table 102.
# 10-vrf-uplink-1.netdev
[NetDev]
Name=vrf-uplink-1
Kind=vrf
[VRF]
TableId=102
To bring the VRFs up you need a network file for them. You can use the same file for all your VRFs. An easy example would be
# 99-vrf.network
[Match]
Kind=vrf
[Link]
ActivationPolicy=up
RequiredForOnline=no
Some manuals suggest to match the name here, e.g. Name=vrf-*
,
however this requires all your vrfs to start with vrf-
which might not be
the case.
To assign an interface to a VRF, create a network file for that interface:
# 20-eth2.network
[Match]
Name=eth2
[Network]
VRF=vrf-uplink-1
Assigning IP Addresses
SLAAC + DHCP
To run SLAAC for IPv6 and DHCP for legacy IP a network file is added:
[Match]
Name=eth0
[Network]
DHCP=yes
IPv6AcceptRA=yes
IPv6PrivacyExtensions=yes
The handling of IPv6 RAs is a bit complicated, check the documentation for IPv6AcceptRA for details.
The IPv6PrivacyExtensions=yes
enables IPv6 privacy extensions.
The set the route metric (this is relevant if you have multiple interfaces and e.g. want to prefer your wired over your wireless interface) add the following lines:
...
[DHCPv4]
RouteMetric=200
[IPv6AcceptRA]
RouteMetric=200
Static Addresses
[Match]
Name=wg-1
[Network]
Address=2a0a:4587:2001:1015::/127
Routes
Static routes can be added with the [Route]
config section in the network
files.
To add more routes, simply add more [Route]
config sections.
[Route]
Destination=10.42.123.0/28
Gateway=192.0.2.1
[Route]
Destination=2001:db8:101::/46
Gateway: 2001:db8::1
Wireguard Tunnels
For Wireguard a keypair is needed which can be generated with
mkdir -p /etc/wireguard
cd /etc/wireguard
wg genkey | tee privatekey | wg pubkey > publickey
Then the netdev looks like this
[NetDev]
Name=wg-1
Kind=wireguard
[WireGuard]
PrivateKeyFile=/etc/wireguard/privkey
ListenPort=51820
# for a client we only want to listen for but not actively connect to
[WireGuardPeer]
PublicKey=<peers public key here>
AllowedIPs=::/0, 0.0.0.0/0
# for a peer to which we want to connect to
[WireGuardPeer]
PublicKey=<peers public key here>
AllowedIPs=::/0, 0.0.0.0/0
Endpoint=[2001:db8::1234]:51821
Additionally a network file is needed:
[Match]
Name=wg-1
[Network]
Address=172.16.44.1/31