Cambiar el hostname en Linux de forma permanente: hostnamectl, /etc/hosts y cloud-init

Publicado el 19 min de lectura

hostnamectl, /etc/hostname y /etc/hosts en conjunto, el ajuste que impide que cloud-init revierta el nombre y las consecuencias para sudo, el servidor de correo y los certificados.

Un servidor que se llama debian, localhost o vm-01 funciona perfectamente. El problema empieza cuando tienes tres de ellos en marcha a la vez, cuando ya no puedes distinguir unas líneas de log de otras o cuando montas el primer servidor de correo y el servidor remoto comprueba el nombre. Esta guía cambia el hostname de forma que sobreviva al siguiente reinicio, que sudo no se quede colgado en un timeout y que también lo conozcan los servicios que lo leen al arrancar.

Es la profundización del paso 6 de la lista de comprobación para un servidor root nuevo. Allí están los dos comandos que bastan casi siempre. Aquí te contamos qué ocurre por detrás y qué hacer cuando no bastan.

Todos los datos se refieren a Debian 13 (trixie), Debian 12 (bookworm), Ubuntu 24.04 LTS y Ubuntu 22.04 LTS. Los comandos están escritos para ejecutarse como root. Si trabajas como usuario normal, antepón sudo a cada comando.

Un servidor tiene tres nombres, no uno

El motivo más frecuente de un cambio de nombre a medias es que Linux no maneja un hostname, sino tres. Están guardados en sitios distintos y los sobrescriben componentes distintos.

NombreDónde estáCómo consultarloQuién lo establece
estático/etc/hostnamehostnamectl --statichostnamectl set-hostname, cloud-init
transitoriosolo en el kernelhostnamectl --transient, uname -nhostname NAME, cliente DHCP, systemd-networkd
descriptivo/etc/machine-infohostnamectl --prettyhostnamectl set-hostname --pretty

El nombre transitorio lo mantiene el kernel y es el que recibe cualquier programa a través de gethostname(). El nombre estático es la plantilla a partir de la cual se establece durante el arranque. El nombre descriptivo puede llevar espacios y caracteres acentuados, y solo aparece en las interfaces, nunca en la red.

Igual de importante es la segunda distinción: de dónde saca cada comando su respuesta. Supongamos que en /etc/hostname pone srv01 y que en /etc/hosts está la línea 127.0.1.1 srv01.example.com srv01. El resultado es el siguiente.

ComandoSalidaFuente
hostnamesrv01kernel
uname -nsrv01kernel
hostnamectl --staticsrv01/etc/hostname
hostname -ssrv01kernel, recortado hasta el primer punto
hostname -fsrv01.example.comresolución de nombres
hostname -dexample.comresolución de nombres
dnsdomainnameexample.comresolución de nombres
domainname(none)dominio NIS, no DNS

La línea decisiva es hostname -f. El comando no lee /etc/hostname: coge el nombre del kernel y lo pasa por la resolución de nombres. Es decir, el nombre completo sale de /etc/hosts o del DNS, nunca del archivo del hostname. Casi todos los problemas de este artículo se deben a ese malentendido.

Antes del primer cambio: el camino de vuelta

Un cambio de nombre por sí solo no corta tu sesión SSH. Lo peligroso es el paso siguiente: editar /etc/hosts. Si ahí desaparece la línea de localhost, decenas de programas se quedan esperando timeouts, Postfix ya no arranca y sudo tarda segundos en cada llamada. Por eso, deja tres cosas resueltas antes de empezar.

1. Una segunda sesión se queda abierta

Abre una segunda ventana de terminal con una conexión activa y no la cierres hasta que lo hayas comprobado todo. Una sesión ya establecida sobrevive a cualquier cambio en el hostname y en la resolución de nombres. Si la propia conexión todavía no está bien resuelta, te ayuda Conectarte a tu servidor por SSH.

2. La vía que no pasa por SSH

Los servidores root KVM y los servidores dedicados de KernelHost no tienen IPMI ni iDRAC. El acceso que sigue funcionando cuando dentro del sistema invitado ya no funciona nada es la consola VNC del área de cliente. Está enganchada a la capa de virtualización o al propio equipo, con independencia de la resolución de nombres del sistema invitado. Inicia sesión ahí una vez antes de empezar y asegúrate de que conoces la contraseña de root. Una vía de rescate que pruebas por primera vez durante la emergencia no es una vía de rescate.

3. Dos copias y una vuelta atrás

cp -a /etc/hostname /root/hostname.bak
cp -a /etc/hosts /root/hosts.bak
hostnamectl > /root/hostnamectl-antes.txt

Con eso, la vuelta atrás son dos líneas que, si hace falta, tecleas por la consola:

cp -a /root/hosts.bak /etc/hosts
hostnamectl set-hostname "$(cat /root/hostname.bak)"

Inventario en cinco comandos

Mira primero qué está vigente ahora mismo y quién tiene algo que decir al respecto.

hostnamectl
cat /etc/hostname
cat /etc/hosts
grep '^hosts:' /etc/nsswitch.conf
command -v cloud-init >/dev/null && cloud-init status --long || echo "cloud-init no instalado"

Merece la pena mirar con detalle la salida de hostnamectl. Normalmente empieza con Static hostname:. Si además aparece una línea Transient hostname:, el nombre estático y el que está en uso no coinciden, y algo está cambiando el nombre de forma activa: casi siempre cloud-init o un cliente DHCP. Eso hay que desactivarlo primero, porque si no tu cambio habrá desaparecido tras el siguiente reinicio.

La línea hosts: de /etc/nsswitch.conf fija el orden de la resolución de nombres. Las cuatro entradas que aparecen ahí significan:

  • files: se lee /etc/hosts.
  • dns: el resolver consulta los servidores de nombres de /etc/resolv.conf.
  • resolve: la consulta va a systemd-resolved.
  • myhostname: un módulo de systemd que asigna el nombre del propio equipo a las direcciones IP configuradas localmente, incluso sin entrada en /etc/hosts.

El último punto explica más abajo por qué el mismo fallo pasa desapercibido durante años en algunos servidores.

Elegir el nombre: FQDN o nombre corto

Se permiten letras, cifras y el guion. Nada de guion bajo, ni punto al principio o al final, ni guion al comienzo de una etiqueta. Escríbelo en minúsculas: el DNS compara sin distinguir mayúsculas de minúsculas, pero muchos programas lo hacen de forma literal. Una etiqueta (la parte entre dos puntos) puede tener 63 caracteres y el nombre completo en el DNS, 253. El kernel, en cambio, acepta como mucho 64 caracteres para el hostname, así que un FQDN muy largo puede que ni siquiera quepa. Elige el nombre por debajo de un dominio que sea tuyo: .local está reservado para mDNS y las terminaciones inventadas como .lan pueden convertirse en cualquier momento en dominios de primer nivel reales.

Queda la pregunta de qué poner en /etc/hostname. Las dos variantes funcionan y se diferencian en lo que verás después por todas partes.

Variante/etc/hostnamehostnamehostname -f
nombre corto (convención de Debian)srv01srv01srv01.example.com, resuelto vía /etc/hosts o DNS
FQDN (muchas imágenes cloud)srv01.example.comsrv01.example.comsrv01.example.com

En Debian y Ubuntu conviene la primera variante: nombre corto en /etc/hostname y nombre completo como primera entrada en /etc/hosts. Así el prompt y las líneas de log se mantienen cortos, y el FQDN sigue siendo correcto. La segunda variante es igual de limpia mientras la mantengas de forma coherente. El error de verdad es mezclar: un FQDN en /etc/hostname y otro distinto en /etc/hosts.

Lo mejor es que crees ya el registro A (con IPv6, el registro AAAA) para el nombre nuevo. No cuesta nada, hace que hostname -f responda bien incluso sin /etc/hosts y es el requisito para cualquier certificado a ese nombre.

Domar cloud-init antes de tocar nada

En las imágenes con cloud-init, que en Ubuntu son prácticamente todas, el hostname se establece durante el arranque a partir de los metadatos de la instancia. De eso se encargan los módulos set_hostname y update_hostname, además de update_etc_hosts para el archivo /etc/hosts. Los tres se ejecutan pronto, antes incluso de que arranquen tus propios servicios. Dos ajustes lo controlan:

grep -rE '^(preserve_hostname|manage_etc_hosts)' /etc/cloud/cloud.cfg /etc/cloud/cloud.cfg.d/ 2>/dev/null

En las imágenes de Ubuntu Server, /etc/cloud/cloud.cfg contiene la línea preserve_hostname: false, así que cloud-init tiene permiso para tocar el nombre. El ajuste contrario no va en ese archivo, porque una actualización de paquetes lo reemplaza, sino en /etc/cloud/cloud.cfg.d/. Los archivos de ahí se leen por orden alfabético y gana el último, de ahí el 99:

mkdir -p /etc/cloud/cloud.cfg.d
printf 'preserve_hostname: true\n' > /etc/cloud/cloud.cfg.d/99_hostname.cfg

El segundo ajuste afecta a /etc/hosts. Se pasa por alto con frecuencia, aunque hace más daño.

Valor de manage_etc_hostsEfecto sobre /etc/hosts
sin definir o falsecloud-init no toca el archivo
localhostcloud-init se asegura en cada arranque de que el propio nombre resuelva y deja intacto el resto del archivo
truecloud-init regenera el archivo en cada arranque a partir de la plantilla de /etc/cloud/templates/, y tus líneas propias desaparecen

Si ahí pone true y necesitas entradas propias, cambia el valor a localhost o mantén en su lugar la plantilla (en Debian y Ubuntu, hosts.debian.tmpl). Editar a mano un archivo que se sobrescribe en cada arranque produce justo el tipo de fallo del que te das cuenta semanas después.

Lo último que ha establecido cloud-init queda anotado en /var/lib/cloud/data/. Ese estado lo borra cloud-init clean. No lo hagas en un servidor ya configurado: en el siguiente arranque se vuelven a ejecutar todos los módulos como si la máquina fuera nueva.

El segundo que sobrescribe: DHCP

Si el servidor obtiene su dirección por DHCP, el cliente puede adoptar el hostname transitorio que viene en la respuesta (opción 12). El nombre estático queda intacto, lo que complica el diagnóstico: hostnamectl --static muestra tu nombre y hostname, otro distinto. Con netplan lo desactivas así:

network:
  version: 2
  ethernets:
    eth0:
      dhcp4: true
      dhcp4-overrides:
        use-hostname: false

Aplícalo con netplan try en vez de netplan apply: try revierte el cambio por sí solo a los 120 segundos si no confirmas. Si configuras systemd-networkd directamente, el ajuste se llama UseHostname=no en la sección [DHCPv4].

Establecer el hostname

hostnamectl set-hostname srv01

Sin más parámetros, hostnamectl establece a la vez el nombre estático y el transitorio. Que es justo lo que quieres. Con --static solo cambias /etc/hostname y, si hay un nombre transitorio activo, la máquina seguiría funcionando con el antiguo hasta el reinicio. Las versiones más recientes de systemd conocen además la forma corta hostnamectl hostname srv01; set-hostname funciona en los cuatro sistemas.

Comprobación: los dos nombres tienen que coincidir y el archivo debe llevar el contenido nuevo.

hostnamectl --static
hostnamectl --transient
cat /etc/hostname

Dos apuntes al margen. Primero, hostname srv01 sin el ctl cambia solo el nombre transitorio y desaparece tras el reinicio. Segundo, la shell que tienes abierta seguirá mostrando el nombre antiguo en el prompt, porque bash lee el hostname una sola vez al iniciar la sesión. Eso no es un fracaso, es una sesión antigua. Vuelve a iniciar sesión.

De forma opcional puedes guardar un nombre descriptivo, que aparece en las interfaces y puede llevar espacios:

hostnamectl set-hostname --pretty "Servidor web Frankfurt"
cat /etc/machine-info

Escribir bien /etc/hosts

hostnamectl no toca /etc/hosts. Ese archivo sigue siendo cosa tuya, y es el motivo por el que tantas veces un cambio de nombre se queda a medias.

Una línea se compone de una dirección IP, el nombre canónico y tantos alias como quieras. El primer nombre detrás de la dirección es el canónico, y es justo el que devuelve hostname -f. Por eso el nombre completo va delante y el corto detrás, nunca al revés.

127.0.0.1       localhost
127.0.1.1       srv01.example.com srv01

::1             localhost ip6-localhost ip6-loopback
ff02::1         ip6-allnodes
ff02::2         ip6-allrouters

Por qué 127.0.1.1 y no 127.0.0.1: Debian y Ubuntu separan a propósito el nombre del propio equipo de localhost. Si añades el nombre del servidor como alias a la línea de localhost, el nombre canónico de esa línea sigue siendo localhost y hostname -f responde localhost. Los programas que deducen de ahí su propio nombre acaban escribiendo localhost en los logs y en las cabeceras de correo.

Si falta la entrada, la añades; si la línea ya existe, la modificas:

grep -n '^127\.0\.1\.1' /etc/hosts
printf '127.0.1.1\tsrv01.example.com\tsrv01\n' >> /etc/hosts

Si el primer comando ya devuelve una línea, edita esa en vez de añadir una segunda. Con dos líneas para la misma dirección gana la primera, y acabarías modificando una línea que ya no lee nadie.

Comprobación:

getent hosts srv01
getent hosts srv01.example.com
hostname -f
hostname -s

Las dos llamadas a getent tienen que devolver una línea cada una, hostname -f el nombre completo y hostname -s el corto. Si no vuelve nada, la entrada no surte efecto, por ejemplo porque la línea lleva delante un carácter de comentario.

Queda una decisión: 127.0.1.1 o la dirección pública del servidor. Hay software que se enlaza a la dirección a la que resuelve su propio nombre, o que la publica en la lista de miembros de un clúster. En ese caso el FQDN va sobre la dirección pública. Con dirección fija esa es la variante más limpia; con dirección cambiante lo es 127.0.1.1, porque funciona incluso sin conexión de red.

Por qué una entrada que falta ralentiza sudo

sudo averigua en cada llamada el nombre del propio equipo y lo manda resolver. Lo necesita para la línea de log y para compararlo con las especificaciones de host de /etc/sudoers.

La resolución sigue el orden de la línea hosts: de /etc/nsswitch.conf. Si el nombre está en /etc/hosts, el asunto se zanja con un acceso a un archivo, es decir, en menos de un milisegundo. Si no está ahí, la consulta pasa a la siguiente entrada, normalmente dns, y el resolver pregunta a los servidores de nombres de /etc/resolv.conf por un nombre que en el DNS no existe. Los valores por defecto de glibc son cinco segundos de timeout y dos intentos por servidor de nombres. Si no responde nadie, eso se va sumando, y además en cada llamada individual.

Y encima se añade otro factor: un nombre corto no contiene ningún punto y queda por debajo del valor por defecto ndots:1. Por eso el resolver añade primero cada dominio de búsqueda de /etc/resolv.conf y solo después consulta el nombre a secas. Dos dominios de búsqueda significan tres rondas de consultas en lugar de una.

Eso se hace visible en este aviso, que precede a cada llamada:

sudo: unable to resolve host srv01: Name or service not known

Medir en lugar de estimar:

time getent hosts "$(hostname)"
time sudo -n true

Las dos cosas deberían quedar muy por debajo de una décima de segundo. Todo lo que pase de ahí es tiempo de espera a un servidor de nombres.

Y ahora el motivo por el que el fallo no se nota en todas partes: si en la línea hosts: está la entrada myhostname, ese módulo responde por sí mismo a la consulta del propio nombre, sin DNS y sin /etc/hosts. Ahí no aparece el aviso, aunque el archivo esté incompleto. En cuanto la misma configuración se traslada a un sistema sin esa entrada, el fallo vuelve.

Un segundo problema, menos habitual, afecta a los permisos: en /etc/sudoers, cada regla puede estar limitada a determinados nombres de equipo. Las reglas que traen Debian y Ubuntu usan ALL y no son problemáticas. Las reglas propias con un nombre de equipo, en cambio, dejan de surtir efecto, y el usuario afectado se queda después sin poder hacer nada. Compruébalo antes:

grep -rhvE '^[[:space:]]*(#|$)' /etc/sudoers /etc/sudoers.d/

Servicios que leen el nombre al arrancar

Muchos programas consultan el hostname exactamente una vez, al arrancar, y después siguen trabajando con el nombre antiguo. Eso explica buena parte de la confusión que viene tras un cambio de nombre.

  • La shell abierta. El prompt muestra el nombre antiguo. Abre una sesión nueva y listo.
  • rsyslog, allí donde esté instalado. Basta con un systemctl restart rsyslog. Debian 12 y 13 no traen rsyslog en las instalaciones mínimas: ahí escribe journald.
  • Las entradas de log ya escritas conservan el nombre antiguo, y así debe ser. Si en cambio el nombre antiguo aparece en entradas nuevas, reinicia el servicio que las escribe.
  • MariaDB y MySQL derivan del hostname los nombres de archivo por defecto, como el log de errores y el binlog, siempre que las rutas no estén indicadas expresamente en la configuración.
  • Aplicaciones Java. InetAddress.getLocalHost() lanza una java.net.UnknownHostException en cuanto el propio nombre no resuelve. Afecta tanto a servidores de aplicaciones como a servidores de juegos.
  • Los agentes de monitorización llevan el nombre a menudo en su propio archivo de configuración. Si no, tras el cambio de nombre el mismo servidor aparece dos veces.
systemctl list-units --type=service --state=running

Si de todas formas tienes por delante una ventana de mantenimiento, un reinicio es la solución más completa. Cómo registrar tus propios programas de forma limpia como unidad, para que sobrevivan a un reinicio, lo tienes en Crear un servicio systemd.

Servidor de correo: el nombre que ven los demás

En el envío de correo, el hostname deja de ser cosmética. El servidor remoto lo ve en el EHLO y lo comprueba. Tres cosas tienen que encajar:

  1. El nombre con el que se presenta tu servidor de correo (en Postfix, myhostname).
  2. El registro PTR de tu dirección IP, es decir, la resolución inversa.
  3. Un registro A (con IPv6, un registro AAAA) para justo ese nombre, que apunte otra vez a la misma dirección.

Si la cadena no cierra, muchos destinatarios degradan el mensaje o lo rechazan. Comprobación sin paquetes adicionales:

hostname -f
getent hosts 203.0.113.10
getent hosts srv01.example.com

Con dig, del paquete bind9-dnsutils, es más preciso:

apt install -y bind9-dnsutils
dig +short -x 203.0.113.10
dig +short srv01.example.com A

El registro PTR no pertenece al servidor. Va ligado a la dirección IP y lo gestiona el operador de la red, en KernelHost desde el área de cliente. Ninguna llamada a hostnamectl cambia eso, y es justo aquí donde los cambios de nombre salen mal en los servidores de correo.

Postfix no adopta el cambio de nombre por sí solo. En Debian y Ubuntu, el paquete escribe durante la instalación un valor fijo en /etc/postfix/main.cf, y junto a él está /etc/mailname con el nombre que Postfix usa como dominio del remitente para el correo local. Los dos se quedan sin cambios:

postconf myhostname mydomain myorigin
cat /etc/mailname

Ajustar y reiniciar, teniendo en cuenta que /etc/mailname es una decisión aparte y no lleva forzosamente el mismo valor que myhostname:

postconf -e "myhostname = srv01.example.com"
postfix check
systemctl restart postfix

SPF, DKIM y DMARC, en cambio, dependen del dominio del remitente y no del hostname. Un cambio de nombre no arregla, por tanto, ningún problema de entrega cuya causa esté ahí.

Certificados

El nombre del sistema no aparece en ningún certificado, porque un certificado cubre los nombres DNS que figuraban en la solicitud. Aun así, un cambio de nombre repercute en tres sitios.

Primero, en la solicitud. Si pides un certificado a nombre del propio servidor, por ejemplo para el servidor de correo, el nombre tiene que estar en el DNS antes de que la autoridad de certificación lo compruebe. Si no, la ejecución termina con un mensaje del tipo DNS problem: NXDOMAIN looking up A for srv01.example.com. El registro A va antes de la solicitud, no después.

Segundo, en los certificados existentes. Siguen a nombre del host antiguo y se siguen renovando hasta que los elimines:

certbot certificates
certbot delete --cert-name antiguo.example.com

Bórralos solo cuando ya ningún servicio apunte a esa ruta; si no, el servidor web dejará de arrancar en la siguiente recarga.

Tercero, en el servidor de correo. Si Postfix se presenta con el nombre nuevo pero muestra un certificado para el antiguo, fallan los servidores remotos que comprueban el nombre con rigor. El certificado y myhostname tienen que ir al mismo nombre.

No hay ninguna relación entre el nombre del sistema y server_name en nginx. nginx decide en función de la cabecera Host de la petición, no del nombre del equipo. Si tras un cambio de nombre te sirve la página equivocada, busca en la configuración del servidor, no en el hostname. Las bases están en Instalar nginx en Debian y Ubuntu.

Errores frecuentes y soluciones

sudo: unable to resolve host srv01: Name or service not known
El nombre del equipo no está en /etc/hosts y el DNS no lo conoce. Añade la línea 127.0.1.1 srv01.example.com srv01. Mientras falte, cada llamada espera a que venza el timeout del resolver.

hostname: Name or service not known
La respuesta de hostname -f cuando el nombre del kernel no se puede resolver en ninguna parte. Misma causa, misma solución. Después, comprueba con getent hosts "$(hostname)" si de verdad vuelve algo.

Could not set property: Access denied
Se llamó a hostnamectl sin permisos de root, o la llamada se ejecutó dentro de un contenedor que no puede cambiar el nombre del kernel. En un servidor propio, la solución es sudo. En un contenedor sin privilegios, el nombre se establece en la configuración de ese contenedor, no dentro de él.

fatal: unable to use my own hostname
Sale del log de Postfix. El valor de myhostname no resuelve. Añade la entrada en /etc/hosts y después ejecuta systemctl restart postfix.

504 5.5.2 <srv01>: Helo command rejected: need fully-qualified hostname
Tu servidor de correo se presenta con el nombre corto y el servidor remoto exige un nombre completo. Pon myhostname al FQDN y reinicia Postfix.

450 4.7.1 Client host rejected: cannot find your reverse hostname
Para tu dirección IP no existe ningún registro PTR, o apunta al vacío. Eso no se arregla en el servidor, sino solo en el operador de la red IP.

java.net.UnknownHostException: srv01
Una aplicación Java ha intentado resolver su propio nombre y no lo ha conseguido. Otra vez /etc/hosts. Después de añadir la entrada hay que reiniciar la aplicación.

DNS problem: NXDOMAIN looking up A for srv01.example.com
El nombre nuevo todavía no existe en el DNS. Crea el registro A, espera a que se propague y repite la solicitud.

Tras el reinicio, el nombre vuelve a ser el antiguo.
Comprueba en este orden: si preserve_hostname: true está puesto en /etc/cloud/cloud.cfg.d/, si el cliente DHCP ya no entrega ningún nombre y si /etc/hostname contiene realmente el nombre nuevo. Si hostnamectl muestra tras el arranque una línea Transient hostname:, todavía actúa alguna de esas fuentes.

/etc/hosts vuelve a aparecer vaciado tras cada reinicio.
manage_etc_hosts: true está puesto y cloud-init regenera el archivo a partir de la plantilla. Cámbialo a localhost o mantén la plantilla.

Diferencias entre distribuciones

Sistemacloud-init de fábricarsyslogParticularidad
Debian 13 (trixie)solo en las imágenes cloudfalta en las instalaciones mínimaslogs en el journal en vez de en /var/log/syslog
Debian 12 (bookworm)solo en las imágenes cloudsegún la variante de instalaciónigual que Debian 13
Ubuntu 24.04 LTSsí, preserve_hostname: falsepresentesystemd-resolved activo, resolve está en la línea hosts:
Ubuntu 22.04 LTSsí, preserve_hostname: falsepresenteigual que Ubuntu 24.04

Igual en los cuatro sistemas: hostnamectl nunca modifica /etc/hosts, y ninguna herramienta del sistema operativo crea registros DNS o PTR. Esos dos pasos siguen siendo trabajo manual.

La comprobación final

Un comando sin mensaje de error no demuestra nada. La única prueba sólida es el reinicio y, después, estas cinco líneas:

hostnamectl --static
hostname -f
getent hosts "$(hostname)"
time sudo -n true
grep -c '^127\.0\.1\.1' /etc/hosts

Lo que se espera: el nombre corto nuevo, el nombre completo nuevo, una línea de /etc/hosts, un tiempo de ejecución muy por debajo de una décima de segundo y exactamente una línea para 127.0.1.1. Solo cuando las cinco cuadran, el cambio de nombre está hecho, y solo entonces puedes cerrar la segunda ventana de terminal.

Preguntas frecuentes

¿Por qué después de reiniciar mi hostname vuelve a ser el antiguo?
Porque durante el arranque lo establece otra cosa, casi siempre cloud-init o el cliente DHCP. Crea el archivo /etc/cloud/cloud.cfg.d/99_hostname.cfg con la línea preserve_hostname: true y cloud-init dejará el nombre en paz. Para el cliente DHCP, con netplan sirve el ajuste use-hostname: false dentro de dhcp4-overrides, y con systemd-networkd, UseHostname=no en la sección [DHCPv4]. Para saber si alguien interviene, mira la salida de hostnamectl: si junto a Static hostname aparece además una línea Transient hostname, el nombre guardado y el que está en uso no coinciden.
¿Por qué sudo avisa de "unable to resolve host" y de repente tarda segundos?
sudo manda resolver el nombre del propio equipo en cada llamada, para la línea de log y para compararlo con las especificaciones de host de /etc/sudoers. Si el nombre no está en /etc/hosts, la consulta sigue hasta el resolver de DNS, que con los valores por defecto de glibc espera cinco segundos por intento y hace dos intentos por servidor de nombres. Además, un nombre corto sin punto queda por debajo de ndots:1, así que primero se le añade cada dominio de búsqueda. La línea 127.0.1.1 srv01.example.com srv01 en /etc/hosts lo corta de inmediato.
¿En /etc/hostname va el nombre corto o el nombre completo?
Las dos opciones funcionan. En Debian y Ubuntu la convención es el nombre corto, y entonces el nombre completo va como primera entrada en la línea correspondiente de /etc/hosts. Así el prompt y las líneas de log se mantienen cortos, y hostname -f sigue devolviendo el FQDN. Muchas imágenes cloud escriben en su lugar el FQDN en /etc/hostname, que es igual de limpio. El error de verdad es mezclar: un nombre completo en /etc/hostname y otro distinto en /etc/hosts.
¿Por qué 127.0.1.1 en /etc/hosts y no 127.0.0.1?
Debian y Ubuntu separan a propósito el nombre del propio equipo de localhost. El primer nombre detrás de una dirección es el canónico, y es justo el que devuelve hostname -f. Si añades el nombre del servidor como alias a la línea de localhost, localhost sigue siendo el nombre canónico y hostname -f responde localhost. Los programas que deducen de ahí su propio nombre lo acaban escribiendo en los logs y en las cabeceras de correo. Una línea propia con 127.0.1.1 lo evita. Si tienes una dirección pública fija, puedes poner el nombre completo directamente sobre esa dirección.
¿hostnamectl modifica también /etc/hosts?
No. hostnamectl escribe /etc/hostname, establece el nombre en uso del kernel y, si se lo pides, mantiene /etc/machine-info. El archivo /etc/hosts no lo toca nunca. Lo único que lo cambia de forma automática es cloud-init con el ajuste manage_etc_hosts: el valor true regenera el archivo en cada arranque a partir de una plantilla, el valor localhost solo se asegura de que el propio nombre resuelva, y sin ese ajuste el archivo queda intacto.
¿Basta el comando hostname para un cambio permanente?
No. hostname srv01 establece solo el nombre transitorio en el kernel, y ese desaparece tras el siguiente reinicio, porque entonces se vuelve a cargar desde /etc/hostname. Para un cambio permanente usa hostnamectl set-hostname srv01, que establece a la vez el nombre estático y el transitorio. Las versiones más recientes de systemd conocen además la forma corta hostnamectl hostname srv01.
¿Qué tengo que ajustar además para mi servidor de correo?
Tres cosas tienen que encajar: el nombre del EHLO (en Postfix, myhostname), el registro PTR de tu dirección IP y un registro A o AAAA para justo ese nombre, que apunte otra vez a la misma dirección. Postfix no adopta el cambio de nombre por sí solo, porque en Debian y Ubuntu el paquete escribe un valor fijo en /etc/postfix/main.cf y junto a él está /etc/mailname. El PTR no se establece en el servidor, sino en el operador de la red IP, en KernelHost desde el área de cliente. Si falta, los destinatarios estrictos rechazan con 450 4.7.1 Client host rejected: cannot find your reverse hostname.

Hostname hostnamectl cloud-init Linux Debian Ubuntu DNS Servidor root