Systemd/networkd: Difference between revisions
imported>Mweinelt |
→Debugging: note runtime log level changing |
||
(46 intermediate revisions by 16 users not shown) | |||
Line 1: | Line 1: | ||
{{Systemd/breadcrumb}} | |||
{{DISPLAYTITLE:systemd-networkd}} | |||
[https://www.freedesktop.org/software/systemd/man/systemd-networkd.html systemd-networkd] is the network configuration component of the [[systemd]][[Category:systemd]] software suite. It is well integrated into NixOS below {{Nixos:option|systemd.network}} and should be preferred over {{Nixos:option|networking.interfaces}} options for most use cases, since it receives far superior maintenance. | |||
Configuration for networkd is split into three sections. | Configuration for networkd is split into three sections. | ||
* | * {{Nixos:option|systemd.network.links}} reconfigures existing network devices | ||
** https://www.freedesktop.org/software/systemd/man/systemd.link.html | ** https://www.freedesktop.org/software/systemd/man/systemd.link.html | ||
** actually implemented by udev, not networkd | ** actually implemented by udev, not networkd | ||
* | * {{Nixos:option|systemd.network.netdevs}} creates virtual network devices | ||
** https://www.freedesktop.org/software/systemd/man/systemd.netdev.html | ** https://www.freedesktop.org/software/systemd/man/systemd.netdev.html | ||
* | * {{Nixos:option|systemd.network.networks}} configures network devices | ||
** https://www.freedesktop.org/software/systemd/man/systemd.network.html | ** https://www.freedesktop.org/software/systemd/man/systemd.network.html | ||
In most simple scenarios configuring existing network devices is what you want to do. | In most simple scenarios configuring existing network devices is what you want to do. | ||
== Basics == | |||
=== When to use === | |||
Use systemd-networkd for setups that rely on static configuration, that doesn't change much during its lifetime, that does not require varying profiles for a single interface. Common examples are: | |||
* Servers/Routers | |||
* Always-On VPN Tunnels | |||
Following that logic, it is less suitable to | |||
* Varying WLAN profiles | |||
* Selectively used VPN tunnels | |||
These use cases are better served by [[NetworkManager]] and its various frontends, that provides a better integrated user experience for various desktop systems. | |||
{{Note|Both systemd-networkd and NetworkManager can exist in parallel on the same machine, when they manage a distinct set of interfaces. If upstream connectivity is managed by NetworkManager (for example, NM handles wifi and networkd does VM networking), set {{Nixos:option|systemd.network.wait-online.enable}} to false so that boot isn't blocked on connectivity that networkd will never provide.}} | |||
=== Enabling === | === Enabling === | ||
To be able to use networkd configuration it needs to be enabled first. | To be able to use networkd configuration, it needs to be enabled first. | ||
<syntaxhighlight lang="nix"> | <syntaxhighlight lang="nix"> | ||
Line 21: | Line 39: | ||
</syntaxhighlight> | </syntaxhighlight> | ||
Some guides will mention the | Some guides will mention the {{Nixos:option|networking.useNetworkd}} option, which | ||
offers translation of some | in addition to enabling systemd-networkd, also offers translation of some | ||
can write your complete network setup in native networkd configuration, you should | {{Nixos:option|networking.interfaces}} and {{Nixos:option|networking.useDHCP}} options | ||
stay away from that option. | into networkd. | ||
If you can write your complete network setup in native networkd configuration, you | |||
should stay away from that option. | |||
=== Configuring === | === Configuring === | ||
Line 31: | Line 51: | ||
interface stored in <code>/etc/systemd/network</code>. | interface stored in <code>/etc/systemd/network</code>. | ||
The following | The following declaration in your NixOS configuration | ||
<syntaxhighlight lang="nix"> | <syntaxhighlight lang="nix"> | ||
Line 50: | Line 70: | ||
</nowiki>}} | </nowiki>}} | ||
Note that we usually prefix the configuration file with a number. This can be important, | Note that we usually prefix the configuration file with a number. This can be important, because networkd collects all available configuration files, then sorts them alphanumerically, and uses the first match for each interface as its configuration. This happens separately for <code>.link</code>, <code>.netdev</code> and <code>.network</code> files, so that you can have one configuration of each type per interface. | ||
because networkd collects all available configuration files, then sorts them | |||
and uses the first match for each interface as its configuration. This happens separately | === Debugging === | ||
for <code>.link</code>, <code>.netdev</code> and <code>.network</code> files, so | |||
that you can have one configuration of each type per interface. | When things don't work as expected, the journal for <code>systemd-networkd.service</code> should be consulted. Unfortunately, by default the log is not very useful in its default loglevel. Increasing the loglevel can be done using the <code>SYSTEMD_LOG_LEVEL</code> environment variable. | ||
<syntaxhighlight lang="nix"> | |||
systemd.services."systemd-networkd".environment.SYSTEMD_LOG_LEVEL = "debug"; | |||
</syntaxhighlight>Log level can also be changed at runtime with<syntaxhighlight lang="bash"> | |||
$ systemctl service-log-level systemd-networkd.service debug | |||
# or | |||
$ systemctl service-log-level systemd-networkd.service info | |||
</syntaxhighlight> | |||
=== Limitations === | === Limitations === | ||
Some limitations might be surprising, so it is probably helpful to get them out of the way early. | |||
* {{Nixos:option|systemd.network.links}} | |||
** Executed by udev and only applied on boot | |||
* {{Nixos:option|systemd.network.netdevs}} | |||
** Does not modify properties (e.g., MTU, VLAN ID, VXLAN ID, Wireguard Peers) of existing netdevs | |||
*** https://github.com/systemd/systemd/issues/9627 | |||
*** This should be fixed as of systemd v257 (https://github.com/systemd/systemd/pull/34909) | |||
=== network-online.target === | === network-online.target === | ||
Line 100: | Line 122: | ||
<syntaxhighlight lang="nix"> | <syntaxhighlight lang="nix"> | ||
systemd.network."50-enp3s0" = { | systemd.network.networks."50-enp3s0" = { | ||
matchConfig.Name = "enp3s0"; | matchConfig.Name = "enp3s0"; | ||
# acquire a DHCP lease on link up | # acquire a DHCP lease on link up | ||
Line 116: | Line 138: | ||
entirely, because a working <code>network-online.target</code> is required for some | entirely, because a working <code>network-online.target</code> is required for some | ||
services to properly start without race conditions. | services to properly start without race conditions. | ||
Also consider enabling the <code>systemd.network.wait-online.anyInterface</code> option, | |||
which makes networkd consider the network online when any interface is online, | |||
as opposed to all that have a positive value for <code>linkConfig.RequiredForOnline</code>. | |||
This is useful on portable machines with a wired and a wireless interface, for example. | |||
Recommended documentation: | Recommended documentation: | ||
Line 125: | Line 152: | ||
Examples should be concise and give proper hints on how to achieve a reliably working <code>network-online.target</code>. | Examples should be concise and give proper hints on how to achieve a reliably working <code>network-online.target</code>. | ||
=== Interface Naming === | |||
The name of an interface can be changed based on different matches. This is useful for pretty names (e.g. wan, lan), but also if you want to make sure that your interface name never changes. This might be useful because even with predictable interface naming your interface name can change, for example when you add a new PCIe card and indexing changes, or due to kernel changes the way your mainboard gets interpreted changes.<syntaxhighlight lang="nix"> | |||
systemd.network.links."10-wan" = { | |||
# Check systemd.link(5) for other matchers | |||
matchConfig.Path = "pci-0000:09:00.0"; | |||
linkConfig.Name = "wan"; | |||
}; | |||
</syntaxhighlight> | |||
=== DHCP/RA === | === DHCP/RA === | ||
Line 134: | Line 170: | ||
matchConfig.Name = "enp1s0"; | matchConfig.Name = "enp1s0"; | ||
networkConfig = { | networkConfig = { | ||
# start a DHCP Client for IPv4 Addressing/Routing | |||
DHCP = "ipv4"; | DHCP = "ipv4"; | ||
# accept Router Advertisements for Stateless IPv6 Autoconfiguraton (SLAAC) | |||
IPv6AcceptRA = true; | IPv6AcceptRA = true; | ||
}; | }; | ||
# | # make routing on this interface a dependency for network-online.target | ||
linkConfig.RequiredForOnline = "routable"; | linkConfig.RequiredForOnline = "routable"; | ||
}; | }; | ||
Line 153: | Line 191: | ||
matchConfig.Name = "enp1s0"; | matchConfig.Name = "enp1s0"; | ||
address = [ | address = [ | ||
# configure addresses including subnet mask | |||
"192.0.2.100/24" | |||
"2001:DB8::2/64" | |||
]; | ]; | ||
routes = [ | routes = [ | ||
# create default routes for both IPv6 and IPv4 | # create default routes for both IPv6 and IPv4 | ||
{ | { Gateway = "fe80::1"; } | ||
{ | { Gateway = "192.0.2.1"; } | ||
# or when the gateway is not on the same network | # or when the gateway is not on the same network | ||
{ | |||
Gateway = "172.31.1.1"; | Gateway = "172.31.1.1"; | ||
GatewayOnLink = true; | GatewayOnLink = true; | ||
} | |||
]; | ]; | ||
# make the routes on this interface a dependency for network-online.target | # make the routes on this interface a dependency for network-online.target | ||
Line 176: | Line 214: | ||
VLANs can be configured on top of hardlinks as well as virtual links, like bonding interfaces. They provide separate logical networks over physical links. | VLANs can be configured on top of hardlinks as well as virtual links, like bonding interfaces. They provide separate logical networks over physical links. | ||
In this example we tag two VLANs with Ids 10 and 20 on a physical link <code>enp1s0</code>. The VLAN interfaces become available <code>vlan10</code> and <code>vlan20</code> and can receive additional configuration. | In this example we tag two VLANs with Ids 10 and 20 on a physical link <code>enp1s0</code>. The VLAN interfaces become available as <code>vlan10</code> and <code>vlan20</code> and can receive additional configuration. | ||
<syntaxhighlight lang="nix"> | <syntaxhighlight lang="nix"> | ||
Line 202: | Line 240: | ||
# tag vlan on this link | # tag vlan on this link | ||
vlan = [ | vlan = [ | ||
vlan10 | "vlan10" | ||
vlan20 | "vlan20" | ||
]; | ]; | ||
networkConfig.LinkLocalAddressing = "no"; | |||
linkConfig.RequiredForOnline = "carrier"; | |||
}; | }; | ||
"40-vlan10" = { | "40-vlan10" = { | ||
Line 215: | Line 255: | ||
}; | }; | ||
}; | }; | ||
}; | |||
</syntaxhighlight> | |||
=== Bridge === | |||
Given multiple interfaces, that are connected into a bridge will act like a common switch and forward Ethernet frames between all connected bridge ports. The Linux bridge supports various features, like spanning tree, bridge port isolation or acting as a multicast router. | |||
The configuration on top of the bridge interface depends on the desired functionality, e.g., configuring an IP address would make the bridge host reachable on the Ethernet segment. | |||
Recommended documentation: | |||
* [https://www.freedesktop.org/software/systemd/man/systemd.network.html#%5BBridge%5D%20Section%20Options <nowiki>[Bridge]</nowiki> configuration reference] | |||
<syntaxhighlight lang="nix"> | |||
systemd.network = { | |||
netdevs = { | |||
# Create the bridge interface | |||
"20-br0" = { | |||
netdevConfig = { | |||
Kind = "bridge"; | |||
Name = "br0"; | |||
}; | |||
}; | |||
}; | |||
networks = { | |||
# Connect the bridge ports to the bridge | |||
"30-enp1s0" = { | |||
matchConfig.Name = "enp1s0"; | |||
networkConfig.Bridge = "br0"; | |||
linkConfig.RequiredForOnline = "enslaved"; | |||
}; | |||
"30-enp2s0" = { | |||
matchConfig.Name = "enp2s0"; | |||
networkConfig.Bridge = "br0"; | |||
linkConfig.RequiredForOnline = "enslaved"; | |||
}; | |||
# Configure the bridge for its desired function | |||
"40-br0" = { | |||
matchConfig.Name = "br0"; | |||
bridgeConfig = {}; | |||
# Disable address autoconfig when no IP configuration is required | |||
#networkConfig.LinkLocalAddressing = "no"; | |||
linkConfig = { | |||
# or "routable" with IP addresses configured | |||
RequiredForOnline = "carrier"; | |||
}; | |||
}; | |||
}; | |||
}; | |||
</syntaxhighlight> | </syntaxhighlight> | ||
=== Bonding === | === Bonding === | ||
Given two hardlinks <code>enp2s0</code> and <code>enp3s0</code> create a virtual <code>bond0</code> interface using Dynamic LACP (802.3ad), hashing outgoing packets using a packet's | <div style="margin-left: 2em; margin-bottom:1em"> | ||
''More details: [[Networking#Link aggregation]]''</div> | |||
Given two hardlinks <code>enp2s0</code> and <code>enp3s0</code> create a virtual <code>bond0</code> interface using Dynamic LACP (802.3ad), hashing outgoing packets using a packet's layer 3/4 (network/transport layer in the OSI model) information. | |||
<syntaxhighlight lang="nix"> | <syntaxhighlight lang="nix"> | ||
Line 254: | Line 345: | ||
}; | }; | ||
</syntaxhighlight> | </syntaxhighlight> | ||
=== Router Advertisement === | |||
Router advertisements are way to allow clients to achieve stateless autoconfiguration (SLAAC). The most prominent setup is where the router announces a prefix onto a LAN segment, which the receiving client can use to set up an address on that prefix, and configure the sender as its default gateway. | |||
In this example the router will announce a static IPv6 prefix on the <code>lan</code> interface from it's automatically configured link local address on that link. The router does not generally require a unique local or globally reachable address on the link, unless you also want to host services like DNS and NTP on that LAN segment. | |||
Recommended documentation: | |||
* [https://www.freedesktop.org/software/systemd/man/systemd.network.html#%5BIPv6SendRA%5D%20Section%20Options <nowiki>[IPv6SendRa]</nowiki> configuration reference] | |||
<syntaxhighlight lang="nix"> | |||
systemd.network = { | |||
networks = { | |||
"30-lan" = { | |||
matchConfig.Name = "lan"; | |||
address = [ "2001:db8:1122:3344::1/64" ]; | |||
networkConfig = { | |||
IPv6SendRA = true; | |||
}; | |||
ipv6Prefixes = [ | |||
{ | |||
# Announce a static prefix | |||
ipv6PrefixConfig.Prefix = "2001:db8:1122:3344::/64"; | |||
} | |||
]; | |||
ipv6SendRAConfig = { | |||
# Provide a DNS resolver | |||
EmitDNS = true; | |||
DNS = "2001:db8:1122:3344::1"; | |||
}; | |||
}; | |||
}; | |||
}; | |||
</syntaxhighlight> | |||
An extended form of this setup uses DHCPv6 prefix delegation to acquire a dynamic prefix over a WAN link, which then gets distributed onto designated LAN segments. | |||
=== WireGuard === | |||
WireGuard can also be set up using <code>systemd.network.netdevs</code>. More details can be found at [[WireGuard#Setting up WireGuard with systemd-networkd]]. | |||
== User configurations == | == User configurations == | ||
Line 263: | Line 394: | ||
* [https://gist.github.com/mweinelt/b78f7046145dbaeab4e42bf55663ef44 NixOS 22.11 VDSL Router (VLANs on top of Bonding, IPv6 Prefix-Delegation, pppd Integration)] by [https://github.com/mweinelt mweinelt] | * [https://gist.github.com/mweinelt/b78f7046145dbaeab4e42bf55663ef44 NixOS 22.11 VDSL Router (VLANs on top of Bonding, IPv6 Prefix-Delegation, pppd Integration)] by [https://github.com/mweinelt mweinelt] | ||
* [https://github.com/philipwilk/nixos/blob/4fec9d73bfa7b1ecb490186522de38d25ee81e69/homelab/router/systemd.nix NixOS Unstable (25.04) Router (ipv4/ipv6 dual stack, dnssec+dnsovertls, NTP-rs)] by [https://github.com/philipwilk philipwilk] | |||
[[Category: Networking]] | [[Category:systemd]] | ||
[[Category:Networking]] |