Systemd/networkd: Difference between revisions

imported>Broizter
m vlans needs to be quoted or else you get an undefined variable error
DHCP (talk | contribs)
m remove unneeded indent at the beginning of each line in nix blocks; use console highlight for shell command snippets
 
(23 intermediate revisions by 12 users not shown)
Line 1: Line 1:
{{Systemd/breadcrumb}}
{{DISPLAYTITLE:systemd-networkd}}
{{DISPLAYTITLE:systemd-networkd}}
[https://www.freedesktop.org/software/systemd/man/systemd-networkd.html systemd-networkd] is the network[[Category: Networking]] 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.
[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.
Line 28: Line 29:
These use cases are better served by [[NetworkManager]] and its various frontends, that provides a better integrated user experience for various desktop systems.
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,
{{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.}}
when they manage a distinct set of interfaces.}}


=== Enabling ===
=== Enabling ===
Line 54: Line 54:


<syntaxhighlight lang="nix">
<syntaxhighlight lang="nix">
  systemd.network.networks."10-lan" = {
systemd.network.networks."10-lan" = {
    matchConfig.Name = "lan";
  matchConfig.Name = "lan";
    networkConfig.DHCP = "ipv4";
  networkConfig.DHCP = "ipv4";
  };
};
</syntaxhighlight>
</syntaxhighlight>


Line 70: Line 70:
</nowiki>}}
</nowiki>}}


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 alphabetically, 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.
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.


=== Debugging ===
=== Debugging ===
Line 78: Line 78:
<syntaxhighlight lang="nix">
<syntaxhighlight lang="nix">
systemd.services."systemd-networkd".environment.SYSTEMD_LOG_LEVEL = "debug";
systemd.services."systemd-networkd".environment.SYSTEMD_LOG_LEVEL = "debug";
</syntaxhighlight>
Log level can also be changed at runtime with
<syntaxhighlight lang="console">
$ systemctl service-log-level systemd-networkd.service debug
$ # or
$ systemctl service-log-level systemd-networkd.service info
</syntaxhighlight>
</syntaxhighlight>


Line 89: Line 95:
** Does not modify properties (e.g., MTU, VLAN ID, VXLAN ID, Wireguard Peers) of existing netdevs
** Does not modify properties (e.g., MTU, VLAN ID, VXLAN ID, Wireguard Peers) of existing netdevs
*** https://github.com/systemd/systemd/issues/9627
*** 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 102: Line 109:


The current operational state of network interfaces can be learned from <code>networkctl</code>.
The current operational state of network interfaces can be learned from <code>networkctl</code>.
<syntaxhighlight lang="bash">
<syntaxhighlight lang="console">
networkctl
$ networkctl
IDX LINK          TYPE    OPERATIONAL SETUP     
IDX LINK          TYPE    OPERATIONAL SETUP     
   1 lo            loopback carrier    unmanaged
   1 lo            loopback carrier    unmanaged
Line 117: Line 124:


<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 147: Line 154:


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 153: Line 171:


<syntaxhighlight lang="nix">
<syntaxhighlight lang="nix">
  systemd.network.networks."10-wan" = {
systemd.network.networks."10-wan" = {
    matchConfig.Name = "enp1s0";
  matchConfig.Name = "enp1s0";
    networkConfig = {
  networkConfig = {
      # start a DHCP Client for IPv4 Addressing/Routing
    # start a DHCP Client for IPv4 Addressing/Routing
      DHCP = "ipv4";
    DHCP = "ipv4";
      # accept Router Advertisements for Stateless IPv6 Autoconfiguraton (SLAAC)
    # 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";
   };
   };
  # make routing on this interface a dependency for network-online.target
  linkConfig.RequiredForOnline = "routable";
};
</syntaxhighlight>
</syntaxhighlight>


Line 173: Line 191:


<syntaxhighlight lang="nix">
<syntaxhighlight lang="nix">
  systemd.network.networks."10-wan" = {
systemd.network.networks."10-wan" = {
    # match the interface by name
  # match the interface by name
    matchConfig.Name = "enp1s0";
  matchConfig.Name = "enp1s0";
    address = [
  address = [
        # configure addresses including subnet mask
    # configure addresses including subnet mask
        "192.0.2.100/24"
    "192.0.2.100/24"
        "2001:DB8::2/64"
    "2001:DB8::2/64"
    ];
  ];
    routes = [
  routes = [
      # create default routes for both IPv6 and IPv4
    # create default routes for both IPv6 and IPv4
      { routeConfig.Gateway = "fe80::1"; }
    { Gateway = "fe80::1"; }
      { routeConfig.Gateway = "192.0.2.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
      { routeConfig = {
    {
        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
    linkConfig.RequiredForOnline = "routable";
  linkConfig.RequiredForOnline = "routable";
  };
};
</syntaxhighlight>
</syntaxhighlight>


Line 200: Line 218:
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">
  systemd.network = {
systemd.network = {
    netdevs = {
  netdevs = {
      "20-vlan10" = {
    "20-vlan10" = {
        netdevConfig = {
      netdevConfig = {
          Kind = "vlan";
        Kind = "vlan";
          Name = "vlan10";
        Name = "vlan10";
        };
        vlanConfig.Id = 10;
       };
       };
       "20-vlan20" = {
       vlanConfig.Id = 10;
        netdevConfig = {
    };
          Kind = "vlan";
    "20-vlan20" = {
          Name = "vlan20";
      netdevConfig = {
        };
        Kind = "vlan";
        vlanConfig.Id = 20;
        Name = "vlan20";
       };
       };
      vlanConfig.Id = 20;
     };
     };
  };


    networks = {
  networks = {
      "30-enp1s0" = {
    "30-enp1s0" = {
        matchConfig.Name = "enp1s0";
      matchConfig.Name = "enp1s0";
        # tag vlan on this link
      # tag vlan on this link
        vlan = [
      vlan = [
          "vlan10"
        "vlan10"
          "vlan20"
        "vlan20"
        ];
      ];
       };
       networkConfig.LinkLocalAddressing = "no";
      "40-vlan10" = {
      linkConfig.RequiredForOnline = "carrier";
        matchConfig.Name = "vlan10";
    };
        # add relevant configuration here
    "40-vlan10" = {
      };
      matchConfig.Name = "vlan10";
      "40-vlan20" = {
      # add relevant configuration here
        matchConfig.Name = "vlan20";
    };
        # add relevant configuration here
    "40-vlan20" = {
      };
      matchConfig.Name = "vlan20";
      # add relevant configuration here
     };
     };
   };
   };
};
</syntaxhighlight>
</syntaxhighlight>


Line 252: Line 272:


<syntaxhighlight lang="nix">
<syntaxhighlight lang="nix">
  systemd.network = {
systemd.network = {
    netdevs = {
  netdevs = {
      # Create the bridge interface
    # Create the bridge interface
      "20-br0" = {
    "20-br0" = {
        netdevConfig = {
      netdevConfig = {
          Kind = "bridge";
        Kind = "bridge";
          Name = "br0";
        Name = "br0";
        };
       };
       };
    };
  };
  networks = {
    # Connect the bridge ports to the bridge
    "30-enp1s0" = {
      matchConfig.Name = "enp1s0";
      networkConfig.Bridge = "br0";
      linkConfig.RequiredForOnline = "enslaved";
     };
     };
     networks = {
     "30-enp2s0" = {
      # Connect the bridge ports to the bridge
       matchConfig.Name = "enp2s0";
      "30-enp1s0" = {
      networkConfig.Bridge = "br0";
        matchConfig.Name = "enp1s0";
      linkConfig.RequiredForOnline = "enslaved";
        networkConfig.Bridge = "br0";
    };
        linkConfig.RequiredForOnline = "enslaved";
    # Configure the bridge for its desired function
      };
    "40-br0" = {
       "30-enp2s0" = {
      matchConfig.Name = "br0";
        matchConfig.Name = "enp2s0";
      bridgeConfig = {};
        networkConfig.Bridge = "br0";
      # Disable address autoconfig when no IP configuration is required
        linkConfig.RequiredForOnline = "enslaved";
      #networkConfig.LinkLocalAddressing = "no";
      };
      linkConfig = {
      # Configure the bridge for its desired function
        # or "routable" with IP addresses configured
      "40-br0" = {
        RequiredForOnline = "carrier";
        matchConfig.Name ="br0";
        bridgeConfig = {};
        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 Layer3/4 (OSI Layer) information.
<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">
  systemd.network = {
systemd.network = {
    netdevs = {
  netdevs = {
      "10-bond0" = {
    "10-bond0" = {
        netdevConfig = {
      netdevConfig = {
          Kind = "bond";
        Kind = "bond";
          Name = "bond0";
        Name = "bond0";
        };
      };
        bondConfig = {
      bondConfig = {
          Mode = "802.3ad";
        Mode = "802.3ad";
          TransmitHashPolicy = "layer3+4";
        TransmitHashPolicy = "layer3+4";
        };
       };
       };
     };
     };
    networks = {
  };
      "30-enp2s0" = {
  networks = {
        matchConfig.Name = "enp2s0";
    "30-enp2s0" = {
        networkConfig.Bond = "bond0";
      matchConfig.Name = "enp2s0";
      };
      networkConfig.Bond = "bond0";
      "30-enp3s0" = {
    };
        matchConfig.Name = "enp3s0";
    "30-enp3s0" = {
        networkConfig.Bond = "bond0";
      matchConfig.Name = "enp3s0";
      };
      networkConfig.Bond = "bond0";
      "40-bond0" = {
    };
        matchConfig.Name = "bond0";
    "40-bond0" = {
        linkConfig = {
      matchConfig.Name = "bond0";
          RequiredForOnline = "carrier";
      linkConfig = {
        };
        RequiredForOnline = "carrier";
        networkConfig.LinkLocalAddressing = "no";
       };
       };
      networkConfig.LinkLocalAddressing = "no";
     };
     };
   };
   };
};
</syntaxhighlight>
</syntaxhighlight>


Line 335: Line 360:


<syntaxhighlight lang="nix">
<syntaxhighlight lang="nix">
  systemd.network = {
systemd.network = {
    networks = {
  networks = {
      "30-lan" = {
    "30-lan" = {
        matchConfig.Name = "lan";
      matchConfig.Name = "lan";
        address = [
      address = [ "2001:db8:1122:3344::1/64" ];
          "2001:db8:1122:3344::1/64"
      networkConfig = {
        ];
        IPv6SendRA = true;
        networkConfig = {
      };
          IPv6SendRA = true;
      ipv6Prefixes = [
        };
        {
        ipv6Prefixes = [ {
           # Announce a static prefix
           # Announce a static prefix
           ipv6PrefixConfig.Prefix = "2001:db8:1122:3344::/64";
           ipv6PrefixConfig.Prefix = "2001:db8:1122:3344::/64";
         } ];
         }
        ipv6SendRAConfig = {
      ];
          # Provide a DNS resolver
      ipv6SendRAConfig = {
          EmitDNS = true;
        # Provide a DNS resolver
          DNS = "2001:db8:1122:3344::1";
        EmitDNS = true;
        };
        DNS = "2001:db8:1122:3344::1";
       };
       };
    };
   };
   };
};
</syntaxhighlight>
</syntaxhighlight>


Line 372: Line 398:


* [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:systemd]]
[[Category:Networking]]