I've been working with NMState for quite a bit of time, mostly in OpenShift environments, and I've really grown to like the declarative way of handling network configuration
First, let's iron out some basics. NMState doesn't completely replace NetworkManager; it relies on it and generates standard .nmconnection files under the hood. Think of it as a clean, declarative wrapper to configure NetworkManager and manage connections seamlessly.
There are two distinct ways you can run NMState
- Imperatively with a Failsafe: Best for initial testing and manual updates
- As a Service on Boot: Automatically enforces your declared configuration during startup (here be dragons).
Let's look at the imperative mode first, which features a brilliant safeguard known as a "dead man's trigger". Running nmstatectl apply with the '--no-commit' and '--timeout 30' flags will automatically revert any changes if you don't explicitly confirm them within 30 seconds. This provides an excellent safety net if an adjustment accidentally breaks your connectivity.
Conversely, running NMState as a system service will automatically apply your configuration files at reboot, unless they've already been processed. Once a configuration is successfully applied, the service moves the file from 'filename.yaml' to 'filename.applied' to prevent it from executing over and over again.
Here Be Dragons: Running NMState strictly as a service lacks an easy, automated failsafe . If your configuration contains a typo or structural mistake, it will apply on boot and can easily lock you out of your system's network interfaces . Always thoroughly test your files before automated deployment!
Here's a step-by-step guide on how I migrated my Hypervisor to declarative Network Config Management.
1. Installing NMState
[root@hyv02 ~]# dnf -y --refresh install nmstate 2. Capture the current config
[root@hyv02 ~]# nmstatectl show > /etc/nmstate/config.yaml
The generated configuration is going to be incredibly verbose. Interfaces that you don't want NMState to actively manage can be safely deleted from the file, along with detailed ethtool settings if you haven't explicitly customized them. Since we're living in the age of AI, you can easily feed this verbose text to an LLM to strip out the fluff, as it's a fantastic tool for parsing large amounts of configuration text quickly .
3. Crafting the Core Configuration
Below is a cleaned-up example snippet of what a finalized configuration looks like for a hypervisor host handling a 10G LACP bond, tagged VLANs, and Linux bridges assigned to virtual machines :
dns-resolver:
config:
server:
- 172.31.10.5
search:
- archyslife.lan
routes:
config:
- destination: 0.0.0.0/0
next-hop-interface: br0
next-hop-address: 172.31.10.254
interfaces:
# -- Physical Interfaces for Bonds --
# -- 10G Fiber Interfaces --
- name: ens5f0
type: ethernet
state: up
mtu: 9000
- name: ens5f1
type: ethernet
state: up
mtu: 9000
# -- Bond Interface (LACP) --
# -- 10G Fiber Interfaces --
- name: bond0
type: bond
state: up
mtu: 9000
link-aggregation:
mode: 802.3ad
port:
- ens5f0
- ens5f1
# -- VLANs on Bond --
# -- Public Server Network VLAN --
- name: bond0.100
type: vlan
state: up
mtu: 9000
vlan:
base-iface: bond0
id: 100
# -- Untrusted Server Network VLAN --
- name: bond0.200
type: vlan
state: up
mtu: 9000
vlan:
base-iface: bond0
id: 200
# -- VLAN Bridges for VMs --
# -- Internal Server Network --
- name: br0
type: linux-bridge
state: up
mtu: 9000
ipv4:
enabled: true
dhcp: false
address:
- ip: 172.31.10.249
prefix-length: 24
ipv6:
enabled: false
bridge:
port:
- name: bond0
# -- Public Server Network --
- name: br0.100
type: linux-bridge
state: up
mtu: 9000
ipv4:
enabled: false
ipv6:
enabled: false
bridge:
port:
- name: bond0.100
# -- Untrusted Server Network --
- name: br0.200
type: linux-bridge
state: up
mtu: 9000
ipv4:
enabled: false
ipv6:
enabled: false
bridge:
port:
- name: bond0.200
4. Testing the layout
Because NMState unfortunately doesn't include a built-in 'dry-run' validation command, we will test the configuration safely using our rollback timer. This command gives you a 30-second window to verify you still have access before automatically reverting the changes:
[root@hyv02 ~]# nmstatectl apply --no-commit --timeout 30 /etc/nmstate/config.yaml
If the configuration works as expected and your server remains perfectly reachable, go ahead and permanently commit those changes before the timer expires:
[root@hyv02 ~]# nmstatectl commit
5. Enforcing state on Boot
Now that you know your configuration is completely stable and valid, you can safely enable the NMState system service to apply these configurations at boot, mitigating the risk of future configuration drift:
[root@hyv02 ~]# systemctl enable --now nmstate.service
6. Final Verification
You can easily keep tabs on the service's execution and check the status of your configuration files using journalctl and ls:
[root@hyv02 ~]# journalctl -e -f -b 0 -u nmstate.service
[root@hyv02 ~]# ls -ahils /etc/nmstate
total 24K
8388896 0 drwxr-xr-x. 2 root root 42 May 19 22:16 .
8388738 16K drwxr-xr-x. 122 root root 12K May 20 08:36 ..
8390960 4.0K -rw-r-----. 1 root root 2.2K May 19 22:16 config.applied
8392075 4.0K -rw-r--r--. 1 root root 95 Dec 9 05:56 README
When configurations apply cleanly, you will notice your configuration file has taken on a '.applied' extension, and the underlying interfaces will be natively running inside NetworkManager.
Feel free to comment and / or suggest a topic.

Comments
Post a Comment