1. Introduction

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.

2. Dynamic and Static IP Address

When using a static IP, the operating system (OS) knows that we have two requirements for a given interface:

  • a specific IP address
  • full control over the address assignment

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:

  • DHCP server IP reservation
  • same DHCP server
  • unchanged DHCP server configuration
  • same network interface card (NIC) or MAC address

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:

  • manual settings might not comply with a given environment
  • might have to change configuration depending on the network
  • can lead to IP address conflicts, especially on smaller networks

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.

3. Static IP on Linux

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.

3.1. Current Settings

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.

3.2. Consider DHCP

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:

  • we might not need to disable DHCP at all if it’s properly configured
  • the daemon name and control mechanisms can vary
  • on older systems, DHCP client calls can instead be in other services
  • custom solutions can provide and force DHCP depending on the Linux distribution

Because of this, how and whether we turn DHCP off depends on the system and our needs.

3.3. Temporary Static IP via ip

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.

3.4. Permanent Static IP via ip

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.

4. Network Managers

Using a manager can be critical for complex setups. Yet, even a one-interface machine can benefit from the features network managers provide:

  • seamlessly detect networks
  • automatically configure connections
  • maintain and switch between configuration profiles
  • support multiple protocols, wireless and wired

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.

4.1. Identify Network Managers

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.

4.2. Control Network Managers

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.

5. Static IP on Debian Distributions

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.

5.1. Add Interface Configuration

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:

  • auto eth1 enables automatic configuration for this interface during boot
  • iface eth1 inet static sets eth1 as an IPv4 interface with a static address
  • address, netmask, and gateway assign the respective addresses and network
  • dns-nameservers, while not strictly necessary, sets the DNS servers to use

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.

5.2. Restart Networking or Interface

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.

5.3. Confirm Setup

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.

6. Static IP in RedHat and Other RPM Distributions

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.

6.1. network-scripts and NetworkManager

The SysV-based network-scripts package contains tools and scripts for different functions:

  • /etc/init.d/network script to stop, start, and restart network components
  • ifup*, ifdown*, and other /etc/sysconfig/network-scripts directory scripts
  • ifup and ifdown native tools for interface state toggling
  • usernetctl native command for general network configuration

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.

6.2. Create Interface Configuration File

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:

  • DEVICE=eth1 ensures we have the correct interface name
  • BOOTPROTO is dhcp for DHCP, but our static configuration doesn’t require any protocol, so we use none
  • ONBOOT=yes, similar to Debian’s auto, indicates the interface should be activated on boot
  • IPADDR, NETMASK, GATEWAY, and BROADCAST are all set to their respective values for our static address
  • DNS1 and DNS2 optionally set DNS servers
  • USERCTL=no prevents non-superusers to control the interface
  • NM_CONTROLLED=no stops NetworkManager from managing the interface

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.

6.3. Restart Networking or Interface

Naturally, the changes are applied once we restart the networking.

There are two main options for that:

  • with systemd
  • directly via network-scripts with /etc/rc.d/init.d/network (deprecated, not recommended)

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.

6.4. Confirm Setup

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.

7. Static IP in Slackware Distributions

In Slackware and its related distributions like Slax and Absolute Linux, the system startup goes through the original /etc/rc.d network file framework:

  • /etc/rc.d/rc.inet1
  • /etc/rc.d/rc.inet1.conf
  • /etc/rc.d/rc.inet2

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.

7.1. Disable Network Managers

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.

7.2. Modify Interface Configuration

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.

7.3. Restart Networking

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.

8. Static IP in Gentoo Distributions

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:

  • /etc/conf.d/net for general interface setup (usually created by an administrator)
  • /etc/init.d/net.lo and /etc/init.d/net.* scripts to control interfaces

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.

8.1. Add Interface Configuration

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.

8.2. Restart the Interface

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.

9. Static IP in ArchLinux Distributions

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.

10. Summary

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.

Comments are open for 30 days after publishing a post. For any issues past this date, use the Contact form on the site.