NetworkManager is a daemon for configuring the network on Linux. It’s all about connection profiles, which are created by the user and “activated” by NetworkManager. A profile is just a bunch of settings and configuration values with defined keys and values, that can be sent over D-Bus or persisted to disk. Currently two file formats exists for that purpose: keyfile and ifcfg-rh. Let’s take a look at the history and future of the ifcfg-rh format.
About initscripts
The very short version of the history is that various Linux distributions use the System V “initscripts” for system configuration and management. For example, the Fedora variant is (un)maintained at github/fedora-sysv. One part of initscripts is concerned about network and provides two scripts ifup
and ifdown
and a SysV-style init service network
. On Fedora and RHEL, users would edit files like /etc/sysconfig/network-scripts/ifcfg-eth0
according to the documentation. These files are the “profiles” in the sense that they are configurations for a network interface.
The network-scripts part of initscripts are really a bunch of shell scripts that parse ifcfg files (by executing them as shell scripts) and configure the network accordingly. They do so by calling iproute2 (the ip
tool) to setup interfaces and IP addresses in kernel. But the scripts can also start ISC’s dhclient
to do DHCP, in which case the DHCP daemon keeps running in the background.
As such, initscripts are a simple thing that work well for what they are. But they are one-shot commands that do their task and quit. This is a fundamental limitation, despite that they leave some state for the next time when they run — like the PID file of dhclient or an IP address configured on an interface. Another problem is that their API essentially is to have users write an ifcfg file and reboot. Yes, you can also manually call ifup
and ifdown
to apply changes, but that might not reliably work in subtle cases. For example if you change the DEVICE=
name in the ifcfg file that is currently up, ifdown
wouldn’t know that there was something to tear down. Or calling ifup
twice in a row can lead to errors. The scripts simply don’t know the current state. Such an API is not well suited to build applications that configure the network, like a GUI or cockpit. Providing such an API is the main reason why NetworkManager exists.
NetworkManager handles ifcfg Files
When NetworkManager was first introduced at around 2004, initscripts and ifcfg was the way to configure the network on Fedora Core. Consequently, NetworkManager persisted its connection profiles also in ifcfg format because users were already familiar with the format and because it already existed. Also initscripts on Fedora/RHEL started to integrate with NetworkManager. When you called ifup
, the script would check whether NetworkManager is running and manages the profile, in which case the script will call nmcli connection up
to let NetworkManager handle it. This can be prevented by configuring a key NM_CONTROLLED=no
in the ifcfg file.
While a goal was that the same ifcfg file can be used both by initscripts and NetworkManager in a similar way, in practice this only works with simple configurations. NetworkManager defines a large number of additional shell variables that are not supported by initscripts. And likewise, in several ways initscripts will behave differently than NetworkManager. For example, NetworkManager does not support IP aliases and the way Openvswitch and Wi-Fi configuration is expressed in ifcfg files is fundamentally incompatible. Also, not every NetworkManager profile can be persisted in ifcfg format, in which case NetworkManager always uses the keyfile format.
In Fedora 29 the network-scripts
package was split out of the initscripts
package. On recent Fedora and RHEL, the network-scripts
package is not installed by default. They are considered deprecated but still available for installation. Note that the initscripts
package itself does things beyond network configuration and that part is still in use.
Moving away from ifcfg files
As far as NetworkManager is concerned, it keeps handling ifcfg files. Regardless whether network-scripts are in use, the file format is used by NetworkManager, along side the keyfile
format which has ini style files in /{etc,run,usr/lib}/NetworkManager/system-connections
. Note that the keyfile backend is the preferred format of NetworkManager and the one that can handle all connection types. It is thus always enabled in NetworkManager. You can only select whether to use the ifcfg-rh
backend in addition. This is done via the main.plugins
setting in NetworkManager.conf. Before Fedora 34, this setting had a default of main.plugins=ifcfg-rh,keyfile
. Since Fedora 34 it defaults to main.plugins=keyfile,ifcfg-rh
. The difference is that now NetworkManager preferably writes new profiles in keyfile format. This change is a step away from using the ifcfg-rh
format.
It will probably take a while until NetworkManager completely gets rid of supporting ifcfg-rh format. The difficulty is that this concerns user configuration on disk, and it is important to NetworkManager to not break during package upgrade or during upgrade to a newer Fedora/RHEL release. To do this, we will also need to write migration tools that can convert ifcfg files to keyfile format. And in the end, if a user or tool relied on finding an ifcfg file, the change will be noted and might break existing setups. There is no hurry for you to migrate, but be aware that eventually we want to get rid of the ifcfg file format. The reason is that maintaining multiple formats has an overhead, not only for the development but for users who need to learn two formats and for tools that not work if an unexpected format is used. It’s also desirable that NetworkManager on Fedora/RHEL uses the same format as it does on most other Linux distributions.
Example of the ifcfg Format
If we create a new connection profile with
nmcli connection add type ethernet con-name eth0 \ ifname eth0 autoconnect no
then this results in the following ifcfg file:
# cat /etc/sysconfig/network-scripts/ifcfg-eth0 TYPE=Ethernet PROXY_METHOD=none BROWSER_ONLY=no BOOTPROTO=dhcp DEFROUTE=yes IPV4_FAILURE_FATAL=no IPV6INIT=yes IPV6_AUTOCONF=yes IPV6_DEFROUTE=yes IPV6_FAILURE_FATAL=no IPV6_ADDR_GEN_MODE=stable-privacy NAME=eth0 UUID=a64c3983-5a14-46ef-90e4-e3ec4e57e8a5 DEVICE=eth0 ONBOOT=no
In comparison, in keyfile format this looks like
# cat /etc/NetworkManager/system-connections/eth0.nmconnection [connection] id=eth0 uuid=fbd13bf5-01d9-4569-ba79-f2d79daf79c8 type=ethernet autoconnect=false interface-name=eth0 permissions= [ethernet] mac-address-blacklist= [ipv4] dns-search= method=auto [ipv6] addr-gen-mode=stable-privacy dns-search= method=auto [proxy]
Subjectively, I find the ini style format nicer. It’s also based on glib’s GKeyfile API that can parse these files into some form of dictionary. Also, libnm provides an API to convert NMConnection
instaces to/from keyfile.