Static IP in the House

Pin a computer's IP to your router's wall

Moving target

If you’re into home networking and DIY projects, you’ve probably been through bitter experiences where your devices get assigned a random IP address every so often, forcing you to spend precious time—15+ seconds—to find its new address in the local network. That’s unacceptable!

One way to fix that intolerable annoyance is by making a DHCP reservation in your router, which is the most usual means of acquiring an unchanging IP address. But sometimes you need to go more aggressive, y’know what I mean?, and in those cases a static IP address set up directly on the device is your best option. That’s what we’ll be doing in this article, and we’re going to use a Raspberry Pi for that.

DHCP reservation versus static IP address

One of the greatest advantages of a dynamic IP address is that you don’t have to move a finger in order to get it working. Connect your device to the LAN and it gets an IP address out of the box. The router does all the work for you. If you want that address to stay put, just tell the router (actually, the router’s DHCP server) to reserve that IP address so that it doesn’t get assigned to any other device in the network.

That’s called a DHCP reservation or static DHCP allocation. It’s easy, elegant and will fulfil most of your needs. Some routers are so locked down that they won’t give you that option, but if yours comes with that feature enabled, you should definitely take advantage of it. One of the nicest things about it is that you can control everything from a central location—your router’s GUI.

Why go through the hassle of manually defining a static IP address, then? Servers. You hardly ever want their IP address to change, even after resetting the router. This is the rule of thumb I apply to SOHO networks:

  • laptops, desktops, tablets, smart phones etc.: dynamic DCHP (plug and play);
  • printers, IOT devices, IP cameras: static DHCP (DHCP reservation configured in the router);
  • servers: static IP address configured directly in the machine.

With that being said, let’s get our hands dirty and assign a static IP to our RPi.

Gathering the LAN’s information

First off, log into your router’s web GUI. The web GUI is usually accessible from 192.168.0.1 or 192.168.2.1—consult your router’s manual otherwise.

Once there, get the general information about the local network. In the router provided to me by my ISP (a horrid Hitron CGN3), that information goes under the Basic tab, where I can find the LAN address (192.168.0.1), subnet mask (255.255.255.0) and DHCP reservation block (192.168.0.10192.168.0.200). Note that all of these are default values set by my router’s vendor—the same ones I’d get if I were to perform a factory reset.

/img/2018/07/2018-07-24-static-ip-in-the-house/router-basic-settings-thumb.jpg

Router's GUI.

You can also use netstat to grab that kind of information:

netstat -rn

If your router comes with DHCP reservation enabled, it will usually start its reservation block at a low address. In my case, that’s 192.168.0.10, which means that any IP addresses below that value will not be assigned to any devices by default. Those untouchable addresses are the ones I assign to my servers, because I know they’ll never be leased by my router’s DHCP server.

If you feel those are not enough (maybe you have a mini data center in your closet, like someone I know…), you can always change the default values in the router and increase the beginning of the reservation block to fit your needs. You could have a DHCP reservation block starting at 192.168.0.300, for instance.

Decide what IP address you want to use

For this tutorial, I’d like to get the IP address closest to the router’s. You may remember that my router’s IP address is 192.168.0.1, so I’ll try to use 192.168.0.2 on my RPi.

We can check the router to see if that IP is already assigned to a machine or ping the address directly from the terminal:

ping -c3 192.168.0.2

If you get Destination Host Unreachable as a result, you’re probably safe to use that IP address. If it’s already taken but the device it is assigned to doesn’t really need that specific IP address, you may need to manually move that device somewhere else in the DHCP block reservation, which is easily doable through the router’s web interface.

Assign IP address statically

SSH into the RPi and run ifconfig -a to list all network interfaces. In my case, because there’s no wi-fi card connected to the RPi, the only entries I see are eth0 and lo—I’ll talk about wi-fi and wlan0 later on. lo (loopback) is a virtual network interface and can be completely ignored for our current purposes. For now, we’ll only set up the Ethernet interface, eth0, to statically use the IP address mentioned above (192.168.0.2).

Before we proceed, a note of warning about previous versions of the Raspbian OS. On Raspbian/Debian Wheezy and older (pre-SystemD), most network options were configured inside the /etc/network/interfaces file. Since Raspbian/Debian Jessie, that’s not the best place to set up a static IP address any more:

$ cat /etc/network/interfaces
# interfaces(5) file used by ifup(8) and ifdown(8)

# Please note that this file is written to be used with dhcpcd
# For static IP, consult /etc/dhcpcd.conf and 'man dhcpcd.conf'

# Include files from /etc/network/interfaces.d:
source-directory /etc/network/interfaces.d

That’s also true of Debian/Raspbian Stretch; instead of /etc/network/interfaces, we’ll be using the DHCP client daemon’s config file (/etc/dhcpcd.conf). These are the parameters we’ll be playing with:

  • interface: specifies what network interface the options should be applied to;
  • static ip_address: specifies a static (pre-determined) IP address to be assigned to the interface;
  • static routers: specifies the IP address of the device responsible for routing requests (usually your network router);
  • static domain_name_servers: specifies the IP address(es) of the device(s) responsible for DNS resolution (usually your network router).

Start by making a backup copy of that config file:

sudo cp /etc/dhcpcd.conf /etc/dhcpcd.conf.bak

After that, we can change the network configurations of the RPi to use a static IP instead of DHCP assignments (indentation is optional but highly recommended):

sudo tee -a /etc/dhcpcd.conf << END
interface eth0
    static ip_address=192.168.0.2/24
    static routers=192.168.0.1
    static domain_name_servers=192.168.0.1
END

If you’re confused about that /24, that’s just the netmask value shown in my router’s web GUI (255.255.255.0), only this time it was converted to CIDR notation. If your netmask is different than 255.255.255.0, you can easily find a CIDR translator online.

We now have to reboot the RPi in order for those changes to take effect:

sudo reboot

We could instead restart the network interface (ifdown eth0 && ifup eth0) or force a DHCP release (dhclient -r eth0), but those would break the SSH connection and log us out of our session anyway, so what’s the point?

You should now be able to SSH into the RPi with the new address:

ssh pi@192.168.0.2

Why this works

Think of a static IP as just a self-assigned IP. The most important thing to note here is that assigning a static IP to the RPi’s eth0 interface doesn’t mean we’re turning DHCP off; the RPi’s DHCP client daemon, dhcpcd, keeps running and communicating over the LAN:

$ sudo netstat -lpnut | grep 68
udp        0      0 0.0.0.0:68              0.0.0.0:*                           353/dhcpcd
$ sudo dhcpcd -T eth0
eth0: IPv6 kernel autoconf disabled
DUID xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx
eth0: IAID xx:xx:xx:xx
eth0: using static address 192.168.0.2/24
interface='eth0'
pid='xxxx'
reason='TEST'
ifcarrier='up'
ifflags='4163'
ifmtu='1500'
ifwireless='0'
new_broadcast_address='192.168.0.255'
new_domain_name_servers='192.168.0.1'
new_ip_address='192.168.0.2'
new_network_number='192.168.0.0'
new_subnet_cidr='24'
new_subnet_mask='255.255.255.0'
dhcpcd exited

And that’s expected behavior, because all we did so far was ask the RPi’s network stack to cancel out DHCP assignments on the eth0 interface; at no point did we “turn off DHCP.” In other words, DHCP is still working on the RPi and talking to the router, it’s just not assigning values on the eth0 interface anymore.

Wi-Fi

If your RPi is connected to wi-fi, then you need to make the wlan0 interface bypass DHCP assignments as well. There are two steps involved in this process, the first one being very similar to the DHCP configuration we used for the eth0 interface. All we need to do is replace eth0 with wlan0 and replay the command, like this:

sudo tee -a /etc/dhcpcd.conf << END
interface wlan0
    static ip_address=192.168.0.2/24
    static routers=192.168.0.1
    static domain_name_servers=192.168.0.1
END

The second step is to update the file /etc/wpa_supplicant/wpa_supplicant.conf, which is the configuration file used by the system’s WPA supplicant daemon. Start by making a backup copy of that file:

sudo cp /etc/wpa_supplicant/wpa_supplicant.conf /etc/wpa_supplicant/wpa_supplicant.conf.bak

Before modifying the original file, we’ll need two pieces of information: the wi-fi’s SSID (network name) and password. Your next command should be similar to the following:

sudo tee -a /etc/wpa_supplicant/wpa_supplicant.conf << END
network={
    ssid="Why, Phy?"
    psk="SuperSecretPasswordGoesHere"
}
END

Replace ssid and spk accordingly. All that’s left now is rebooting the RPi:

sudo reboot

Finito. To confirm that the RPi is reachable over wi-fi, unplug the Ethernet cable from it and try to connect using its static IP address:

ssh pi@192.168.0.2

Conclusion

You don’t have to worry about your local servers’ IP addresses changing any more. As long as you only use addresses that are outside the router’s default DHCP lease poll, even a router reset will keep those static IP addresses intact.

diy  hardware  home  rpi  sbc  soho