How to Check IP Address in Linux: ip addr, hostname -I, curl
- October 30, 2026
- 9:00 am
- By Adrien Roche
- Networking

Check your IP address in Linux with ip addr
The command that answers "what is my IP address" on any current Linux distribution is ip, from the iproute2 package. It ships by default on every major distribution, works without root, and is what the other commands in this guide wrap or have been replaced by. The basic form lists every interface with all of its addresses:
ip addr show
ip a # same thing, shorterOn a server with a single network card the output looks like this (the valid_lft lifetime lines are trimmed):
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
inet 127.0.0.1/8 scope host lo
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
link/ether 52:54:00:12:34:56 brd ff:ff:ff:ff:ff:ff
inet 203.0.113.25/24 brd 203.0.113.255 scope global eth0
inet6 2001:db8:1::25/64 scope global
inet6 fe80::5054:ff:fe12:3456/64 scope linkHow to read it:
- Interface name.
lois the loopback, always127.0.0.1, reachable only from the machine itself. The real card iseth0here; with predictable interface names it appears asens3,enp0s3oreno1, and wireless cards start withwl. inetis the IPv4 address,inet6the IPv6. The/24suffix is the prefix length in CIDR notation, the modern spelling of the netmask255.255.255.0.scope globalmeans routable beyond this host;scope link(thefe80::line) is valid only on the attached network segment;scope hostis loopback.state UPwithLOWER_UPmeans the interface is enabled and has a link.state DOWNorNO-CARRIERis the usual reason an interface has no address at all.
Useful variants:
ip -4 addr # IPv4 only
ip -6 addr # IPv6 only
ip -br -4 addr # one line per interface
ip -4 addr show dev eth0 # a single interfaceThe brief form (-br) is the fastest way to check an IP address in Linux when several interfaces exist, the normal situation on a VPS running Docker:
$ ip -br -4 addr
lo UNKNOWN 127.0.0.1/8
eth0 UP 203.0.113.25/24
docker0 DOWN 172.17.0.1/16hostname -I: just the addresses
When you only need the addresses, hostname -I (capital I) prints every configured address on one line, space-separated, loopback and IPv6 link-local excluded:
$ hostname -I
203.0.113.25 2001:db8:1::25Two caveats. The lowercase hostname -i is a different command: it resolves the machine's hostname through /etc/hosts and DNS, which on Debian and Ubuntu usually yields 127.0.1.1. And hostname -I prints addresses in no guaranteed order, virtual bridges such as docker0 included, so hostname -I | awk '{print $1}' is a shortcut for humans, not a reliable "primary IP" for scripts. The option is not POSIX: Debian, Ubuntu, Fedora and RHEL have it, minimal BusyBox-based images such as Alpine may not.
ifconfig, nmcli and networkctl
ifconfig (deprecated, net-tools)
ifconfig is what older tutorials show. It belongs to net-tools, deprecated in favour of iproute2 for years and no longer in the default install of current Ubuntu, Debian and Fedora/RHEL releases. If it returns command not found, switch to ip or install the package:
sudo apt install net-tools # Debian / Ubuntu
sudo dnf install net-tools # Fedora / RHEL / Rocky / Alma$ ifconfig eth0
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 203.0.113.25 netmask 255.255.255.0 broadcast 203.0.113.255
inet6 fe80::5054:ff:fe12:3456 prefixlen 64 scopeid 0x20<link>Readable, but with a real limitation: ifconfig shows only one IPv4 address per interface. Secondary addresses added with ip addr add, common on a VPS with several public IPs, are invisible to it.
nmcli and networkctl
Desktops and Fedora/RHEL-family servers manage their network with NetworkManager; Ubuntu Server uses netplan on top of systemd-networkd, and many VPS images follow the same model. Each has a status tool that shows address, gateway and DNS in one block:
nmcli device show eth0
nmcli -g IP4.ADDRESS device show eth0 # NetworkManager: just the address field
networkctl status eth0 # systemd-networkdThe -g (--get-values) flag prints the bare value of one field, prefix length included, which is handy for scripts. If you are not sure which stack your machine runs, or even which distribution and release it is, identify the OS version from the command line first; the answer decides which tool is present.
Find your public IP address with curl
Everything above reports the address configured on the interface. On most VPS the public IPv4 is assigned directly to the interface, so that is also what the internet sees. At home, in an office or on some clouds, the interface carries a private address from the RFC 1918 ranges (10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16) and a router or a 1:1 NAT translates it on the way out. The only reliable way to see the public side is to ask an external service:
curl -4 icanhazip.com
curl -4 ifconfig.me/ip
curl -4 https://api.ipify.org
curl -6 icanhazip.com # public IPv6, if the host has oneThe -4 and -6 flags force the address family, which matters on dual-stack hosts: without them curl may prefer IPv6 and return an address you did not expect. icanhazip.com has been operated by Cloudflare since 2021 and returns plain text. Read the answer as "the address my traffic leaves from": behind a VPN or a proxy it is the exit node's address, not your ISP's.
IPv6: global versus link-local
Almost every Linux interface shows at least one inet6 line, and it is often mistaken for a public IPv6 address. The line beginning with fe80:: and marked scope link is link-local: every interface generates one automatically, it is valid only on the attached network, and it is never reachable from the internet. A public IPv6 address is marked scope global and starts with a 2 or a 3, since global unicast space is 2000::/3.
ip -6 addr show scope global
ip -6 route show defaultIf the first command prints nothing, the machine has no routable IPv6 and curl -6 will fail. Extra global addresses flagged temporary on a desktop come from privacy extensions; servers keep those off so the address stays stable for DNS and firewall rules.
Default gateway, route and DNS
An address on its own does not tell you whether the machine can reach anything. The routing table does, and ip route (short form ip r) prints it:
$ ip route
default via 203.0.113.1 dev eth0 proto static
203.0.113.0/24 dev eth0 proto kernel scope link src 203.0.113.25The default via line is the default gateway, the router every packet uses when no more specific route matches. The second line was added by the kernel when the address was configured; its src field is the address the host prefers as a source on that network. The most useful trick here builds on that: ask the kernel which address it would use for a given destination.
$ ip route get 1.1.1.1
1.1.1.1 via 203.0.113.1 dev eth0 src 203.0.113.25 uid 1000
cacheThat src value is, by definition, the machine's outbound address toward the internet, whatever interfaces, bridges or tunnels exist. For DNS, /etc/resolv.conf is still the place to look, but on systems running systemd-resolved (Ubuntu since 18.04, recent Fedora) it only contains the local stub 127.0.0.53; the real upstream resolvers are shown by resolvectl status, or by the IP4.DNS fields of nmcli device show on NetworkManager hosts.
Scripting: put the IP address in a variable
Interactive output is designed for humans; a script needs one address with nothing around it. These patterns hold up, from the simplest to the most robust:
# One interface, IPv4, prefix length stripped
IP=$(ip -4 -o addr show dev eth0 | awk '{print $4}' | cut -d/ -f1)
# Robust: the source address used to reach the internet
IP=$(ip route get 1.1.1.1 | awk '{for (i=1; i<=NF; i++) if ($i == "src") {print $(i+1); exit}}')
# Same thing with JSON output and jq
IP=$(ip -j route get 1.1.1.1 | jq -r '.[0].prefsrc')
# Public IP, with a timeout so the script never hangs offline
PUBLIC_IP=$(curl -4 -s --max-time 5 https://icanhazip.com)The -o flag makes ip print one address per line, which keeps the awk field positions safe; add head -n 1 if the interface carries several IPv4 addresses. The -j flag switches ip to JSON output, and jq then picks fields by name. Prefer that form in anything that runs on more than one machine: interface names differ from host to host, field names do not.
| Command | What it shows | Best for |
|---|---|---|
ip addr / ip -br -4 addr | Every interface, all addresses, state | Daily use, the full picture |
hostname -I | All addresses on one line | A quick glance |
ip route get 1.1.1.1 | Source address used toward the internet | Scripts, multi-interface hosts |
ifconfig | One IPv4 per interface (deprecated) | Legacy systems, old tutorials |
curl -4 icanhazip.com | Public IPv4 as the internet sees it | NAT, VPN, confirming a VPS address |
What changes on a VPS
On a VPS with a dedicated IPv4, ip -4 addr, hostname -I and curl -4 icanhazip.com should all return the same address, because the public IP is configured straight on the interface with no NAT in between. When they disagree, something is in the path: a provider-side NAT, a forgotten VPN client, or a Docker bridge that took the first slot in hostname -I.
Once the address is confirmed, check two things. First, whether it is actually reachable and on which ports, which is a different question from whether it is configured: check the open ports on your Linux server from the inside with ss -tulpn and from the outside with nmap. Second, reverse DNS. Look up the PTR record for your address:
dig -x 203.0.113.25 +shortA fresh VPS usually answers with a generic provider name, or with nothing at all. If the server sends mail or exposes any public service, set the hostname and the reverse DNS so they match; outbound mail in particular is routinely rejected when the PTR record and the HELO name disagree.
These commands become reflexes fastest on a server whose address is yours alone and does not move. A Linux VPS from rdp.monster comes with a dedicated IPv4, full root access, dedicated CPU and RAM, unlimited (fair-use) bandwidth and no KYC, with crypto accepted, from $8.99/month. The server is online about 10 seconds after payment confirms, so the first ip -br -4 addr you run on it is only a moment away.
Frequently Asked Questions
Why does hostname -I show more than one IP address?
hostname -I prints all addresses on all interfaces except loopback and IPv6 link-local ones, so a machine with Docker, libvirt, a VPN client or a second network card shows several. docker0 contributes 172.17.0.1, virbr0 typically 192.168.122.1, and a dual-stack host adds its global IPv6 address. The order is not guaranteed. When you need the address your traffic really leaves from, run ip route get 1.1.1.1 and read its src field instead.Why does ifconfig say command not found on Ubuntu?
ifconfig command is part of the net-tools package, deprecated in favour of iproute2 and absent from the default install of current Ubuntu, Debian and Fedora/RHEL releases. The replacement is ip addr, which is available everywhere. If a script or an old habit really requires it, install the package with sudo apt install net-tools or sudo dnf install net-tools, keeping in mind that ifconfig shows only one IPv4 per interface and hides secondary addresses added with ip addr add.Why does hostname -i return 127.0.1.1?
hostname -i does not inspect the network at all: it resolves the system's hostname the way any application would, through /etc/hosts and then DNS. The Debian and Ubuntu installers add a line mapping the hostname to 127.0.1.1 so the machine can resolve its own name without a network, and that line is what comes back. Use the capital-I form, hostname -I, which reads the real interface addresses, or ip -4 addr for the full detail.How do I find the IP addresses of other devices on my network?
ip neigh show (or arp -a if net-tools is installed). For a complete picture, ping-sweep the subnet: nmap -sn 192.168.1.0/24 lists every host that answers, with names when reverse DNS provides them. Substitute your own network, which you can read from the scope link route in ip route. On a VPS this is rarely useful, and scanning neighbouring addresses may breach your provider's terms.Adrien Roche, Infrastructure & Hosting Editor
Systems engineer with 10+ years operating Windows Server and Linux fleets. Adrien runs the rdp.monster infrastructure documentation and writes our guides on RDP, VPS hosting, server administration, networking and privacy tooling.




