DEBOPS.NETWORKD(5)

NAME
debops.networkd - Manage network interfaces using systemd-networkd

SYNOPSIS

debops run service/networkd [--limit group,host,...] [--diff] [--check] [--tags tag1,tag2,...] [--skip-tags tag1,tag2,...] [<ansible-playbook options>] ...

DESCRIPTION

The systemd-networkd(8) <https://manpages.debian.org/systemd-networkd(8)> service is a part of the systemd <https://www.freedesktop.org/wiki/Software/systemd/> project. The service manages the runtime and on-disk configuration of the network connections, physical and virtual network devices and their state in the systemd-udevd(8) <https://manpages.debian.org/systemd-udevd(8)> subsystem.

The debops.networkd Ansible role can be used to generate and update configuration of the systemd-networkd service. Other parts of the systemd ecosystem are managed by separate Ansible roles.

GETTING STARTED

  On first run, no changes to network stack take effect

The role is designed around the default presence of the ifupdown Debian package, which manages the network interfaces. Due to this, first execution of the role will result in the systemd-networkd configuration files being generated, but the service itself will not be restarted (see below for detailed instructions). The service will be restarted on subsequent executions of the role. In an environment where the systemd-networkd already manages the network interfaces, the role should work normally.

  Replacing ifupdown scripts with systemd-networkd

The default non-GUI Debian installation uses the ifupdown package to configure network interfaces. It's not compatible with the systemd-networkd service, therefore it's best to purge it from the host after the new configuration has been applied. This has to be done through local console, since during removal the post-rm scripts will bring the network interfaces down, disconnecting the host from the network.

Specific steps to take to replace the ifupdown package with systemd-networkd service:

1.  Make sure that the host is in the [debops_service_networkd] Ansible inventory group.

    [debops_all_hosts]
    hostname
    [debops_service_networkd]
    hostname

2.  Apply the debops.networkd playbook, check if the host has network connection. On first execution of the role, the systemd-networkd service will not be restarted to avoid making changes in the network stack.

    user@host:~$ debops check service/networkd -l hostname
    user@host:~$ debops run service/networkd -l hostname

3.  Login to the host on the local console, purge ifupdown package and reboot the host.

    user@host:~$ sudo apt purge ifupdown
    user@host:~$ sudo systemctl reboot

4.  Login to the host and check if the new configuration has been set up correctly. Apply the debops.resolved playbook to configure /etc/resolv.conf configuration file.

    user@host:~$ debops check service/resolved -l hostname
    user@host:~$ debops run service/resolved -l hostname

  Example inventory

To manage the network configuration using systemd-networkd service, the host needs to be included in the [debops_service_networkd] Ansible inventory group:

[debops_all_hosts]
hostname
[debops_service_networkd]
hostname

  Example playbook

If you are using this role without DebOps, here's an example Ansible playbook that uses the debops.networkd role:

---
- name: Manage systemd-networkd service
  collections: [ 'debops.debops', 'debops.roles01',
                 'debops.roles02', 'debops.roles03' ]
  hosts: [ 'debops_service_networkd' ]
  become: True
  environment: '{{ inventory__environment | d({})
                   | combine(inventory__group_environment | d({}))
                   | combine(inventory__host_environment  | d({})) }}'
  roles:
    - role: networkd
      tags: [ 'role::networkd', 'skip::networkd' ]

  Ansible tags

You can use Ansible --tags or --skip-tags parameters to limit what tasks are performed during Ansible run. This can be used after a host was first configured to speed up playbook execution, when you are sure that most of the configuration is already in the desired state.

Available role tags:

role::networkd
    Main role tag, should be used in the playbook to execute all of the role tasks as well as role dependencies.

DEFAULT VARIABLE DETAILS

Some of the debops.networkd default variables have more extensive configuration than simple strings or lists, here you can find documentation and examples for them.

  networkd__configuration

The networkd__*_configuration default variables define the configuration of the systemd-networkd service itself. You can find more details about systemd-networkd configuration in the networkd.conf(5) <https://manpages.debian.org/networkd.conf(5)> manual page.

The generated configuration will be located in the /etc/systemd/networkd.conf.d/ansible.conf config file. This file is not generated by default to fall back on the default configuration provided in the OS packages; to generate it the networkd__deploy_state variable needs to be set to present.

  Examples

You can check the networkd__default_configuration variable for the default contents of the configuration file.

  Syntax

The role uses the Universal Configuration system to configure systemd-networkd daemon. Each configuration entry in the list is a YAML dictionary. The simple form of the configuration uses the dictionary keys as the parameter names, and dictionary values as the parameter values. Remember that the parameter names need to be specified in the exact case they are used in the documentation (e.g. SpeedMeterInterval, DUIDType), otherwise they will be duplicated in the generated configuration file. It's best to use a single YAML dictionary per configuration option.

If the YAML dictionary contains the name key, the configuration switches to the complex definition mode, with configuration options defined by specific parameters:

name
    Required. Specify the name of the systemd-networkd configuration file parameter. The case is important and should be the same as specified in the configuration file or the networkd.conf(5) <https://manpages.debian.org/networkd.conf(5)> manual page, otherwise the configuration entries will be duplicated.

    Multiple configuration entries with the same name parameter are merged together in order of appearance. This can be used to modify parameters conditionally.

value
    Required. The value of a given configuration option. It can be a string, number, True/False boolean or an empty string.

state
    Optional. If not specified or present, a given configuration parameter will be present in the generated configuration file. If absent, a given parameter will be removed from the configuration file. If comment, the parameter will be present but commented out.

    If the state is init, the parameter will be "primed" in the configuration pipeline, but it will be commented out in the generated configuration file. Any subsequent configuration entry with the same name will switch the state to present - this is used to define the default parameters in the role which can be changed via the Ansible inventory.

    If the state is ignore, a given configuration entry will not be evaluated during role execution. This can be used to activate configuration entries conditionally.

  networkd__units

The networkd__*_units default variables can be used to manage systemd-networkd units (*.network, *.netdev and *.link files) located in the /etc/systemd/network/ subdirectory. You can find more information about the units themselves in the systemd.network(5) <https://manpages.debian.org/systemd.network(5)>, systemd.netdev(5) <https://manpages.debian.org/systemd.netdev(5)> and systemd.link(5) <https://manpages.debian.org/systemd.link(5)> manual pages.

  Examples

Disable the default network configuration defined in networkd__default_units variable so that it doesn't interfere with the user configuration:

networkd__units:
  - name: 'wired-dhcp.network'
    state: 'absent'

The examples below are based on examples found in the systemd.network(5) <https://manpages.debian.org/systemd.network(5)> manual page. For ease of use, the examples are provided in the debops.networkd role documentation in the DebOps monorepo.

Configure any wired Ethernet network cards using DHCP and accept search domains provided remotely (default configuration in networkd__default_units variable):

---
# File: ansible/inventory/group_vars/all/networkd.yml
networkd__units:
  - name: 'wired-dhcp.network'
    comment: 'Configure any wired Ethernet interface via DHCP'
    raw: |
      [Match]
      Name=en*
      [Network]
      DHCP=yes
      [DHCPv4]
      UseDomains=true
    state: 'present'

Configure a network bridge using DHCP and connect a physical Ethernet interface to it:

---
# File: ansible/inventory/group_vars/all/networkd.yml
networkd__units:
  - name: 'br0.netdev'
    raw: |
      [NetDev]
      Name=br0
      Kind=bridge
    state: 'present'
  - name: 'br0.network'
    raw: |
      [Match]
      Name=br0
      [Network]
      DHCP=yes
      [DHCPv4]
      UseDomains=true
    state: 'present'
  - name: 'enp1s0.network'
    raw: |
      [Match]
      Name=enp1s0
      [Network]
      Bridge=br0
    state: 'present'

Configure a network interface with static IP address:

---
# File: ansible/inventory/host_vars/hostname/networkd.yml
networkd__units:
  - name: '50-static.network'
    comment: 'Configure specific interface with static IP address'
    raw: |
      [Match]
      Name=enp2s0
      [Network]
      Address=192.0.2.15/24
      Gateway=192.0.2.1
    state: 'present'

Configure a bridge interface and connect two network cards to it, wired Ethernet and WiFi:

---
# File: ansible/inventory/group_vars/group0/networkd.yml
bridge_if: 'bridge0'
networkd__group_units:
  - name: 'bridge0.netdev'
    raw: |
      [NetDev]
      Name={{ bridge_if }}
      Kind=bridge
    state: 'present'
  - name: '25-bridge-static.network'
    raw: |
      [Match]
      Name={{ bridge_if }}
      [Network]
      Address=192.0.2.15/24
      Gateway=192.0.2.1
      DNS=192.0.2.1
    state: 'present'
  - name: '25-bridge-slave-interface-1.network'
    raw: |
      [Match]
      Name=enp2s0
      [Network]
      Bridge={{ bridge_if }}
    state: 'present'
  - name: '25-bridge-slave-interface-2.network'
    raw: |
      [Match]
      Name=wlp3s0
      [Network]
      Bridge={{ bridge_if }}
    state: 'present'

Augment the above configuration on a specific host with VLAN support:

---
# File: ansible/inventory/host_vars/hostname/networkd.yml
networkd__host_units:
  - name: '20-bridge-slave-interface-vlan.network'
    raw: |
      [Match]
      Name=enp2s0
      [Network]
      Bridge=bridge0
      [BridgeVLAN]
      VLAN=1-32
      PVID=42
      EgressUntagged=42
      [BridgeVLAN]
      VLAN=100-200
      [BridgeVLAN]
      EgressUntagged=300-400
    state: 'present'

Create a bonded network interface using two specific Ethernet network cards and configure IPv6 connectivity using DHCP:

---
# File: ansible/inventory/host_vars/hostname/networkd.yml
networkd__host_units:
  - name: '30-bond1.network'
    raw: |
      [Match]
      Name=bond1
      [Network]
      DHCP=ipv6
    state: 'present'
  - name: '30-bond1.netdev'
    raw: |
      [NetDev]
      Name=bond1
      Kind=bond
    state: 'present'
  - name: '30-bond1-dev1.network'
    raw: |
      [Match]
      MACAddress=52:54:00:e9:64:41
      [Network]
      Bond=bond1
    state: 'present'
  - name: '30-bond1-dev2.network'
    raw: |
      [Match]
      MACAddress=52:54:00:e9:64:42
      [Network]
      Bond=bond1
    state: 'present'

  Syntax

The role uses the Universal Configuration system to manage systemd-networkd unit files. Each configuration entry in the list is a YAML dictionary, with configuration options defined by specific parameters:

name
    Required. Name of the systemd-networkd unit file to manage. The name can be in the form <unit.type> to denote a single systemd.unit(5) <https://manpages.debian.org/systemd.unit(5)>, as well as <unit.type>.d/<override>.conf to denote a single "override" configuration file that changes the configuration of a specific unit.

    Unit files are stored under the /etc/systemd/network/ subdirectory. The role will create the <unit.type>.d/ subdirectories as needed.

    The name parameter needs to be unique. Multiple configuration entries with the same name parameter are merged together and override each other.

raw Optional. YAML text block in the INI format, with the systemd-networkd configuration options which will be included in the generated configuration file as-is. The text block can contain Jinja statements to generate parts of the configuration dynamically.

    See the systemd.network(5) <https://manpages.debian.org/systemd.network(5)>, systemd.netdev(5) <https://manpages.debian.org/systemd.netdev(5)> and systemd.link(5) <https://manpages.debian.org/systemd.link(5)> manual pages for details about the unit configuration syntax and available options. The generated files are not validated by Ansible before being applied in the systemd-networkd configuration at this time.

state
    Optional. If not specified or present (default), a given unit configuration file will be generated by Ansible and placed in the systemd-networkd configuration directory. The service will be automatically restarted on changes.

    If absent, the role will remove the specified unit configuration file as well as the override directory if it is present (all override files will be removed, even ones not managed by Ansible). Specific override files can be removed as well if they are defined directly in the name parameter.

    If init, the configuration entry will be prepared, but no changes will be done on the host itself. This can be done to prepare a unit configuration and activate it conditionally later in the universal configuration pipeline.

    If ignore, a given configuration entry will not be evaluated during role execution.

comment
    Optional. String or YAML text block with comments included in the generated configuration file.

SEE ALSO

•   Manual pages: systemd-networkd.service(8) <https://manpages.debian.org/systemd-networkd.service(8)>, networkctl(1) <https://manpages.debian.org/networkctl(1)>

•   Debian Wiki: systemd-networkd <https://wiki.debian.org/SystemdNetworkd>

•   Arch Linux Wiki: systemd-networkd <https://wiki.archlinux.org/title/systemd-networkd>

AUTHOR
Maciej Delmanowski

COPYRIGHT
2014-2024, Maciej Delmanowski, Nick Janetakis, Robin Schneider and others