Systemd/networkd

From NixOS Wiki
Revision as of 23:39, 26 March 2023 by imported>Mweinelt (→‎Static)

Networkd is the network configuration component of the systemd software suite. It is well integrated into NixOS below systemd.network and should be preferred over networking.interfaces options for most use cases, since it receives far superior maintenance.

Configuration for networkd is split into three sections.

In most simple scenarios configuring existing network devices is what you want to do.

Enabling

To be able to use networkd configuration it needs to be enabled first.

systemd.network.enable = true;

Some guides will mention the networking.useNetworkd option, which offers translation of some networking.* options into networkd. If you can write your complete network setup in native networkd configuration, you should stay away from that option.

Limitations

Some limitations might be surprising, so it is probably helpful to get them out of the way early.

network-online.target

While network.target only requires the network management stack to be up, which means it does not care about network interfaces being configured, the network-online.target waits until a defined set of network interfaces are in a state, that by its configuration is considered online.

When networkd is enabled, the network-online.target is implemented through the systemd-networkd-wait-online.service, which makes sure interfaces configured through networkd are in their expected operational state.

The current operational state of network interfaces can be learned from networkctl.

 networkctl
IDX LINK          TYPE     OPERATIONAL SETUP     
  1 lo            loopback carrier     unmanaged
  2 enp10s0       ether    routable    unmanaged
  3 wlp9s0        wlan     no-carrier  unmanaged

For most network interfaces that will mean that they have routable network connectivity, but in more complex setups some links may be content with more simple states like carrier or enslaved. Interfaces that are managed by networkd, but not always in use, shouldn't be required for network-online.target

systemd.network."50-enp3s0" = {
  matchConfig.Name = "enp3s0";
  # acquire a DHCP lease on link up
  networkConfig.DHCP = "yes";
  # this port is not always connected and not required to be online
  linkConfig.RequiredForOnline = "no";
};

Note that the default value for linkConfig.RequiredForOnline is unexpectedly "yes", which often leads to a failing network-online.target.

Setting individual interfaces to "no" is a perfectly valid choice and should be considered, before disabling the systemd-networkd-wait-online.service entirely, because a working network-online.target is required for some services to properly start without race conditions.

Recommended documentation:

Examples

Examples should be concise and give proper hints on how to achieve a reliably working network-online.target.

DHCP

Acquire a DHCP lease on an interface and make network-online.target wait until addresses and routes from the DHCP exchange are configured.

  systemd.network.networks."10-dhcp-wan" = {
    matchConfig.Name = "enp1s0";
    networkConfig.DHCP = "yes";
    # make acquiring a DHCP lease a dependency for network-online.target
    linkConfig.RequiredForOnline = true;
  };

Static

Apply a static address and routing configuration onto enp1s0. When the gateway is not on the same prefix as the address configured, you usually also need to set GatewayOnLink, to indicate the gateway is directly reachable on the interface.

  systemd.network.networks."10-wan" = {
    # match the interface by name
    matchConfig.Name = "enp1s0";
    address = [
        # configure addresses including subnet mask
        "192.0.2.100/24"
        "2001:DB8::2/64"
    ];
    routes = [
      # create default routes for both IPv6 and IPv4
      { routeConfig.Gateway = "fe80::1"; }
      { routeConfig.Gateway = "192.0.2.1"; }
      # or when the gateway is not on the same network
      { routeConfig = {
        Gateway = "172.31.1.1";
        GatewayOnLink = true;
      }; }
    ];
    # make the routes on this interface a dependency for network-online.target
    linkConfig.RequiredForOnline = "routable";
  };

Bonding

Given two hardlinks enp2s0 and enp3s0 create a virtual bond0 interface using Dynamic LACP (802.3ad), hashing outgoing packets using a packet's Layer3/4 (OSI Layer) information.

  systemd.network = {
    netdevs = {
      "10-bond0" = {
        netdevConfig = {
          Kind = "bond";
          Name = "bond0";
        };
        bondConfig = {
          Mode = "802.3ad";
          TransmitHashPolicy = "layer3+4";
        };
      };
    };
    networks = {
      "30-enp2s0" = {
        matchConfig.Name = "enp2s0";
        networkConfig.Bond = "bond0";
      };
      "30-enp3s0" = {
        matchConfig.Name = "enp3s0";
        networkConfig.Bond = "bond0";
      };
      "40-bond0" = {
        matchConfig.Name = "bond0";
        linkConfig = {
          RequiredForOnline = "carrier";
        };
        networkConfig.LinkLocalAddressing = "no";
      };
    };
  };