An incorrectly set hostname is a quiet bug that breaks email delivery, SSL certificate validation, monitoring agent registration, log correlation, and Kerberos. Linux exposes hostname configuration across four files, three commands, and at least two demons that each think they own the value. This guide walks through the layers, the common mistakes, and a reliable verification routine that proves your server identifies itself the same way to every protocol.
The hostname Linux actually uses
Three concepts:
- Static hostname β set in
/etc/hostname, applied at boot. - Transient hostname β set at runtime by DHCP or by
hostnamecommand. - Pretty hostname β human-readable label, set in
/etc/machine-info(rarely matters for servers).
Read all three at once:
hostnamectl status
cat /etc/hostname
hostname
hostname -f # FQDN
hostname -d # domain part only
domainname # NIS domain (legacy, usually not set)
Setting hostname properly
sudo hostnamectl set-hostname web-01.prod.example.com
# or, persist manually:
echo 'web-01.prod.example.com' | sudo tee /etc/hostname
sudo hostname web-01.prod.example.com
The hostname command takes effect immediately and applies to new processes; existing processes (including loggers, syslog, your shell) continue to report the old name until restarted. After hostname change, restart cron, rsyslog, and your monitoring agents.
The /etc/hosts file matters
Network applications resolve their own hostname during init. If hostname -f cannot return a fully-qualified name, Postfix, Apache, OpenLDAP, and most Java runtimes complain or fail. Configure /etc/hosts:
127.0.0.1 localhost
::1 localhost ip6-localhost
192.0.2.10 web-01.prod.example.com web-01
# DO NOT do this on a server:
# 127.0.1.1 web-01.prod.example.com web-01 # Debian default, breaks bind addresses
Debian and Ubuntu add a 127.0.1.1 line during install. Replace it with the actual public IP β many services bind to whatever IP the FQDN resolves to and end up listening on loopback only when the file is left at the default.
FQDN vs short name
The fully-qualified domain name (FQDN) includes the domain: web-01.prod.example.com. The short name is just web-01. Critical: hostname -f must return the FQDN. Test:
hostname -f # web-01.prod.example.com
getent hosts $(hostname) # should resolve to a non-loopback IP
host $(hostname -f) # forward DNS lookup
host $(host $(hostname -f) | awk '/has address/ {print $4}') # reverse DNS lookup
Forward and reverse DNS should agree. Mail servers reject mail from hosts where the reverse PTR does not match the HELO name; this is the #1 cause of "my email goes to spam."
The nsswitch order
Lookup order is configured in /etc/nsswitch.conf:
hosts: files dns # check /etc/hosts first, then DNS
hosts: files mdns4_minimal [NOTFOUND=return] dns # avoid mDNS hangs
Always have files first; it lets you override DNS for testing or rescue without touching the resolver.
DNS pieces a server needs
Forward (A or AAAA) record for the FQDN. Reverse (PTR) record matching the public IP. If the server runs a service that authenticates with TLS, the certificate must include the FQDN as either CN or a Subject Alternative Name.
dig +short A web-01.prod.example.com
dig +short PTR 10.2.0.192.in-addr.arpa
openssl s_client -connect web-01.prod.example.com:443 \
-servername web-01.prod.example.com 2>/dev/null \
| openssl x509 -noout -text | grep -E 'Subject:|DNS:'
NetworkManager and cloud-init surprises
Cloud images set hostname via cloud-init from instance metadata. NetworkManager (or systemd-networkd) may overwrite /etc/resolv.conf on every link change. Pin behavior:
# /etc/cloud/cloud.cfg.d/99-hostname.cfg
preserve_hostname: true
manage_etc_hosts: false
This prevents cloud-init from re-applying its idea of the hostname on every boot.
Verification routine
A 10-line script run after every hostname change:
#!/bin/bash
fqdn=$(hostname -f)
short=$(hostname -s)
ip=$(hostname -I | awk '{print $1}')
echo "FQDN : $fqdn"
echo "Short : $short"
echo "IP : $ip"
echo "Forward DNS : $(dig +short "$fqdn")"
echo "Reverse DNS : $(dig +short -x "$ip")"
echo "Files lookup: $(getent hosts "$fqdn" | awk '{print $1}')"
echo "ssh test : $(ssh -o BatchMode=yes -o ConnectTimeout=3 "$fqdn" hostname 2>&1 | head -1)"
Forward DNS, reverse DNS, and the hostname command should all agree. SSH to the FQDN should succeed and report the same hostname back.
Common pitfalls
- Setting only
hostnameat runtime; reboot reverts because/etc/hostnamestill has the old value. - Leaving the Debian-default
127.0.1.1line β many services bind to localhost only. - Mismatched forward/reverse DNS β silently breaks Kerberos and email reputation.
- Using underscores in hostnames; legal in DNS but rejected by many TLS implementations.
- Pretty hostname looking right in
hostnamectloutput whilehostname -freturnslocalhost.
Hostname configuration is unglamorous and never appears on a roadmap, but every operations issue you have ever debugged that touches DNS, mail, certificates, or distributed systems has a hostname misconfiguration as a likely root cause. Spend ten minutes per host, run the verification script, and move on.