Skip to content
DevOps devops networking 6 min read

IP Addresses & Subnets

Every device on a network needs a unique address so that data knows where to go, just like every house on a street needs a postal address. That address is the IP address (IP stands for Internet Protocol, the set of rules computers use to send data to each other). As a DevOps engineer you will read, type, and reason about IP addresses every single day, so getting comfortable with how they are built and how subnets carve them up is one of the highest-value things you can learn early.

What an IPv4 address looks like

An IPv4 address (version 4 of the Internet Protocol, the most common kind) is written as four numbers separated by dots, like 192.168.1.10. Each of those four numbers is called an octet because, under the hood, it is 8 binary bits. Eight bits can hold a value from 0 to 255, so each octet is always somewhere between 0 and 255.

Four octets of 8 bits each gives you 32 bits total. That means there are only about 4.3 billion possible IPv4 addresses in the whole world. That sounds like a lot, but we ran out years ago, which is one reason private addresses and IPv6 (covered below) exist.

An IP address actually carries two pieces of information at once:

  • The network part — which network the device belongs to (the “street”).
  • The host part — which specific device it is on that network (the “house number”).

The subnet mask, explained later, is what decides where the network part ends and the host part begins.

Public vs private IP addresses

Not all IP addresses are equal. Some are public (reachable from anywhere on the internet) and some are private (only usable inside a local network, like your home, office, or a cloud Virtual Private Cloud).

Private addresses were deliberately set aside in three ranges. Any address inside these ranges is private and will never appear directly on the public internet:

RangeCIDRCommon use
10.0.0.010.255.255.25510.0.0.0/8Large networks, cloud VPCs (AWS, GCP)
172.16.0.0172.31.255.255172.16.0.0/12Mid-size networks, Docker default bridge
192.168.0.0192.168.255.255192.168.0.0/16Home and small-office routers

When a device with a private IP needs to reach the internet, a router translates its private address into a shared public one. That trick is called NAT (Network Address Translation), and it has its own page in this section.

Never expose a service that you think is “internal” without checking its bind address. A database listening on 0.0.0.0 (all interfaces) instead of 127.0.0.1 (localhost only) can be reachable from outside even if you assumed it was private. Always confirm with ss -tlnp.

When to use which: use private ranges for everything that talks only inside your own network — app servers talking to databases, containers talking to each other. Reserve public IPs for the few things that genuinely must be reachable from the internet, such as a web server or a load balancer.

CIDR notation and subnets

CIDR (Classless Inter-Domain Routing, pronounced “cider”) is the modern way to describe a block of IP addresses. It looks like 192.168.1.0/24. The number after the slash, the prefix length, tells you how many of the 32 bits belong to the network part. The remaining bits are free for hosts.

Here is the gentle math. The slash number is how many bits are “locked” as network. Whatever is left over is for hosts, and the number of host addresses is 2^(32 - prefix).

Take /24 as the everyday example:

  • /24 means 24 network bits, leaving 32 - 24 = 8 host bits.
  • 2^8 = 256 total addresses, from .0 to .255.
  • Two of those are reserved: .0 is the network address itself and .255 is the broadcast address (used to talk to every host at once). So you get 254 usable addresses.

A quick reference table for the most common subnet sizes:

CIDRSubnet maskTotal addressesUsable hosts
/24255.255.255.0256254
/25255.255.255.128128126
/26255.255.255.1926462
/30255.255.255.25242

The bigger the slash number, the smaller the network. A /30 is handy for a point-to-point link between two routers because it gives you exactly two usable addresses and wastes nothing.

When to use this: you will choose CIDR ranges when you create a cloud network. A common, sane starting point is a /16 for the whole VPC and /24 blocks for each subnet inside it, which leaves plenty of room to grow.

IPv6 in brief

Because IPv4 ran out of addresses, IPv6 (version 6) was created. It uses 128 bits instead of 32, which gives an almost unimaginable number of addresses. They are written in hexadecimal (base-16) groups separated by colons, like 2001:0db8:85a3:0000:0000:8a2e:0370:7334. Long runs of zeros can be shortened with ::, so that same address can be written 2001:db8:85a3::8a2e:370:7334.

You do not need to master IPv6 to start with, but you should recognise it. Many cloud providers and modern networks now assign IPv6 addresses by default, and tools will happily show you both.

Finding your IP address on Ubuntu

On a fresh Ubuntu server (22.04 or 24.04 LTS), the modern command is ip addr. It lists every network interface and the addresses assigned to it.

ip addr show

Output:

1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN
    inet 127.0.0.1/8 scope host lo
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP
    inet 10.0.1.42/24 brd 10.0.1.255 scope global dynamic eth0
    inet6 2600:1f18:abcd::42/64 scope global dynamic

Reading this: lo is the loopback interface (the machine talking to itself) at 127.0.0.1. eth0 is the real network card with a private IPv4 of 10.0.1.42 in a /24 subnet, plus an IPv6 address. The brd line shows the broadcast address.

To see only your IPv4 addresses without the noise:

ip -4 addr show eth0

That command shows you the private address of the machine. To find the public address the internet sees (the one NAT translates you to), ask an outside service:

curl -s https://ifconfig.me

Output:

203.0.113.57

Best practices

  • Always know whether an address is public or private before you open a firewall rule for it — getting this wrong is a top cause of accidental exposure.
  • Plan CIDR ranges before building a network; resizing a subnet later usually means rebuilding it.
  • Use /24 blocks as your default subnet size unless you have a specific reason to go smaller or larger — they are easy to read and leave room to grow.
  • Bind sensitive services to 127.0.0.1 (localhost) by default and only expose them deliberately.
  • Prefer the ip command (ip addr, ip route) over the old, deprecated ifconfig, which is not installed on modern Ubuntu by default.
  • Document your subnet layout so the next engineer knows which range does what.
Last updated June 15, 2026
Was this helpful?