Skip to content

Configure a static IP address

In this tutorial, we will give a server's second network interface a fixed IPv4 address. First you'll look at the interfaces and addresses the system already has, then add an address by hand and take it away again, and finally make the address permanent so that it comes back after a reboot. By the end, you will have a Debian 13 server whose second interface always has the address 192.0.2.10, and you will know the difference between a change the kernel forgets and a change the system remembers.

Before you begin

  • A Debian 13 server built from the official cloud image, such as a virtual machine, with two network interfaces. The first interface is already working: it's the one you log in through with SSH. The second interface is connected but not configured yet.
  • A user account that can run commands with sudo.

Warning

Throughout this tutorial you change only the second interface. If you change or remove the address of the interface your SSH session uses, the session freezes and you need the server's console to get back in.

Step 1: list the network interfaces

Every network device the kernel knows about is a link. List them with ip link show:

$ ip link show
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
2: enp0s3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP mode DEFAULT group default qlen 1000
    link/ether 52:54:00:7a:00:01 brd ff:ff:ff:ff:ff:ff
    altname enx5254007a0001
3: enp0s4: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000
    link/ether 52:54:00:7a:00:02 brd ff:ff:ff:ff:ff:ff
    altname enx5254007a0002

Notice three links:

  • lo is the loopback interface, which the system uses to talk to itself.
  • enp0s3 is the first network interface. Its flags include UP and its state is UP: it's in use.
  • enp0s4 is the second network interface. It has no UP flag and its state is DOWN: nothing has switched it on.

The names on your server may be different. From now on, this tutorial writes the name of your second interface as <INTERFACE>. Wherever you see <INTERFACE>, type that name instead, for example enp0s4.

Step 2: look at the addresses

Now look at the IP addresses on each link. The -br option asks for a brief, one-line-per-link summary:

$ ip -br addr show
lo               UNKNOWN        127.0.0.1/8 ::1/128
enp0s3           UP             198.51.100.15/24 metric 100 2001:db8::5054:ff:fe7a:1/64 fe80::5054:ff:fe7a:1/64
enp0s4           DOWN

The first interface has an IPv4 address (yours will be different), and the second interface has none at all.

Step 3: add a temporary address

Switch the second interface on:

sudo ip link set <INTERFACE> up

Then give it the address 192.0.2.10 with a /24 prefix, which means the interface is on the network 192.0.2.0/24:

sudo ip addr add 192.0.2.10/24 dev <INTERFACE>

Look at the interface again, this time in full:

$ ip addr show dev <INTERFACE>
3: enp0s4: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
    link/ether 52:54:00:7a:00:02 brd ff:ff:ff:ff:ff:ff
    altname enx5254007a0002
    inet 192.0.2.10/24 scope global enp0s4
       valid_lft forever preferred_lft forever
    inet6 fe80::5054:ff:fe7a:2/64 scope link proto kernel_ll
       valid_lft forever preferred_lft forever

Notice the line starting with inet: that's your new IPv4 address. The interface is now UP, and the kernel also gave it an IPv6 link-local address (inet6 fe80::…) on its own. If you look very quickly, that line may also say tentative for a second or two, while the kernel checks that no other system uses the same address.

Adding an address does one more thing. Look at the routes that use the interface:

$ ip route show dev <INTERFACE>
192.0.2.0/24 proto kernel scope link src 192.0.2.10

The kernel added a route for the whole 192.0.2.0/24 network as soon as the address appeared. It now knows that any address in that network can be reached directly through <INTERFACE>.

Step 4: remove the temporary address

An address added with ip exists only in the running kernel. Nothing writes it to a file, so it would disappear at the next reboot. Remove it yourself now:

sudo ip addr del 192.0.2.10/24 dev <INTERFACE>

Check the interface again:

$ ip -br addr show dev <INTERFACE>
enp0s4           UP             fe80::5054:ff:fe7a:2/64

The IPv4 address is gone, and only the IPv6 link-local address remains. Look at the routes again:

ip route show dev <INTERFACE>

This time the command prints nothing: the route to 192.0.2.0/24 disappeared together with the address.

Step 5: find out what configures the network

To make an address permanent, you write it into the configuration that the system reads at boot. On the Debian 13 cloud image, that configuration is written for netplan, which turns it into settings for systemd-networkd, the service that actually sets up the interfaces.

The netplan configuration lives in /etc/netplan/:

$ ls /etc/netplan/
50-cloud-init.yaml

Look at the file that's already there:

$ sudo cat /etc/netplan/50-cloud-init.yaml
network:
  version: 2
  ethernets:
    primary:
      match:
        macaddress: "52:54:00:7a:00:01"
      dhcp4: true

This file configures only the first interface (it matches its hardware address), and asks for an address by DHCP. Your file may look a little different, but it doesn't mention your second interface.

Now ask systemd-networkd which links it manages:

$ networkctl
IDX LINK   TYPE     OPERATIONAL SETUP
  1 lo     loopback carrier     unmanaged
  2 enp0s3 ether    routable    configured
  3 enp0s4 ether    carrier     unmanaged

3 links listed.

Notice that the second interface is unmanaged: no configuration applies to it yet.

Step 6: make the address permanent

Create a new netplan file for the second interface. The command below writes the file /etc/netplan/60-static.yaml in one go; type it exactly, with your interface name in place of <INTERFACE>:

sudo tee /etc/netplan/60-static.yaml > /dev/null << EOF
network:
  version: 2
  ethernets:
    <INTERFACE>:
      addresses:
        - 192.0.2.10/24
EOF

The file says: for the Ethernet interface with this name, set the address 192.0.2.10/24. YAML is sensitive to indentation, so keep the spaces exactly as shown.

Netplan expects its files to be readable only by root, because they can contain passwords for some kinds of network. Restrict the permissions:

sudo chmod 600 /etc/netplan/60-static.yaml

Now apply the configuration:

sudo netplan apply

Netplan reads every file in /etc/netplan/, writes the matching systemd-networkd configuration and tells systemd-networkd to use it. Check the result:

$ networkctl
IDX LINK   TYPE     OPERATIONAL SETUP
  1 lo     loopback carrier     unmanaged
  2 enp0s3 ether    routable    configured
  3 enp0s4 ether    routable    configured

3 links listed.

The second interface is now configured. Look at its address:

$ ip -br addr show dev <INTERFACE>
enp0s4           UP             192.0.2.10/24 fe80::5054:ff:fe7a:2/64

The address is back, but this time systemd-networkd set it, from a file.

Step 7: reboot and check again

The real test of a permanent setting is a reboot. Restart the server:

sudo reboot

Your SSH session closes. Wait a minute, then log in again and look at the second interface:

$ ip -br addr show dev <INTERFACE>
enp0s4           UP             192.0.2.10/24 fe80::5054:ff:fe7a:2/64

The address 192.0.2.10/24 is there. Nobody ran ip addr add this time: systemd-networkd read the configuration you wrote and applied it during boot.

What you have learned

  • ip link show lists the network interfaces, and ip link set <INTERFACE> up switches one on.
  • ip addr show displays addresses; -br gives a short summary.
  • ip addr add and ip addr del change addresses immediately, but only until the next reboot.
  • Adding an address also adds a route to its network.
  • On the Debian 13 cloud image, permanent network settings are netplan files in /etc/netplan/, applied by systemd-networkd; sudo netplan apply puts a change into effect without a reboot.
  • networkctl shows which interfaces systemd-networkd manages.

Next steps