
Learn through the super-clean Baeldung Pro experience:
>> Membership and Baeldung Pro.
No ads, dark-mode and 6 months free of IntelliJ Idea Ultimate to start with.
Last updated: November 2, 2022
Many Linux distributions come with a network manager. In theory, it should help during the networking setup. Yet, we might not always want to install or use managers when setting up an interface. Moreover, a network manager is often just a convenient abstraction or interface to the configuration files of a Linux distribution.
In this tutorial, we look at standard low-level files and tools to configure our IP address settings. We start off by briefly discussing dynamic and static addresses. After picking static IP network configuration as an example, we look at a universal way to perform it under Linux. Next, we explore network managers in detail. Finally, we show our main example in action on multiple Linux distributions.
For brevity, we only use IPv4 instead of IPv6 and static instead of dynamic addresses, but most concepts apply to all variants.
We tested the code in this tutorial on Debian 12 (Bookworm), CentOS Stream 9, Slackware 15.0, Gentoo 2.8, and ArchLinux Rolling (2022.10.01). It should work in most POSIX-compliant environments.
When using a static IP, the operating system (OS) knows that we have two requirements for a given interface:
Since the Dynamic Host Configuration Protocol (DHCP) can take the Media Access Control (MAC) address into account when assigning the network-layer address, we might still automatically receive the same IP on each connection with that protocol. Moreover, the client can usually specify a preference.
However, whether we get the same IP address with DHCP might depend on many factors, some of which are external:
Thus, we give up control of our network-layer address, which may become inconvenient when it’s our sole means to identify a system. For example, switching environments can lead to a new IP. If we don’t have remotely-resolvable hostnames or domain names, we’d need this new IP when using access protocols like SSH. Further, a name (type) on one network could be unrecognizable on another.
On the other hand, a static IP ensures we always assign the same address. Of course, this comes with its own problems:
Still, for stationary machines and the proper administration, a static address is usually more of a convenience than a burden. So, we use that as our example configuration.
While there are many managers, graphical user interface (GUI) front-ends, and command-line interface (CLI) utilities for network settings, many boil down to the ip command, which supersedes ifconfig.
Let’s use ip to acquire and set our NIC configuration.
First, we check our current setup:
$ ip address show dev eth1
[...]
inet 192.168.6.2/24 brd 192.168.6.255 scope global dynamic noprefixroute eth1
[...]
Here, we have an IPv4 (inet) address of 192.168.6.2 with its associated 192.168.6.255 broadcast and several specifiers. Of the latter, dynamic means the system uses DHCP to set up the connection. Let’s confirm this:
$ journalctl | grep --ignore-case 'dhcp'
Oct 20 08:08:10 miner NetworkManager[729]: [1666253290.8110] dhcp: init: Using DHCP client 'internal'
Oct 20 08:08:11 miner NetworkManager[729]: [1666253291.5178] dhcp4 (eth1): activation: beginning transaction (timeout in 45 seconds)
Oct 20 08:08:11 miner NetworkManager[729]: [1666253291.5225] dhcp4 (eth1): state changed no lease
Oct 20 08:08:12 miner NetworkManager[729]: [1666253292.2943] dhcp4 (eth1): state changed new lease, address=192.168.6.2
Above, we use grep to case-insensitively filter for dhcp in the system log from the last boot as returned by journalctl. Consequently, we see the setup of our eth1 interface with the address 192.168.6.2.
In most recent Linux distributions, disabling DHCP comes down to controlling a daemon for the server (dhcpd) or client (dhcpcd):
$ systemctl stop dhcpcd dhcpd
$ systemctl disable dhcpcd dhcpd
However, there are several pitfalls:
Because of this, how and whether we turn DHCP off depends on the system and our needs.
Now, let’s use ip to set a static IP on eth1:
$ ip address flush dev eth1
$ ip route flush dev eth1
$ ip address add 192.168.6.66/24 brd + dev eth1
$ ip route add 192.168.6.1 dev eth1
$ ip route add default via 192.168.6.1 dev eth1
$ ip address show dev eth1
[...]
inet 192.168.6.66/24 brd 192.168.6.255 scope global eth1
[...]
After flushing all addresses and routes from eth1, we add a new static address and gateway. Next, we verify the settings by confirming that dynamic is no longer present in the interface characteristics. However, a system reboot now would wipe our network setup and restore the IP to what DHCP provides.
To make the settings we applied remain the same between reboots, we can run a script on startup, which includes the ip lines above, along with any other related commands. Naturally, the exact way depends on the Linux distribution.
Using a manager can be critical for complex setups. Yet, even a one-interface machine can benefit from the features network managers provide:
Critically, network managers are feature-rich abstractions to the network configuration files of a given system. While there are many Linux network managers like Connman, netctl, and wicd, three are ubiquitous:
Since most Linux distributions migrated to systemd, the first of these is now mostly deprecated, although still widely supported. Importantly, SysV network(ing) service configuration files provide the original framework commonly used by other network management solutions.
Before doing any network configuration on a Linux system, we should identify and disable unused network managers. Thus, it’s usually a good idea to start by checking for any related services:
$ systemctl --type=service | grep --ignore-case 'network'
NetworkManager-wait-online.service loaded active exited Network Manager Wait Online
NetworkManager.service loaded active running Network Manager
nis-domainname.service loaded active exited Read and set NIS domainname from /etc/sysconfig/network
systemd-network-generator.service loaded active exited Generate network units from Kernel command line
In this case, we use grep to search for the keyword network in the list of services. While not foolproof, this is a good first step. Consequently, we see NetworkManager is active and running.
We can simply use systemctl to detect and toggle most service-based network managers. For example, we can easily replace one manager with another where available:
$ systemctl stop NetworkManager NetworkManager-wait-online
$ systemctl disable NetworkManager NetworkManager-wait-online
$ systemctl start systemd-networkd systemd-networkd-wait-online
$ systemctl enable systemd-networkd systemd-networkd-wait-online
Notably, the *-wait-online and other secondary daemons that each solution offers are also part of the packages. While the enable and disable lines are optional, running conflicting services or configurations of any kind is considered bad practice and can lead to severe issues and system instability, especially regarding networking.
Of course, with services of this kind, any setup should be easier to configure and maintain. Adding to that, most managers have a GUI, terminal user interface (TUI), or at least a flexible CLI. Unlike ip, settings from network management tools can persist between reboots.
Now, we move to the most persistent, albeit in part, distribution-specific solutions.
Let’s check the default structure of networking configuration files in Debian derivatives such as Kali, Knoppix, Ubuntu, Raspberry Pi OS, and Tails:
$ tree /etc/network
/etc/network
├── if-down.d
├── if-post-down.d
├── if-pre-up.d
├── if-up.d
├── interfaces
└── interfaces.d
Here, the tree command shows the /etc/network/*.d directories for scripts that run before (pre), after (post), or while an interface (if) goes up or down. Next to them, the /etc/network/interfaces file contains the main network interface configuration, sourcing any files in the /etc/network/interfaces.d.
By default, to set a static IP on eth1 under Debian-based systems, we add a block to /etc/network/interfaces and remove any other configuration related to eth1:
auto eth1
iface eth1 inet static
address 192.168.6.66
netmask 255.255.255.0
gateway 192.168.6.1
broadcast 192.168.6.255
dns-nameservers 1.1.1.1, 1.0.0.1
Let’s break down the meaning of this block:
Of course, we can add more options like pre-up /etc/network/if-pre-up.d/secure.sh, which utilizes a script in the if-pre-up.d directory from earlier. Now, we’re ready to apply our configuration.
At this point, we just need to restart networking via SysV with /etc/init.d/networking (deprecated, not recommended), systemd, our network management tool, or directly for changes to take effect, depending on the system version:
$ /etc/init.d/networking restart
$ systemctl restart networking
$ systemctl restart NetworkManager
$ ifdown eth1; ifup eth1
Basically, the last command uses the legacy ifupdown package to only toggle the particular interface.
However, NetworkManager can also handle the native Debian network setup files. Importantly, the method of choice depends more on the version of the system and less on our preferences.
Finally, we can verify the new settings:
$ ip address show dev eth1
[...]
inet 192.168.6.66/24 brd 192.168.6.255 scope global eth1
[...]
Here, we see our changes are in effect via ip.
Again, we start by briefly looking at the network setup files in RedHat, SUSE, openSUSE, Fedora, CentOS, Oracle Linux, and other RPM-based Linux versions:
$ tree /etc/sysconfig -P 'network'
/etc/sysconfig
├── network
└── network-scripts
By utilizing the -P flag of tree, we can filter only network-related items in the /etc/sysconfig directory. In particular, /etc/sysconfig/network contains global options for all interfaces, while /etc/sysconfig/network-scripts/ifcfg-IFNAME files are responsible for configuring interface IFNAME.
However, since version 9 of RHEL, CentOS, Fedora, and other RPM-based distributions, ifcfg configuration files have been deprecated in favor of so-called keyfiles. This is also indicated by /etc/sysconfig/network-scripts-readme-ifcfg-rh.txt file:
$ cat /etc/sysconfig/network-scripts-readme-ifcfg-rh.txt
NetworkManager stores new network profiles in keyfile format in the
/etc/NetworkManager/system-connections/ directory.
[...]
Notably, keyfiles require the NetworkManager to function correctly.
The SysV-based network-scripts package contains tools and scripts for different functions:
In the case of RedHat and other related distributions, their newer versions have deprecated network-scripts in favor of NetworkManager.
To that end, some tools and scripts are either not available or have become wrappers for nmcli command lines. Consequently, for recent versions of RPM-based distributions, it’s usually best to leave NetworkManager installed, enabled, and started.
As an alternative, we might still be able to install the network-scripts package in its place, but that’s not recommended. If we do go that route, we must stop and disable NetworkManager via systemctl stop NetworkManager NetworkManager-wait-online, and systemctl disable NetworkManager NetworkManager-wait-online.
All of the above means that, while the interface settings files have mostly remained unchanged, their default processing has.
After considering the network setup mechanisms, to configure eth1 with a static IP on RPM distributions, we can simply add the necessary options in a deprecated /etc/sysconfig/network-scripts/ifcfg-eth1 file:
DEVICE=eth1
BOOTPROTO=none
ONBOOT=yes
IPADDR=192.168.6.66
NETMASK=255.255.255.0
GATEWAY=192.168.6.1
BROADCAST=192.168.6.255
DNS1=1.1.1.1
DNS2=1.0.0.1
USERCTL=no
NM_CONTROLLED=no
As before, let’s check what the options mean:
Of course, there are many other settings.
Alternatively, we can use the NetworkManager keyfiles instead. Let’s see an equivalent of the above in the new format:
$ cat /etc/NetworkManager/system-connections/eth1.nmconnection
[connection]
id=eth1
uuid=97666084-dead-beef-0010-06660bed4301
type=ethernet
autoconnect-priority=-999
interface-name=eth0
timestamp=1696896416
[ethernet]
[ipv4]
address1=192.168.6.66/24
gateway=192.168.6.1
dns=1.1.1.1,1.0.0.1
method=manual
[ipv6]
addr-gen-mode=eui64
method=disabled
[proxy]
Further, as indicated in /etc/sysconfig/network-scripts-readme-ifcfg-rh.txt, we can migrate all connections from the deprecated ifcfg format to the new keyfile format:
$ nmcli connection migrate
Notably, many keyfiles fields are the same in ifcfg files, while others are similar.
In addition, having to use NetworkManager for keyfiles means nmcli can perform our configuration directly:
$ nmcli connection modify eth1 ipv4.addr '192.168.6.66/24'
$ nmcli connection modify eth1 ipv4.gateway '192.168.6.1'
$ nmcli connection modify eth1 ipv4.dns '1.1.1.1,1.0.0.1'
This provides the added benefit of syntax checking.
Naturally, the changes are applied once we restart the networking.
There are two main options for that:
By default, we’d use nmcli or the NetworkManager service:
$ nmcli networking off; nmcli networking on
$ systemctl restart NetworkManager
Alternatively, we can employ nmcli and keyfiles to just manage the specific interface:
$ nmcli connection load /etc/NetworkManager/system-connections/eth1.nmconnection
$ nmcli connection up filename /etc/NetworkManager/system-connections/eth1.nmconnection
$ nmcli connection down eth1; nmcli connection up eth1
If we have them disabled, we can use basic tooling:
$ systemctl restart network
$ /etc/rc.d/init.d/network stop; /etc/rc.d/init.d/network start
$ ifdown eth1; ifup eth1
Once again, the last command only restarts eth1. Also, the method of choice depends on the version of the system and our needs.
Now, we can confirm eth1 has the correct settings:
$ ip address show dev eth1
[...]
inet 192.168.6.66/24 brd 192.168.6.255 scope global eth1
[...]
Here, we see that our interface has a static IP address.
In Slackware and its related distributions like Slax, the system startup goes through the original /etc/rc.d network file framework:
Of these, /etc/rc.d/rc.inet1 ensures we have a network, while /etc/rc.d/rc.inet1.conf sets the properties of our interfaces.
Indeed, recent Slackware versions often come with NetworkManager by default. Still, external network management solutions can interfere with our manual settings or add more on top of them. Because of this, we stop and disable NetworkManager and any other similar services:
$ /etc/rc.d/rc.networkmanager stop
$ chmod -x /etc/rc.d/rc.networkmanager
At this point, we can move on with the internal network setup mechanism.
Basically, to configure a static IP address for eth1 on Slackware-based distributions, we can simply replace or add options for that interface in /etc/rc.d/rc.inet1.conf:
IFNAME[0]="eth1"
IPADDR[0]="192.168.6.66"
NETMASK[0]="255.255.255.0"
USE_DHCP[0]=""
DHCP_HOSTNAME[0]=""
DEFAULT_GW="192.168.6.1"
GATEWAY="192.168.6.1"
Notably, the matching numbers (0) within square brackets indicate settings for the same interface. Also, unlike other methods, there are no options for DNS servers, as Slackware uses only /etc/resolv.conf by default. Of course, we don’t set values for DHCP options.
In Slackware-based Linux versions, the built-in networking restart mechanism is the /etc/rc.d/rc.inet1 script:
$ /etc/rc.d/rc.inet1 restart
Stopping the network interfaces...
Starting the network interfaces...
Now, we can confirm our new settings:
$ ip address show dev eth1
[...]
inet 192.168.6.66/24 brd 192.168.6.255 scope global eth1
[...]
Conveniently, Slackware-based distributions also include the netconfig tool. It provides an interactive way to configure most network settings.
Because Gentoo and its family are commonly source-based and highly flexible, we can perform their initialization process with many init systems.
By default, it’s the OpenRC init system, very similar to Slackware’s. Further, Gentoo uses Netifrc as its default integrated network configuration framework:
Because of this, interface setup means editing /etc/conf.d/net and creating the related service script for that interface. Of course, keeping with the general philosophy of Gentoo, we can remove or ignore the netifrc package in favor of external managers.
By default, to set a static IP on eth1 on Gentoo-based systems, we modify /etc/conf.d/net with our settings:
config_eth1="192.168.6.66 netmask 255.255.255.0 broadcast 192.168.6.255"
routes_eth1="default via 192.168.6.1"
dns_servers_eth1="1.1.1.1 1.0.0.1"
Here, options refer to the interface name with a suffix. The configuration is similar to the options of ip.
Next, to control the interface, we have to create a respectively-named script by making a symbolic link with ln to /etc/init.d/net.lo:
$ ln --symbolic /etc/init.d/net.lo /etc/init.d/net.eth1
In case /etc/init.d/net.lo is missing, we can acquire it via emerge:
$ cat /etc/init.d/net.lo
cat: /etc/init.d/net.lo: No such file or directory
$ emerge --oneshot --ask netifrc
These are the packages that would be merged, in order:
Calculating dependencies... done!
[ebuild N ] net-misc/netifrc-0.7.3
Would you like to merge these packages? [Yes/No] Yes
>>> Verifying ebuild manifests
>>> Emerging (1 of 1) net-misc/netifrc-0.7.3::gentoo
>>> Installing (1 of 1) net-misc/netifrc-0.7.3::gentoo
>>> Jobs: 1 of 1 complete Load avg: 0.66, 0.21, 0.07
* GNU info directory index is up-to-date.
$ cat /etc/init.d/net,lo
#!/sbin/openrc-run
[...]
Thus, we restored /etc/init.d/net.lo.
At this point, we are ready to start or restart our interface service net.eth1 with the new configuration:
$ rc-service net.eth1 restart
* Bringing up interface eth1
* Caching network module dependencies
* Starting netplug on eth1 ...
* Backgrounding ...
* WARNING: net.eth1 has started, but is inactive
Usually, the warning can safely be ignored.
To apply the settings on each restart, we add the script via OpenRC’s rc-update:
$ rc-update add net.eth1 default
* service net.eth1 added to runlevel default
Further, we can do the same via systemctl where available:
$ systemctl enable [email protected]
$ systemctl start [email protected]
Similar to Slackware’s netconfig, Gentoo includes the net-setup script for interactive network configuration.
Since ArchLinux is built from scratch, its family, including Manjaro and others, usually doesn’t provide its own network configuration framework. Instead, they integrate and leverage the framework of systemd-networkd by default:
$ tree /etc/systemd/network
/etc/systemd/network
├── 20-ethernet.network
└── 20-wlan.network
└── 20-wwan.network
This is more or less in contrast with Gentoo. Essentially, we can set a static IP in ArchLinux via systemd-networkd by creating a /etc/systemd/network/eth1.network file:
[Match]
Name=eth1
[Network]
Address=192.168.6.66/24
Gateway=192.168.6.66
Broadcast=192.168.6.255
DNS=1.1.1.1
DNS=1.0.0.1
Now, we just disable DHCP and restart systemd-networkd:
$ systemctl stop dhcpcd dhcpd
$ systemctl disable dhcpcd dhcpd
$ systemctl restart systemd-networkd
At this point, we should have the correct static IP on eth1.
In this article, we looked at network configuration under many different Linux distributions, with the main example of setting a static IP address.
In conclusion, while the way we configure our network setup can vary widely between Linux versions, there are also universal ways to perform it.