Alterar o hostname no Linux de forma permanente: hostnamectl, /etc/hosts e cloud-init

Publicado a 19 min de leitura

hostnamectl, /etc/hostname e /etc/hosts em conjunto, o parâmetro que impede o cloud-init de repor o nome antigo e as consequências para o sudo, o servidor de e-mail e os certificados.

Um servidor chamado debian, localhost ou vm-01 funciona perfeitamente. A coisa só se torna incómoda quando três deles correm ao mesmo tempo, quando já não se conseguem distinguir as linhas de log ou quando entra em cena o primeiro servidor de e-mail e o lado de lá verifica o nome. Este guia altera o hostname de forma a que sobreviva ao reinício seguinte, a que o sudo não fique preso num timeout e a que também o conheçam os serviços que o leem no arranque.

É o aprofundamento do passo 6 da checklist para um novo servidor root. Lá estão os dois comandos que, na maioria dos casos, chegam. Aqui fica o que acontece por trás deles e o que fazer quando não chegam.

Todas as indicações se referem ao Debian 13 (trixie), Debian 12 (bookworm), Ubuntu 24.04 LTS e Ubuntu 22.04 LTS. Os comandos estão escritos para serem executados como root. Enquanto utilizador normal, anteponha sudo a cada comando.

Um servidor tem três nomes, não um

A causa mais frequente de uma mudança de nome que só resulta a meias é o Linux não conhecer um hostname, mas sim três. Ficam guardados em sítios diferentes e são sobrescritos por mecanismos diferentes.

NomeOnde ficaComo se lêQuem o define
estático/etc/hostnamehostnamectl --statichostnamectl set-hostname, cloud-init
transitórioapenas no kernelhostnamectl --transient, uname -nhostname NAME, cliente DHCP, systemd-networkd
descritivo/etc/machine-infohostnamectl --prettyhostnamectl set-hostname --pretty

O nome transitório é mantido pelo kernel e é esse que qualquer programa recebe através de gethostname(). O nome estático é o modelo a partir do qual ele é definido no arranque. O nome descritivo pode conter espaços e caracteres acentuados e aparece apenas em interfaces, nunca na rede.

Igualmente importante é a segunda distinção: de onde é que cada comando tira a sua resposta. Suponha que /etc/hostname contém srv01 e que /etc/hosts tem a linha 127.0.1.1 srv01.example.com srv01. O quadro que daí resulta é este.

ComandoSaídaOrigem
hostnamesrv01kernel
uname -nsrv01kernel
hostnamectl --staticsrv01/etc/hostname
hostname -ssrv01kernel, truncado no primeiro ponto
hostname -fsrv01.example.comresolução de nomes
hostname -dexample.comresolução de nomes
dnsdomainnameexample.comresolução de nomes
domainname(none)domínio NIS, não DNS

A linha decisiva é hostname -f. O comando não/etc/hostname: pega no nome do kernel e passa-o pela resolução de nomes. O nome completo vem, portanto, de /etc/hosts ou do DNS, nunca do ficheiro do hostname. Quase todos os problemas deste artigo remontam a este mal-entendido.

Antes da primeira alteração: o caminho de volta

Mudar o nome não corta, por si só, a sua sessão SSH. Perigoso é o passo seguinte: editar o /etc/hosts. Se aí desaparecer a linha do localhost, dezenas de programas ficam à espera de timeouts, o Postfix deixa de arrancar e o sudo passa a demorar segundos em cada invocação. Por isso, esclareça três coisas antes.

1. Uma segunda sessão fica aberta

Abra uma segunda janela de terminal com uma ligação ativa e não a feche enquanto não estiver tudo verificado. Uma sessão já estabelecida sobrevive a qualquer alteração ao hostname e à resolução de nomes. Se o próprio estabelecimento da ligação ainda não estiver bem afinado, consulte Ligar ao servidor por SSH.

2. O caminho que não passa pelo SSH

Os servidores root KVM e os servidores dedicados da KernelHost não têm IPMI nem iDRAC. O acesso que continua a funcionar mesmo quando já nada funciona dentro do sistema convidado é a consola VNC na área de cliente. Está ligada à camada de virtualização, ou à própria ligação física, independentemente da resolução de nomes no sistema convidado. Inicie sessão aí uma vez antes e certifique-se de que conhece a palavra-passe de root. Uma via de salvamento que só se experimenta pela primeira vez em plena emergência não serve de nada.

3. Duas cópias e uma reversão

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

Com isto, o caminho de volta são duas linhas que, em caso de necessidade, escreve na consola:

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

Levantamento em cinco comandos

Comece por ver o que está em vigor neste momento e quem tem uma palavra a dizer no assunto.

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 não instalado"

Vale a pena olhar com atenção para a saída do hostnamectl. Normalmente começa com Static hostname:. Se surgir ainda uma linha Transient hostname:, o nome estático e o nome em execução divergem e há algo a impor o nome de forma ativa: quase sempre o cloud-init ou um cliente DHCP. Isso tem de ser travado primeiro, caso contrário a sua alteração desaparece no reinício seguinte.

A linha hosts: de /etc/nsswitch.conf define a ordem da resolução de nomes. As quatro entradas que aí aparecem significam o seguinte:

  • files: é lido o ficheiro /etc/hosts.
  • dns: o resolver interroga os nameservers indicados em /etc/resolv.conf.
  • resolve: o pedido segue para o systemd-resolved.
  • myhostname: um módulo do systemd que faz corresponder o nome da própria máquina aos endereços IP configurados localmente, mesmo sem entrada em /etc/hosts.

O último ponto explica, mais abaixo, porque é que o mesmo erro passa despercebido durante anos em alguns servidores.

Escolher o nome: FQDN ou nome curto

São permitidas letras, algarismos e o hífen. Nada de underscore, nada de ponto no início ou no fim, nada de hífen a abrir um label. Escreva em minúsculas: o DNS compara sem distinguir maiúsculas de minúsculas, mas muitos programas comparam à letra. Um label (cada troço do nome delimitado por pontos) pode ter 63 caracteres e o nome completo no DNS pode ter 253. O kernel, porém, aceita no máximo 64 caracteres para o hostname, pelo que um FQDN muito longo pode nem sequer caber. Escolha o nome dentro de um domínio que lhe pertença: .local está reservado para mDNS e extensões inventadas como .lan podem tornar-se domínios de topo reais a qualquer momento.

Fica a questão do que escrever em /etc/hostname. As duas variantes funcionam e distinguem-se apenas naquilo que lhe passa a ser mostrado por todo o lado.

Variante/etc/hostnamehostnamehostname -f
Nome curto (convenção do Debian)srv01srv01srv01.example.com, resolvido através de /etc/hosts ou do DNS
FQDN (muitas imagens de cloud)srv01.example.comsrv01.example.comsrv01.example.com

No Debian e no Ubuntu recomendamos a primeira variante: nome curto em /etc/hostname e nome completo como primeira entrada em /etc/hosts. Assim, o prompt e as linhas de log ficam curtos e o FQDN continua correto. A segunda variante é igualmente limpa, desde que seja mantida com coerência. O verdadeiro erro é a mistura: um FQDN em /etc/hostname e outro diferente em /etc/hosts.

O melhor é criar já o registo A (com IPv6, o registo AAAA) para o novo nome. Não custa nada, faz com que hostname -f responda corretamente mesmo sem /etc/hosts e é o requisito para qualquer certificado emitido para esse nome.

Domar o cloud-init antes de definir seja o que for

Nas imagens com cloud-init, e no Ubuntu são praticamente todas, o hostname é definido no arranque a partir dos metadados da instância. Os responsáveis são os módulos set_hostname e update_hostname, além de update_etc_hosts para o ficheiro /etc/hosts. Os três correm cedo, ainda antes de arrancarem os seus próprios serviços. Dois parâmetros controlam isto:

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

Nas imagens de servidor do Ubuntu, o ficheiro /etc/cloud/cloud.cfg traz a linha preserve_hostname: false, ou seja, o cloud-init pode mexer no nome. O parâmetro contrário não pertence a esse ficheiro, porque uma atualização de pacote o substitui, mas sim a /etc/cloud/cloud.cfg.d/. Os ficheiros dessa pasta são lidos por ordem alfabética e o último ganha, daí o 99:

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

O segundo parâmetro diz respeito ao /etc/hosts. É facilmente esquecido, apesar de causar mais estragos.

Valor de manage_etc_hostsEfeito no /etc/hosts
não definido ou falseo cloud-init não toca no ficheiro
localhostem cada arranque, o cloud-init garante que o próprio nome resolve e deixa o resto do ficheiro intacto
trueem cada arranque, o cloud-init recria o ficheiro a partir do modelo em /etc/cloud/templates/, e as linhas próprias desaparecem

Se aí estiver true e precisar de entradas próprias, defina o valor como localhost ou passe antes a manter o modelo (no Debian e no Ubuntu, hosts.debian.tmpl). Editar à mão um ficheiro que é sobrescrito em cada arranque produz exatamente o tipo de erro que só se nota semanas depois.

O cloud-init guarda em /var/lib/cloud/data/ aquilo que definiu da última vez. Esse estado é apagado por cloud-init clean. Não faça isso num servidor já configurado: no arranque seguinte, todos os módulos voltam a correr como se a máquina fosse nova.

O segundo a reescrever: DHCP

Se o servidor obtém o endereço por DHCP, o cliente pode assumir o hostname transitório a partir da resposta (opção 12). O nome estático fica intacto, o que dificulta o diagnóstico: hostnamectl --static mostra o seu nome e hostname mostra outro. No netplan, desliga-se assim:

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

Ative com netplan try em vez de netplan apply: o try reverte a alteração sozinho ao fim de 120 segundos se não houver confirmação. Com o systemd-networkd configurado diretamente, a definição chama-se UseHostname=no na secção [DHCPv4].

Definir o hostname

hostnamectl set-hostname srv01

Sem parâmetros adicionais, o hostnamectl define em conjunto o nome estático e o transitório. É exatamente isso que se pretende. Com --static altera apenas o /etc/hostname e, havendo um nome transitório ativo, a máquina continuaria a correr com o antigo até ao reinício. As versões mais recentes do systemd conhecem ainda a forma abreviada hostnamectl hostname srv01; o set-hostname funciona nos quatro sistemas.

Verificação: os dois nomes têm de coincidir e o ficheiro tem de conter o novo conteúdo.

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

Duas notas à margem. Primeiro, o hostname srv01 sem o ctl altera apenas o nome transitório e desaparece com o reinício. Segundo, a shell em execução continua a mostrar o nome antigo no prompt, porque o bash lê o hostname uma única vez ao iniciar a sessão. Isso não é uma falha, é apenas uma sessão antiga. Volte a iniciar sessão.

Opcionalmente, pode registar um nome descritivo, que aparece nas interfaces e pode conter espaços:

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

Escrever o /etc/hosts corretamente

O hostnamectl não toca no /etc/hosts. Esse ficheiro continua a ser tarefa sua e é a razão pela qual uma mudança de nome tantas vezes só resulta a meias.

Uma linha é composta por um endereço IP, o nome canónico e um número qualquer de aliases. O primeiro nome a seguir ao endereço é o canónico, e é precisamente esse que o hostname -f devolve. Por isso, o nome completo vai à frente e o nome curto atrás, nunca ao contrário.

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

Porquê 127.0.1.1 e não 127.0.0.1: o Debian e o Ubuntu separam deliberadamente o nome da própria máquina do localhost. Se acrescentar o nome do servidor como alias à linha do localhost, o nome canónico dessa linha continua a ser localhost e o hostname -f responde localhost. Os programas que daí derivam o seu próprio nome passam a escrever localhost nos logs e nos cabeçalhos de e-mail.

Uma entrada em falta acrescenta-se; uma linha já existente altera-se:

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

Se o primeiro comando já devolver uma linha, edite essa linha em vez de acrescentar uma segunda. Havendo duas linhas para o mesmo endereço, ganha a primeira, e passaria a alterar uma linha que já ninguém lê.

Verificação:

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

As duas invocações de getent têm de devolver uma linha cada, o hostname -f o nome completo e o hostname -s o nome curto. Se não vier nada, a entrada não está a produzir efeito, por exemplo porque a linha começa por um sinal de comentário.

Falta uma decisão: 127.0.1.1 ou o endereço público do servidor. Há software que se liga ao endereço para o qual o seu próprio nome resolve, ou que o inscreve na lista de membros de um cluster. Nesse caso, o FQDN pertence ao endereço público. Com um endereço fixo, essa é a variante mais limpa; com um endereço variável, é o 127.0.1.1, porque funciona mesmo sem ligação à rede.

Porque é que uma entrada em falta torna o sudo lento

Em cada invocação, o sudo apura o nome da própria máquina e manda-o resolver. Precisa dele para a linha de log e para a comparação com as indicações de máquina em /etc/sudoers.

A resolução segue a linha hosts: de /etc/nsswitch.conf. Se o nome estiver em /etc/hosts, o assunto fica arrumado com um acesso ao ficheiro, ou seja, em menos de um milissegundo. Se não estiver, o pedido passa para a entrada seguinte, em regra dns, e o resolver pergunta aos nameservers de /etc/resolv.conf por um nome que não existe no DNS. As predefinições da glibc são cinco segundos de timeout e duas tentativas por nameserver. Se ninguém responder, isso vai somando, e acontece em cada invocação.

A isto acresce um agravante: um nome curto não contém ponto nenhum e fica, por isso, abaixo da predefinição ndots:1. O resolver começa então por acrescentar cada domínio de pesquisa de /etc/resolv.conf e só depois consulta o nome em si. Dois domínios de pesquisa significam três rondas de consultas em vez de uma.

Isto torna-se visível neste aviso, que antecede cada invocação:

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

Medir em vez de adivinhar:

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

Ambos devem ficar bastante abaixo de um décimo de segundo. Tudo o que passe disso é tempo de espera por um nameserver.

E agora a razão pela qual o erro não salta à vista em todo o lado: se a linha hosts: contiver a entrada myhostname, é esse módulo que responde ele próprio ao pedido pelo nome da máquina, sem DNS e sem /etc/hosts. Aí o aviso não aparece, apesar de o ficheiro estar incompleto. Assim que a mesma configuração passa para um sistema sem essa entrada, o erro volta.

Um segundo problema, mais raro, tem que ver com a atribuição de permissões: em /etc/sudoers, cada regra pode estar limitada a determinados nomes de máquina. As regras que vêm com o Debian e o Ubuntu usam ALL e não são críticas. Já as regras próprias com um nome de máquina perdem o efeito, e o utilizador afetado deixa de poder fazer o que quer que seja. Convém verificar antes:

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

Serviços que leem o nome no arranque

Muitos programas consultam o hostname exatamente uma vez, no arranque, e continuam depois a trabalhar com o nome antigo. Isso explica boa parte da confusão que se segue a uma mudança de nome.

  • A shell em execução. O prompt mostra o nome antigo. Abrir uma sessão nova e está resolvido.
  • rsyslog, onde estiver instalado. Basta um systemctl restart rsyslog. O Debian 12 e o Debian 13 não trazem rsyslog em instalações mínimas; aí quem escreve é o journald.
  • As entradas de log já escritas mantêm o nome antigo, e é assim que deve ser. Se, pelo contrário, o nome antigo aparecer em entradas novas, reinicie o serviço que as escreve.
  • O MariaDB e o MySQL derivam do hostname os nomes de ficheiro predefinidos, como o log de erros e o binlog, desde que os caminhos não estejam indicados explicitamente na configuração.
  • Aplicações Java. InetAddress.getLocalHost() lança uma java.net.UnknownHostException assim que o próprio nome deixa de resolver. Isto afeta tanto servidores aplicacionais como gameservers.
  • Os agentes de monitorização guardam muitas vezes o nome no seu próprio ficheiro de configuração. Caso contrário, o mesmo servidor aparece duas vezes depois da mudança de nome.
systemctl list-units --type=service --state=running

Se de qualquer forma houver uma janela de manutenção prevista, o reinício é a solução mais completa. Como registar programas próprios de forma limpa como unit, para que sobrevivam a um reinício, está explicado em Criar um serviço systemd.

Servidor de e-mail: o nome que os outros veem

No envio de e-mail, o hostname deixa de ser cosmética. O lado de lá vê-o no EHLO e verifica-o. Três coisas têm de encaixar:

  1. O nome com que o seu servidor de e-mail se apresenta (no Postfix, myhostname).
  2. O registo PTR do seu endereço IP, ou seja, a resolução inversa.
  3. Um registo A (com IPv6, um registo AAAA) para exatamente esse nome, que aponte de volta para o mesmo endereço.

Se a cadeia não fechar, muitos destinatários desvalorizam a mensagem ou rejeitam-na. Verificação sem pacotes adicionais:

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

Com o dig, do pacote bind9-dnsutils, a leitura fica mais precisa:

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

O registo PTR não pertence ao servidor. Está associado ao endereço IP e é mantido junto do operador da rede, na KernelHost através da área de cliente. Nenhuma invocação de hostnamectl altera isso, e é precisamente aqui que as mudanças de nome correm mal nos servidores de e-mail.

O Postfix não assume a mudança de nome por si próprio. No Debian e no Ubuntu, o pacote escreve um valor fixo em /etc/postfix/main.cf durante a instalação e, ao lado, fica o /etc/mailname com o nome que o Postfix usa como domínio de remetente para o correio local. Ambos permanecem inalterados:

postconf myhostname mydomain myorigin
cat /etc/mailname

Ajustar e reiniciar, tendo presente que o /etc/mailname é uma decisão à parte e não tem obrigatoriamente o mesmo valor que o myhostname:

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

Já o SPF, o DKIM e o DMARC dependem do domínio do remetente e não do hostname. Uma mudança de nome não repara, portanto, problemas de entrega cuja causa esteja aí.

Certificados

O nome do sistema não consta de nenhum certificado, porque um certificado cobre os nomes DNS que constavam do pedido. Ainda assim, uma mudança de nome faz-se sentir em três pontos.

Primeiro, no pedido. Se obtiver um certificado para o próprio nome do servidor, por exemplo para o servidor de e-mail, o nome tem de estar no DNS antes de a autoridade de certificação o consultar. Caso contrário, o processo termina com uma mensagem como DNS problem: NXDOMAIN looking up A for srv01.example.com. O registo A vem antes do pedido, não depois.

Segundo, nos certificados existentes. Continuam emitidos para o nome antigo e continuam a ser renovados até que os remova:

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

Só apague quando nenhum serviço apontar já para esse caminho, caso contrário o servidor web deixa de arrancar no recarregamento seguinte.

Terceiro, no servidor de e-mail. Se o Postfix se apresentar com o nome novo mas mostrar um certificado emitido para o antigo, falham os sistemas do outro lado que verificam o nome com rigor. O certificado e o myhostname pertencem ao mesmo nome.

Não existe qualquer relação entre o nome do sistema e o server_name do nginx. O nginx decide com base no cabeçalho Host do pedido, não com base no nome da máquina. Quem, depois de uma mudança de nome, recebe a página errada deve procurar na configuração do servidor, não no hostname. As bases estão em Instalar o nginx em Debian e Ubuntu.

Erros frequentes e respetivas soluções

sudo: unable to resolve host srv01: Name or service not known
O nome da máquina não está em /etc/hosts e é desconhecido no DNS. Acrescente a linha 127.0.1.1 srv01.example.com srv01. Enquanto ela faltar, cada invocação fica à espera de um timeout do resolver.

hostname: Name or service not known
É a resposta do hostname -f quando o nome do kernel não pode ser resolvido em lado nenhum. Mesma causa, mesma solução. Depois, verifique com getent hosts "$(hostname)" se vem mesmo alguma coisa de volta.

Could not set property: Access denied
O hostnamectl foi invocado sem permissões de root, ou a invocação decorreu num container que não pode alterar o nome do kernel. Num servidor próprio, resolve-se com sudo. Num container não privilegiado, defina o nome na configuração do container, não dentro dele.

fatal: unable to use my own hostname
Vem do log do Postfix. O valor de myhostname não resolve. Acrescente a entrada em /etc/hosts e depois execute systemctl restart postfix.

504 5.5.2 <srv01>: Helo command rejected: need fully-qualified hostname
O seu servidor de e-mail apresenta-se com o nome curto e o lado de lá exige um nome completo. Defina o myhostname com o FQDN e reinicie o Postfix.

450 4.7.1 Client host rejected: cannot find your reverse hostname
Não existe registo PTR para o seu endereço IP ou ele aponta para o vazio. Isto não se corrige no servidor, apenas junto do operador da rede IP.

java.net.UnknownHostException: srv01
Uma aplicação Java quis resolver o seu próprio nome e falhou. Outra vez o /etc/hosts. Depois de acrescentar a entrada, a aplicação tem de ser reiniciada.

DNS problem: NXDOMAIN looking up A for srv01.example.com
O novo nome ainda não existe no DNS. Crie o registo A, aguarde a propagação e repita o pedido.

Depois do reinício, o nome voltou a ser o antigo.
Verifique por esta ordem: se preserve_hostname: true está definido em /etc/cloud/cloud.cfg.d/, se o cliente DHCP já não fornece nome nenhum, se o /etc/hostname contém realmente o novo nome. Se, depois do arranque, o hostnamectl mostrar uma linha Transient hostname:, ainda há uma dessas fontes em ação.

O /etc/hosts volta a aparecer esvaziado depois de cada reinício.
O manage_etc_hosts: true está definido e o cloud-init recria o ficheiro a partir do modelo. Mude para localhost ou passe a manter o modelo.

Diferenças entre distribuições

Sistemacloud-init de origemrsyslogParticularidade
Debian 13 (trixie)apenas nas imagens de cloudausente em instalações mínimaslogs no journal em vez de /var/log/syslog
Debian 12 (bookworm)apenas nas imagens de cloudconforme a variante de instalaçãocomo no Debian 13
Ubuntu 24.04 LTSsim, preserve_hostname: falsepresentesystemd-resolved ativo, o resolve consta da linha hosts:
Ubuntu 22.04 LTSsim, preserve_hostname: falsepresentecomo no Ubuntu 24.04

Igual nos quatro sistemas: o hostnamectl nunca altera o /etc/hosts, e nenhuma ferramenta do sistema operativo cria registos DNS ou PTR. Esses dois passos continuam a ser trabalho manual.

A verificação final

Um comando sem mensagem de erro não prova nada. O único teste sólido é o reinício e, a seguir, estas cinco linhas:

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

O esperado é: o novo nome curto, o novo nome completo, uma linha vinda de /etc/hosts, um tempo de execução claramente abaixo de um décimo de segundo e exatamente uma linha para 127.0.1.1. Só quando os cinco resultados estiverem certos é que a mudança de nome está concluída, e só então pode fechar a segunda janela de terminal.

Perguntas frequentes

Porque é que o meu hostname volta a ser o antigo depois do reinício?
Porque algo o define no arranque, em regra o cloud-init ou o cliente DHCP. Crie o ficheiro /etc/cloud/cloud.cfg.d/99_hostname.cfg com a linha preserve_hostname: true e o cloud-init deixa o nome em paz. No caso do cliente DHCP, no netplan usa-se a definição use-hostname: false em dhcp4-overrides e, no systemd-networkd, UseHostname=no na secção [DHCPv4]. Para saber se alguém está sequer a interferir, veja a saída do hostnamectl: se, além de Static hostname, aparecer uma linha Transient hostname, o nome guardado e o nome em execução divergem.
Porque é que o sudo responde "unable to resolve host" e passou a demorar segundos?
Em cada invocação, o sudo manda resolver o nome da própria máquina, para a linha de log e para a comparação com as indicações de máquina em /etc/sudoers. Se o nome não estiver em /etc/hosts, o pedido segue para o resolver de DNS, que, com as predefinições da glibc, espera cinco segundos por tentativa, com duas tentativas por nameserver. Além disso, um nome curto sem ponto fica abaixo de ndots:1, pelo que ainda é acrescentado primeiro cada domínio de pesquisa. A linha 127.0.1.1 srv01.example.com srv01 em /etc/hosts acaba de imediato com isso.
Em /etc/hostname deve ficar o nome curto ou o nome completo?
As duas hipóteses funcionam. No Debian e no Ubuntu, a convenção é o nome curto, ficando o nome completo como primeira entrada na linha correspondente de /etc/hosts. Isso mantém o prompt e as linhas de log curtos, e o hostname -f devolve na mesma o FQDN. Muitas imagens de cloud escrevem antes o FQDN em /etc/hostname, o que é igualmente limpo. O verdadeiro erro é a mistura: um nome completo em /etc/hostname e outro diferente em /etc/hosts.
Porquê 127.0.1.1 em /etc/hosts e não 127.0.0.1?
O Debian e o Ubuntu separam deliberadamente o nome da própria máquina do localhost. O primeiro nome a seguir a um endereço é o canónico, e é precisamente esse que o hostname -f devolve. Se acrescentar o nome do servidor como alias à linha do localhost, o nome canónico continua a ser localhost e o hostname -f responde localhost. Os programas que daí derivam o seu próprio nome passam a escrever isso nos logs e nos cabeçalhos de e-mail. Uma linha própria com 127.0.1.1 evita esse problema. Com um endereço público fixo, pode em alternativa colocar o nome completo diretamente nesse endereço.
O hostnamectl também altera o /etc/hosts?
Não. O hostnamectl escreve o /etc/hostname, define o nome do kernel em execução e, se lho pedir, mantém o /etc/machine-info. No ficheiro /etc/hosts nunca toca. A única coisa que o altera automaticamente é o cloud-init, através da definição manage_etc_hosts: o valor true recria o ficheiro a partir de um modelo em cada arranque, o valor localhost apenas garante que o próprio nome resolve e, sem essa definição, o ficheiro fica intocado.
O comando hostname chega para uma alteração permanente?
Não. O hostname srv01 define apenas o nome transitório no kernel, e esse desaparece no reinício seguinte, porque volta então a ser carregado a partir de /etc/hostname. Para uma alteração permanente use hostnamectl set-hostname srv01, que define em conjunto o nome estático e o transitório. As versões mais recentes do systemd conhecem ainda a forma abreviada hostnamectl hostname srv01.
O que tenho de ajustar adicionalmente para o meu servidor de e-mail?
Três coisas têm de encaixar: o nome no EHLO (no Postfix, myhostname), o registo PTR do seu endereço IP e um registo A ou AAAA para exatamente esse nome, que aponte de volta para o mesmo endereço. O Postfix não assume a mudança de nome por si próprio, porque no Debian e no Ubuntu o pacote escreve um valor fixo em /etc/postfix/main.cf e, ao lado, fica o /etc/mailname. O PTR não se define no servidor, mas junto do operador da rede IP, na KernelHost através da área de cliente. Se faltar, os destinatários mais rigorosos rejeitam com 450 4.7.1 Client host rejected: cannot find your reverse hostname.

Hostname hostnamectl cloud-init Linux Debian Ubuntu DNS Servidor root