nm-configurator (or nmc) is a CLI tool which makes it easy to generate and apply NetworkManager configurations.
Each release is published with nmc already built for amd64
and arm64
Linux systems:
$ curl -o nmc -L https://github.com/suse-edge/nm-configurator/releases/latest/download/nmc-linux-$(uname -m)
$ chmod +x nmc
$ git clone https://github.com/suse-edge/nm-configurator.git
$ cd nm-configurator
$ cargo build --release # only supports Linux based systems
nmc depends on having the desired network state for all known nodes beforehand.
NetworkManager
is using connection profiles defined as files stored under /etc/NetworkManager/system-connections
.
In order to generate these config (*.nmconnection) files, nmc uses the nmstate library and requires a configuration directory as an input. This directory must contain the desired network state in one of the following file formats:
-
A single or multiple
<hostname>.yaml
files containing the different configurations per host. This method requires specifying the MAC addresses of all Ethernet interfaces for each host in order to properly identify the relevant configurations when applying those. -
A single
_all.yaml
file containing the configurations to be applied to all hosts. This method does not depend on MAC address matching.
nmc is then able to apply the generated configurations by identifying and storing the relevant NetworkManager settings for a given host.
Typically used with Combustion in order to bootstrap multiple nodes using the same provisioning artefact instead of depending on different custom images per machine.
mkdir -p desired-states
cat <<- EOF > desired-states/node1.yaml
interfaces:
- name: eth0
type: ethernet
state: up
mac-address: FE:C4:05:42:8B:AA
ipv4:
address:
- ip: 192.168.122.250
prefix-length: 24
enabled: true
ipv6:
address:
- ip: 2001:db8::1:1
prefix-length: 64
enabled: true
EOF
cat <<- EOF > desired-states/node2.yaml
interfaces:
- name: eth1
type: ethernet
state: up
mac-address: FE:C4:05:42:8B:AB
ipv4:
address:
- ip: 192.168.123.250
prefix-length: 24
enabled: true
ipv6:
enabled: false
EOF
cat <<- EOF > desired-states/node3.yaml
interfaces:
- name: eth4
type: ethernet
state: up
mac-address: FE:C4:05:42:8B:AC
ipv4:
address:
- ip: 192.168.124.250
prefix-length: 24
enabled: true
ipv6:
enabled: false
EOF
Please refer to the official nmstate docs for more extensive examples.
$ ./nmc generate --config-dir desired-states --output-dir network-config
[2024-11-12T09:05:57Z INFO nmc::generate_conf] Generating config from "desired-states/node1.yaml"...
[2024-11-12T09:05:59Z INFO nmc::generate_conf] Generating config from "desired-states/node2.yaml"...
[2024-11-12T09:05:59Z INFO nmc::generate_conf] Generating config from "desired-states/node3.yaml"...
[2024-11-12T09:05:59Z INFO nmc] Successfully generated and stored network config
$ find network-config | sort
network-config
network-config/host_config.yaml
network-config/node1
network-config/node1/eth0.nmconnection
network-config/node2
network-config/node2/eth1.nmconnection
network-config/node3
network-config/node3/eth4.nmconnection
There are separate directories for each host (identified by their input hostname.yaml).
Each of these contains the configuration files for the desired network interfaces (e.g. eth0
).
The host_config.yaml
file on the root level maps the hosts to all of their preconfigured interfaces.
This is necessary in order for nmc to identify which host it is running on when applying the network configurations later.
- hostname: node1
interfaces:
- logical_name: eth0
connection_ids:
- eth0
mac_address: FE:C4:05:42:8B:AA
interface_type: ethernet
- hostname: node2
interfaces:
- logical_name: eth1
connection_ids:
- eth1
mac_address: FE:C4:05:42:8B:AB
interface_type: ethernet
- hostname: node3
interfaces:
- logical_name: eth4
connection_ids:
- eth4
mac_address: FE:C4:05:42:8B:AC
interface_type: ethernet
Simply copy the directory containing the results from nmc generate
(network-config
in the example above) to the target host.
$ ./nmc apply --config-dir network-config
[2024-11-12T09:10:10Z INFO nmc::apply_conf] Identified host: node2
[2024-11-12T09:10:10Z INFO nmc::apply_conf] Set hostname: node2
[2024-11-12T09:10:11Z INFO nmc::apply_conf] Processing interface 'eth1'...
[2024-11-12T09:10:11Z INFO nmc::apply_conf] Processing connection 'eth1'...
[2024-11-12T09:10:11Z INFO nmc::apply_conf] Using interface name 'enp0s1' instead of the preconfigured 'eth1'
[2024-11-12T09:10:11Z INFO nmc] Successfully applied config
$ ls /etc/NetworkManager/system-connections
enp0s1.nmconnection
NOTE: Interface names during the installation of nodes might differ from the preconfigured logical ones.
This is expected and nmc will rely on the MAC addresses and use the actual names for the NetworkManager
configurations instead e.g. settings for interface with a predefined logical name eth1
but actually named
enp0s1
on the target node will automatically be adjusted and stored to /etc/NetworkManager/enp0s1.nmconnection
.
There are occasions where relying on known MAC addresses is not an option.
In these cases we can opt for the so-called unified configurations which allows us
to specify settings in an _all.yaml
file which will then be applied across all provisioned nodes.
mkdir -p desired-states
cat <<- EOF > desired-states/_all.yaml
interfaces:
- name: eth0
type: ethernet
state: up
ipv4:
dhcp: true
enabled: true
ipv6:
enabled: false
- name: eth1
type: ethernet
state: up
ipv4:
address:
- ip: 10.0.0.1
prefix-length: 24
enabled: true
dhcp: false
ipv6:
enabled: false
EOF
$ ./nmc generate --config-dir desired-states --output-dir network-config
[2024-05-27T07:23:20Z INFO nmc::generate_conf] Generating config from "desired-states/_all.yaml"...
[2024-05-27T07:23:20Z INFO nmc] Successfully generated and stored network config
$ find network-config | sort
network-config
network-config/_all
network-config/_all/eth0.nmconnection
network-config/_all/eth1.nmconnection
NOTE: The host_config.yaml
file will not be present since host mapping is not necessary.
$ ./nmc apply --config-dir network-config
[2024-05-27T07:24:03Z INFO nmc::apply_conf] Applying unified config...
[2024-05-27T07:24:03Z INFO nmc::apply_conf] Copying file... "network-config/_all/eth0.nmconnection"
[2024-05-27T07:24:03Z INFO nmc::apply_conf] Copying file... "network-config/_all/eth1.nmconnection"
[2024-05-27T07:24:03Z INFO nmc] Successfully applied config
$ ls /etc/NetworkManager/system-connections
eth0.nmconnection eth1.nmconnection