Configurar um servidor root novo: checklist para os primeiros 30 minutos
Os primeiros 30 minutos num servidor root novo são decisivos. Nove passos pela ordem certa, com as armadilhas do Debian 13 e do Ubuntu 24.04 que faltam na maioria dos guias.
Um servidor root novo fica acessível a partir do primeiro segundo e começa a ser sondado logo no primeiro minuto. As tentativas automatizadas de início de sessão na porta 22 arrancam, pela experiência, antes sequer de ter feito o seu primeiro início de sessão. Esta lista coloca um servidor acabado de entregar, em cerca de meia hora, num estado em que o pode deixar a trabalhar de consciência tranquila.
Todos os comandos partem do princípio de que está a trabalhar como root, tal como acontece logo a seguir ao aprovisionamento. Assim que iniciar sessão com o seu novo utilizador, anteponha um sudo a cada comando. A sequência foi testada em Debian 13 (trixie), Debian 12 (bookworm), Ubuntu 24.04 LTS e Ubuntu 22.04 LTS. Onde os quatro sistemas divergem, fica indicado.
Passo 0: garantir o caminho de volta antes de mudar seja o que for
O único erro desta lista que não consegue reparar por SSH é precisamente aquele que lhe tira o SSH. Por isso, nos próximos 30 minutos vale uma única regra de ferro: abra uma segunda janela de terminal com uma ligação SSH ativa e não a feche. Uma sessão SSH já estabelecida sobrevive tanto ao reinício do serviço SSH como à ativação da firewall. Se uma ligação nova deixar de funcionar depois de uma alteração, desfaça essa alteração na sessão que continua aberta.
Convém também saber onde encontrar o acesso à consola do seu servidor antes de precisar dele. Na KernelHost chega lá pela área de cliente, independentemente do SSH e independentemente da firewall. Quem só procura esse caminho quando já ficou fechado do lado de fora perde tempo.
Há mensagens de erro que deve saber distinguir, porque apontam para causas completamente diferentes:
ssh: connect to host 203.0.113.10 port 22: Connection refusedsignifica que o pacote chegou, mas ninguém está à escuta naquela porta. O serviço SSH não está a correr ou escuta noutra porta.ssh: connect to host 203.0.113.10 port 22: Connection timed outsignifica que o pacote foi descartado. Isso é quase sempre a firewall.Permission denied (publickey)significa que o serviço está a correr e a firewall deixa-o passar, apenas a sua chave não encaixa.
Passo 1: atualizar o sistema
Uma imagem acabada de instalar raramente está atualizada. Entre a construção da imagem e a sua encomenda passam muitas vezes semanas, e nesse intervalo saíram atualizações de segurança.
cat /etc/os-release
apt update
apt full-upgrade -y
Usar full-upgrade em vez de upgrade é aqui uma escolha deliberada: num sistema acabado de instalar, o apt pode remover pacotes se alguma dependência o exigir. Num sistema de produção já em funcionamento, verificaria primeiro o que iria ser removido.
No Ubuntu 22.04 e 24.04, o needrestart vem pré-instalado e interrompe o upgrade com um ecrã inteiro colorido a perguntar que serviços devem ser reiniciados. Se não quiser isso, por exemplo dentro de um script:
NEEDRESTART_MODE=a DEBIAN_FRONTEND=noninteractive apt full-upgrade -y
Depois, arrumar a casa e verificar se é preciso reiniciar:
apt autoremove --purge -y
apt list --upgradable
test -f /var/run/reboot-required && echo "reinício necessário" || echo "nenhum reinício necessário"
Diferença entre as distribuições: o ficheiro /var/run/reboot-required só o Ubuntu cria de forma fiável, porque vem do pacote update-notifier-common. O Debian, por predefinição, nem sequer avisa que é preciso reiniciar. No Debian instale para isso o needrestart, que lhe diz na chamada se há um kernel novo à espera. O Debian 13 traz ainda uma geração mais recente do apt, com saída colorida e formatada em colunas, o que não é um erro, apenas algo a que ainda não está habituado.
Controlo de sucesso: apt list --upgradable deixa de produzir qualquer saída além do cabeçalho Listing.... Se durante a atualização aparecer a mensagem Release file for ... is not valid yet, o relógio do seu servidor está errado: salte para o passo 5 e repita depois o passo 1.
Mais sobre o tema, incluindo como lidar com pacotes retidos e com repositórios de terceiros: Atualizar servidores Linux com apt.
Passo 2: criar um utilizador em vez de trabalhar como root
Não se trabalha como root porque qualquer erro de escrita atinge de imediato todo o sistema e porque qualquer atacante já conhece o nome de utilizador root. Nas imagens mínimas de Debian, o sudo muitas vezes nem sequer está instalado:
apt install -y sudo
adduser --disabled-password --gecos "" kernel
usermod -aG sudo kernel
A opção --disabled-password cria o utilizador sem palavra-passe, o que é exatamente o correto para um início de sessão apenas por chave. Se quiser definir também uma palavra-passe, por exemplo para o sudo através da consola, use passwd kernel.
Diferença entre as distribuições: no Debian e no Ubuntu, o grupo de administração chama-se sudo. Só quem vem de um sistema do tipo RHEL procura o wheel, que aqui não existe.
Agora a chave pública. Crie o diretório com as permissões certas, porque permissões erradas são a causa mais frequente de um início de sessão por chave recusado:
mkdir -p /home/kernel/.ssh
chmod 700 /home/kernel/.ssh
touch /home/kernel/.ssh/authorized_keys
chmod 600 /home/kernel/.ssh/authorized_keys
chown -R kernel:kernel /home/kernel/.ssh
O conteúdo da sua chave pública entra no ficheiro authorized_keys. Mais cómodo é fazê-lo a partir da sua máquina de trabalho com ssh-copy-id kernel@203.0.113.10.
Controlo de sucesso, e ainda antes de mexer no SSH:
id kernel
sudo -l -U kernel
A segunda linha tem de conter (ALL : ALL) ALL. Inicie depois sessão numa terceira janela como kernel e execute uma vez sudo -v. Só quando isto funcionar é que se avança. Detalhes: Criar um utilizador e configurar o sudo e ainda Criar e depositar chaves SSH.
Passo 3: proteger o SSH
Nas imagens Debian muito enxutas, o servidor SSH nem sequer está instalado. Nesse caso, instale-o primeiro:
apt install -y openssh-server
Os quatro sistemas aqui tratados leem configuração adicional a partir de /etc/ssh/sshd_config.d/. Não edite portanto o grande sshd_config, crie antes um ficheiro próprio. Esse sobrevive às atualizações de pacotes sem perguntas.
Um pormenor que quase todos os tutoriais erram: na configuração do SSH ganha o primeiro valor encontrado, não o último. A linha Include /etc/ssh/sshd_config.d/*.conf está, no Debian e no Ubuntu, logo no topo, e os ficheiros dessa pasta são lidos por ordem alfabética. Nas imagens Ubuntu já lá se encontra muitas vezes o 50-cloud-init.conf com PasswordAuthentication yes. Um ficheiro chamado 99-... ficaria, portanto, sem qualquer efeito. Veja primeiro o que já lá está:
ls -l /etc/ssh/sshd_config.d/
cat > /etc/ssh/sshd_config.d/10-kernelhost.conf <<'EOF'
PermitRootLogin prohibit-password
PasswordAuthentication no
KbdInteractiveAuthentication no
PubkeyAuthentication yes
X11Forwarding no
MaxAuthTries 3
EOF
Usar prohibit-password em vez de no é uma decisão consciente: o root continua a poder iniciar sessão com chave, mas nunca com palavra-passe. Isso salva-o se alguma coisa correr mal com o utilizador de sudo. Quem quiser apertar mais coloca no, mas nesse caso deve ter mesmo testado o acesso pela consola.
Antes de cada reinício do serviço, verifique a sintaxe:
ssh-keygen -A
sshd -t && echo "configuração ok"
sshd -T | grep -E "^(permitrootlogin|passwordauthentication|pubkeyauthentication|port) "
O sshd -T mostra os valores realmente em vigor, depois de resolvidos todos os ficheiros de Include. É a única prova fiável de que a sua alteração chegou ao destino. Se o comando responder sshd: no hostkeys available -- exiting, faltam as chaves de host e o ssh-keygen -A cria-as. Se, pelo contrário, a verificação abortar com Missing privilege separation directory: /run/sshd, o serviço nunca chegou a correr desde o arranque do sistema e falta o diretório de runtime. Um mkdir -p /run/sshd ou um systemctl restart ssh cria-o, e depois disso o sshd -t volta a avaliar a sua configuração.
Há uma saída que confunde com regularidade: para PermitRootLogin prohibit-password, o sshd -T devolve a linha permitrootlogin without-password. É o mesmo valor com o seu nome antigo, não um sinal de que a sua definição não tenha sido aplicada.
Só depois disso:
systemctl restart ssh
A armadilha do socket no Ubuntu 24.04 e no Debian 13
Desde o Ubuntu 22.10, e portanto também no 24.04, o SSH arranca por ativação de socket. A consequência: uma linha Port na configuração do sshd é ignorada, a porta vem do ssh.socket. Quem quiser mudar a porta precisa de um overlay systemd:
systemctl edit ssh.socket
Lá dentro entra o seguinte, sendo que a primeira linha vazia apaga a predefinição:
[Socket]
ListenStream=
ListenStream=0.0.0.0:2222
ListenStream=[::]:2222
A seguir, systemctl daemon-reload e systemctl restart ssh.socket. O Ubuntu 22.04 ainda não conhece este mecanismo, aí basta a linha Port na configuração.
No Debian 13 surge uma curiosidade aparentada. Algumas imagens novas têm o ssh.socket ativo, os sistemas atualizados a partir do Debian 12 não. Se ambos estiverem ativos ao mesmo tempo, um reload falha com fatal: Cannot bind any address., porque o serviço e o socket disputam a porta 22. Verifique e, na dúvida, decida:
systemctl is-enabled ssh.socket
systemctl disable --now ssh.socket
systemctl enable --now ssh.service
Controlo de sucesso: ss -tlnp | grep ssh mostra a porta esperada, e uma nova tentativa de ligação a partir de uma janela acabada de abrir funciona. Em detalhe: Proteger o SSH e desativar o início de sessão como root e Mudar a porta do SSH.
Passo 4: ativar a firewall
No Ubuntu, o ufw está instalado mas inativo. Nas imagens mínimas de Debian falta por completo. A ordem é aqui vital: primeiro permitir o SSH, só depois ligar.
apt install -y ufw
ufw default deny incoming
ufw default allow outgoing
ufw allow 22/tcp
ufw allow 80/tcp
ufw allow 443/tcp
ufw enable
O último comando é o mais importante de toda a lista. Regras e políticas predefinidas, por si só, não filtram nada: só o ufw enable arma a firewall. Quem o esquece fica no fim com uma firewall totalmente configurada, mas sem qualquer efeito.
Ao ligar, o ufw pergunta: Command may disrupt existing ssh connections. Proceed with operation (y|n)?. O aviso é para levar a sério, mas se a regra para a porta 22 (ou para a porta que alterou) já estiver antes dele, não acontece nada, e é exatamente por isso que ufw allow 22/tcp aparece na lista acima de ufw enable. Se no passo 3 mudou a porta, aqui tem de estar ufw allow 2222/tcp, caso contrário fecha-se do lado de fora. Num script ou numa sessão não interativa, use ufw --force enable, que salta a pergunta.
Controlo de sucesso:
ufw status verbose
Espera-se Status: active, por baixo Default: deny (incoming), allow (outgoing) e, na lista de regras, uma linha 22/tcp ALLOW IN para a sua porta SSH. Se continuar a aparecer Status: inactive, falta o ufw enable e nada está protegido, por muito completas que as regras pareçam. Abra depois uma janela nova e ligue-se antes de fechar a antiga.
Como complemento, junta-se um mecanismo de bloqueio contra tentativas de início de sessão:
apt install -y fail2ban python3-systemd
cat > /etc/fail2ban/jail.local <<'EOF'
[DEFAULT]
backend = systemd
bantime = 1h
findtime = 10m
maxretry = 5
[sshd]
enabled = true
EOF
Porquê backend = systemd: desde a versão 12, o Debian já não instala o rsyslog em conjunto, pelo que não existe nenhum /var/log/auth.log. O valor por omissão backend = auto procura exatamente esse ficheiro, e o fail2ban acaba por não arrancar de todo, com a mensagem Failed during configuration: Have not found any log file for sshd jail. O pacote python3-systemd é a condição para que o acesso ao journal funcione sequer. No Ubuntu 22.04 e 24.04 o ficheiro ainda existe graças ao rsyslog, mas a variante systemd também funciona lá e é a escolha à prova de futuro. Pode confirmar com:
test -f /var/log/auth.log && echo "auth.log presente" || echo "sem auth.log, é preciso backend systemd"
fail2ban-client -t
Controlo de sucesso: fail2ban-client status sshd mostra uma linha Currently banned. Se em vez disso aparecer Sorry but the jail 'sshd' does not exist, a configuração não foi carregada. Mais em Configurar a firewall UFW e Configurar o Fail2ban.
Passo 5: fuso horário e hora do sistema
Um relógio errado torna os logs inúteis, faz falhar as verificações de certificados e pode bloquear o apt com Release file is not valid yet. Num servidor a sério:
timedatectl set-timezone Europe/Vienna
timedatectl status
Na saída têm de bater certo duas linhas: Time zone: Europe/Vienna e System clock synchronized: yes, além de NTP service: active. Se aparecer NTP service: inactive, não há qualquer sincronização horária a correr. O Ubuntu traz o systemd-timesyncd por predefinição, as imagens mínimas de Debian muitas vezes não:
DEBIAN_FRONTEND=noninteractive apt install -y systemd-timesyncd tzdata
date
Muitos operadores deixam os servidores propositadamente em UTC, para que os logs de vários locais continuem comparáveis. As duas opções são defensáveis, o decisivo é que saiba qual delas escolheu. Se o timedatectl não estiver disponível num ambiente de container, também resulta pela via clássica:
ln -sf /usr/share/zoneinfo/Europe/Vienna /etc/localtime
dpkg-reconfigure -f noninteractive tzdata
Para aprofundar: Configurar o fuso horário e a sincronização horária.
Passo 6: definir o hostname
O hostname aparece nos logs, nos e-mails enviados e nas mensagens de monitorização. Defina-o cedo, senão mais tarde todos os seus servidores acabam com o mesmo nome.
hostnamectl set-hostname srv01.seu-dominio.pt
hostname -f
A seguir falta a entrada correspondente em /etc/hosts, senão, a cada chamada ao sudo, aparece a mensagem sudo: unable to resolve host srv01: Name or service not known com um atraso bem percetível. A linha é, no essencial, 127.0.1.1 srv01.seu-dominio.pt srv01.
A armadilha: nas imagens com cloud-init, o que no Ubuntu é a regra, o hostname é reposto no reinício seguinte. O interruptor contra isso:
command -v cloud-init || echo "cloud-init não instalado"
mkdir -p /etc/cloud/cloud.cfg.d
printf 'preserve_hostname: true\n' > /etc/cloud/cloud.cfg.d/99_hostname.cfg
Controlo de sucesso: depois de um reinício, o hostnamectl continua a devolver o seu nome. Detalhes: Mudar o hostname em Linux de forma permanente.
Passo 7: atualizações de segurança automáticas
O servidor mais perigoso é aquele em que ninguém volta a tocar. As atualizações de segurança automáticas são o passo isolado mais eficaz desta lista.
apt install -y unattended-upgrades
cat > /etc/apt/apt.conf.d/20auto-upgrades <<'EOF'
APT::Periodic::Update-Package-Lists "1";
APT::Periodic::Unattended-Upgrade "1";
EOF
Instalar o pacote não chega em todo o lado: só este ficheiro arma a execução diária. Os ajustes finos próprios pertencem a um ficheiro com um número mais alto do que o 50unattended-upgrades que vem incluído, para que ganhem e não sejam sobrescritos numa atualização do pacote:
cat > /etc/apt/apt.conf.d/52unattended-upgrades-local <<'EOF'
Unattended-Upgrade::Automatic-Reboot "false";
Unattended-Upgrade::Remove-Unused-Kernel-Packages "true";
Unattended-Upgrade::MinimalSteps "true";
EOF
Por predefinição, a ferramenta puxa em ambas as distribuições apenas do repositório de segurança, não as atualizações normais. Isso é intencional e, para sistemas de produção, quase sempre o correto. Se definir Automatic-Reboot "true", defina obrigatoriamente também uma hora, senão o servidor reinicia quando calhar ao temporizador.
Controlo de sucesso: uma execução de teste mostra que pacotes seriam considerados, sem instalar nada. Repare no singular no nome do comando:
unattended-upgrade --dry-run --debug
apt-config dump | grep -iE "unattended|periodic"
No log em /var/log/unattended-upgrades/ tem de aparecer alguma coisa depois da primeira execução. Se ficar vazio, a configuração não está a pegar. Em detalhe: Configurar atualizações de segurança automáticas.
Passo 8: monitorização
Nos primeiros 30 minutos, monitorização não significa montar um Grafana. Significa que fica a saber quando o servidor pára ou quando o disco enche.
apt install -y htop tmux curl
df -h /
free -m
Três coisas chegam para começar. Primeiro, um teste externo de disponibilidade, que verifica de fora e o notifica, porque um servidor que caiu já não envia qualquer aviso sobre si próprio. Segundo, um alerta de espaço em disco, porque um sistema de ficheiros cheio é a causa mais frequente de avarias que ninguém viu chegar. Terceiro, uma vista de olhos ao journal quando alguma coisa parecer estranha:
journalctl -p 3 -b --no-pager | tail -n 30
systemctl --failed
O systemctl --failed deve devolver 0 loaded units listed. Cada linha ali é um serviço que não arranca e que vale a pena reparar agora, não daqui a três meses. Mais sobre o tema: Configurar a monitorização do servidor.
Passo 9: backup antes de haver alguma coisa a perder
O melhor momento para o primeiro backup é antes de existirem dados. Assim treina o procedimento sem pressão. Há duas coisas que vale a pena guardar já, porque reconstruí-las é o que custa mais tempo: a configuração em /etc e a lista dos pacotes instalados.
tar -czf /root/etc-backup-$(date +%F).tar.gz /etc
dpkg --get-selections > /root/pacotes.txt
tar -tzf /root/etc-backup-$(date +%F).tar.gz | wc -l
Com isto ainda não tem uma cópia de segurança, apenas uma cópia no mesmo suporte. Uma cópia de segurança fica noutro sistema, idealmente noutro local. Uma ferramenta com cifragem e deduplicação de blocos iguais compensa desde o primeiro dia:
apt install -y borgbackup
borg --version
A verdade incómoda: um backup do qual nunca se recuperou nada é apenas uma suposição. Marque uma data para a primeira reposição e restaure um único ficheiro. O caminho está descrito em Estratégia de backup para servidores root.
Se ficar fechado do lado de fora
Acontece, quase sempre no passo 3 ou 4. O caminho de volta é sempre o mesmo: iniciar sessão pela consola na área de cliente, aí com nome de utilizador e palavra-passe em vez de chave. Depois, conforme a causa:
- Firewall demasiado restritiva:
ufw disable, corrigir a regra,ufw enable. - Configuração de SSH avariada:
rm /etc/ssh/sshd_config.d/10-kernelhost.conf, depoissshd -tesystemctl restart ssh. - Porta errada depois de mexer no socket:
systemctl revert ssh.socketrepõe o overlay, a seguirsystemctl daemon-reloadesystemctl restart ssh.socket. - Bloqueado pelo fail2ban:
fail2ban-client set sshd unbanip 203.0.113.10. Para que não lhe volte a acontecer, inscreva o seu endereço fixo emignoreipno ficheirojail.local. - Chave recusada: quase sempre permissões.
chmod 700no diretório,chmod 600no ficheiro, e ambos têm de pertencer ao utilizador, não ao root.
O controlo final
Um comando que não devolve erro não significa que tenha surtido efeito. Estas seis verificações mostram o estado real:
sshd -T | grep -E "^(permitrootlogin|passwordauthentication|port) "mostra os valores em vigor, não os desejados.ufw status verboseindicaStatus: activecom uma regra para a sua porta SSH.timedatectl statusindicaSystem clock synchronized: yes.systemctl --failednão lista nada.unattended-upgrade --dry-run --debugcorre até ao fim sem mensagens de erro.- Uma nova ligação SSH a partir de uma janela acabada de abrir funciona, com chave e sem pedido de palavra-passe.
Só quando o ponto seis estiver garantido é que pode fechar a antiga janela de terminal.
O que vem a seguir
Uma palavra sobre a escolha da distribuição, porque ela decide os próximos anos. O Debian 12 saiu do suporte regular em julho de 2026 e continua a ser mantido pela equipa LTS até meados de 2028, com um conjunto de pacotes limitado. Quem instala de raiz hoje escolhe o Debian 13 ou o Ubuntu 24.04 LTS. O Ubuntu 22.04 LTS ainda tem suporte padrão até 2027, mas para um servidor que deve correr durante anos já não é a primeira escolha. O Debian 10 e o Ubuntu 20.04 chegaram definitivamente ao fim em junho de 2024 e em maio de 2025, respetivamente, e não têm lugar num servidor novo.
Também são relevantes na prática as diferenças de versão nos repositórios. O Debian não fornece de todo o mysql-server, aí o padrão é o MariaDB. Quem precisa de uma versão concreta de PHP, Node ou Java faz melhor em verificar antes o que a distribuição traz, em vez de acrescentar repositórios de terceiros mais tarde. E se acrescentar repositórios de terceiros: o apt-key está descontinuado, as chaves pertencem a /etc/apt/keyrings/ e são referenciadas na definição do repositório através de signed-by.
Com isto fica de pé um servidor que está atualizado, que se mantém atualizado sozinho, que só o deixa entrar a si e que avisa quando alguma coisa não está bem. Tudo o resto, servidor web, base de dados e certificados, assenta em cima disto e não ao lado.
Perguntas frequentes
Por que ordem devo configurar um servidor root novo?
Porque é que a minha alteração à sshd_config não faz efeito?
Porque é que a porta SSH não muda no Ubuntu 24.04?
O fail2ban não arranca e diz que não encontrou ficheiro de log para o jail sshd. O que fazer?
Porque é que o meu hostname desaparece outra vez depois do reinício?
Basta o apt upgrade ou preciso mesmo do apt full-upgrade?
2026 KernelHost GmbH. Todos os direitos reservados. Este guia está protegido por direitos de autor. A sua republicação noutros sites, na íntegra, em parte ou de forma editada, não é permitida sem o nosso consentimento por escrito. Citações com indicação da fonte e ligação são expressamente bem-vindas.

