Atualizar um servidor Linux em segurança com o apt
A diferença entre upgrade, full-upgrade e dist-upgrade, os pacotes retidos, as perguntas de configuração do dpkg, o reinício do kernel com o needrestart e a mudança de versão como categoria à parte.
Num servidor acabado de instalar, um upgrade é uma formalidade: não há nada que possa correr mal. A partir do momento em que o servidor passa a suportar serviços, são os detalhes que decidem se um upgrade corre sem que ninguém dê por ele ou se, no fim, um ficheiro de configuração ficou substituído, um serviço continua a manter a biblioteca antiga em memória ou o kernel em execução é outro que não aquele que está no disco. Este artigo percorre esses detalhes um a um. A versão resumida para um sistema acabado de disponibilizar está na checklist para um servidor root novo.
Todas as indicações se referem ao Debian 13 (trixie), ao Debian 12 (bookworm), ao Ubuntu 24.04 LTS e ao Ubuntu 22.04 LTS. Os comandos estão escritos para correr como root. Se trabalha como utilizador normal, anteponha sudo a cada comando.
Antes de executar o primeiro comando: o caminho de volta
Um upgrade pode sair caro de três maneiras: uma pergunta de configuração substitui a configuração do SSH, um kernel novo não arranca, ou a ligação cai a meio de uma transação do dpkg. As três situações são controláveis, mas apenas se tomar precauções antes.
Uma sessão que sobrevive a uma quebra de ligação
Se a ligação SSH cair durante a descompactação, o processo em execução recebe um SIGHUP e o dpkg termina a meio de uma transação. O resultado é uma base de dados de pacotes meio configurada. Por isso, execute os upgrades mais demorados numa sessão que continue a correr no servidor, mesmo que o seu terminal desapareça:
apt install -y tmux
tmux new -s upgrade
Se a ligação falhar, autentique-se de novo e recupere a sessão com tmux attach -t upgrade. Entretanto, a operação continuou a decorrer.
O caminho para o servidor quando o SSH deixa de responder
Nos servidores root KVM e nos servidores dedicados da KernelHost, chega à consola VNC pela área de cliente. Ela não depende da pilha de rede do sistema convidado e funciona também quando já nenhum serviço está à escuta. Autentique-se uma vez por essa via antes de começar e certifique-se de que sabe a palavra-passe de root.
Para o caso de um kernel que não arranca, precisa além disso de um menu de arranque visível. Nos servidores está muitas vezes oculto:
grep -E '^GRUB_TIMEOUT|^GRUB_TIMEOUT_STYLE' /etc/default/grub
Se ali aparecer GRUB_TIMEOUT_STYLE=hidden ou GRUB_TIMEOUT=0, defina GRUB_TIMEOUT_STYLE=menu e GRUB_TIMEOUT=5 e execute update-grub. Em caso de emergência, escolha na consola VNC, em "Advanced options", o kernel anterior.
Verificar o estado e registá-lo
Três verificações prévias que encontram alguma coisa com mais frequência do que se supõe:
df -h / /boot /var
dpkg --audit
apt-get check
Controlo de sucesso: o dpkg --audit não devolve nada, o apt-get check corre sem uma única linha de erro e em /boot estão livres pelo menos 300 MB. Um /boot cheio é a causa mais frequente de um upgrade de kernel interrompido, e sobre isso há mais em disco cheio no Linux. Se o dpkg --audit assinalar alguma coisa, repare isso primeiro com dpkg --configure -a.
A seguir, guarde o estado atual num ficheiro, para poder comparar mais tarde:
dpkg --get-selections > /root/pacotes-antes-do-upgrade.txt
apt-mark showhold > /root/holds-antes-do-upgrade.txt
cp -a /etc/apt /root/apt-config-$(date +%F)
update, upgrade, full-upgrade e dist-upgrade
Estas quatro palavras são confundidas constantemente. A diferença não é cosmética: é ela que decide se um kernel novo chega a ser instalado e se os pacotes podem desaparecer.
| Comando | Pacotes novos | Remove pacotes | Utilização |
|---|---|---|---|
apt update | não | não | obtém apenas as listas de pacotes, não altera nada no sistema |
apt-get upgrade | não | não | a variante mais cautelosa, retém as atualizações do kernel |
apt upgrade | sim, se uma dependência o exigir | não | o caso normal em sistemas em produção |
apt full-upgrade | sim | sim, se for preciso | quando permite remoções de forma consciente |
apt-get dist-upgrade | sim | sim, se for preciso | o nome mais antigo para a mesma coisa |
Daqui decorrem dois pontos. Primeiro: o dist-upgrade nada tem a ver com a mudança para uma nova versão da distribuição. O nome é histórico, o comando mantém-se dentro da sua versão atual.
Segundo, a diferença entre apt upgrade e apt-get upgrade é exatamente a razão pela qual alguns servidores ficam sem kernel novo. O Debian integra o kernel através do metapacote linux-image-amd64, o Ubuntu através de linux-image-generic ou de linux-image-virtual. A cada mudança de ABI, esse metapacote passa a apontar para um pacote novo, cujo número de versão consta do nome. O apt-get upgrade nunca instala pacotes novos, por princípio, e por isso deixa o kernel para trás; o apt upgrade instala-o, porque uma dependência o exige. Quem usar apt-get upgrade num script de manutenção precisa ali adicionalmente de --with-new-pkgs.
Quanto à escolha da ferramenta: a partir de um script, o apt escreve a linha WARNING: apt does not have a stable CLI interface. Use with caution in scripts. Não é uma mensagem de erro, mas é um aviso justificado. Em scripts e em roles de Ansible usa-se o apt-get; de forma interativa, o apt é mais cómodo.
O procedimento com verificação a seguir a cada passo
Passo 1: obter as listas de pacotes.
apt update
Controlo de sucesso: a saída não contém nenhuma linha que comece por Err: ou por W:. No fim aparece All packages are up to date. ou um número seguido de packages can be upgraded. Qualquer linha de erro aqui significa que continuaria a trabalhar com uma imagem incompleta da situação.
Passo 2: ver o que iria acontecer. Este passo falta na maioria dos guias e é o mais importante de todo o procedimento.
apt list --upgradable
apt full-upgrade -s
A opção -s simula e não altera nada. As linhas por baixo de The following packages will be REMOVED: são as únicas que tem realmente de verificar. Se ali não estiver nada, o full-upgrade é tão inofensivo como o upgrade. Se ali estiver um pacote de que precisa, use apt upgrade e esclareça a causa em separado.
No Debian vale ainda a pena o apt install apt-listchanges. Antes da instalação, o pacote mostra os changelogs e, o que é mais importante, os ficheiros NEWS dos responsáveis pelos pacotes. É ali que está exatamente aquilo que exige trabalho manual.
Passo 3: instalar.
apt upgrade
Fique a acompanhar. A operação faz perguntas, e um -y responde apenas à pergunta do próprio apt, não às perguntas sobre ficheiros de configuração. Essas vêm do dpkg e esperam pacientemente até que alguém responda.
Controlo de sucesso:
apt list --upgradable
dpkg --audit
systemctl --failed
journalctl -p 3 -b --no-pager | tail -n 20
O esperado é o seguinte: o apt list --upgradable não devolve nada além de Listing..., o dpkg --audit fica em silêncio e o systemctl --failed comunica 0 loaded units listed. Aquilo que realmente aconteceu fica registado de forma permanente em /var/log/apt/history.log, e a saída completa do dpkg em /var/log/apt/term.log.
Pacotes retidos: duas causas diferentes
Quando o apt deixa pacotes de fora, há para isso duas razões radicalmente diferentes, que são confundidas com regularidade.
Primeiro, um bloqueio verdadeiro. Alguém fixou o pacote de forma explícita:
apt-mark showhold
Se o comando devolver alguma coisa, foi uma decisão consciente, normalmente em bases de dados ou em módulos do kernel. Levanta-se com apt-mark unhold NOME_DO_PACOTE e define-se com apt-mark hold NOME_DO_PACOTE. Um bloqueio ao nível do dpkg vê-se com dpkg --get-selections | grep -w hold.
Segundo, a mensagem The following packages have been kept back:. Isto não é um bloqueio. Significa que, para este upgrade, o apt teria de instalar mais um pacote ou de remover um, e o comando utilizado não tem autorização para isso. A prova numa única linha, sem alterar nada:
apt full-upgrade -s | head -n 20
Se o pacote aparecer ali, a explicação está encontrada e o apt full-upgrade resolve a situação. No Debian 13, a geração mais recente do apt formata esta saída de outra maneira, mas o conteúdo não muda.
O caso particular do Ubuntu. O Ubuntu distribui as atualizações de forma faseada, nem todos os servidores as recebem no mesmo dia. Um pacote pode, portanto, ficar retido sem que exista um bloqueio nem uma dependência a impedi-lo. O diagnóstico faz-se por exclusão: o apt-mark showhold está vazio, o apt full-upgrade -s não mostra qualquer remoção e, ainda assim, o apt-cache policy NOME_DO_PACOTE indica um candidato mais recente. Nesse caso, espere alguns dias ou traga a atualização mais cedo:
apt -o APT::Get::Always-Include-Phased-Updates=true upgrade
No Debian 13 e no Debian 12 não existe distribuição faseada, pelo que esta causa fica logo à partida excluída.
Quando o apt pergunta por um ficheiro de configuração
Esta pergunta só surge quando se verificam duas condições em simultâneo: o ficheiro foi alterado localmente desde a instalação e o pacote traz consigo uma versão nova. Tem este aspeto:
Configuration file '/etc/ssh/sshd_config'
==> Modified (by you or by a script) since installation.
==> Package distributor has shipped an updated version.
What would you like to do about it ? Your options are:
Y or I : install the package maintainer's version
N or O : keep your currently-installed version
D : show the differences between the versions
Z : start a shell to examine the situation
The default action is to keep your current version.
*** sshd_config (Y/I/N/O/D/Z) [default=N] ?
A predefinição é N, ou seja, manter a sua versão. É a resposta segura, mas nem sempre é a resposta certa.
| Situação | Resposta |
|---|---|
| Já não se lembra do que foi alterado | D, ver a diferença e decidir a seguir |
| As suas alterações foram feitas de propósito e o pacote só altera comentários | N, comparar depois o .dpkg-dist |
| O ficheiro vem de uma ferramenta como o cloud-init ou o Ansible | N, voltar a correr a ferramenta a seguir |
| As novas predefinições são relevantes para a segurança e a sua alteração é dispensável | Y, voltar a aplicar depois as suas adaptações |
| Ficheiro crítico e não tem a certeza | Z, copiar o ficheiro para outro sítio, sair da shell e depois N |
Com /etc/ssh/sshd_config impõe-se um cuidado especial: um Y pode repor PermitRootLogin e PasswordAuthentication nos valores predefinidos do pacote, e é precisamente disso que depende o seu acesso. Por isso, as definições próprias de SSH pertencem a um ficheiro separado dentro de /etc/ssh/sshd_config.d/, tal como se descreve em proteger o SSH e configurar a autenticação por chave. Um ficheiro que nem sequer existe no pacote nunca desencadeia uma pergunta.
Independentemente da resposta, o dpkg não deita nada fora. Com N, a versão nova fica ao lado como .dpkg-dist; com Y, a sua versão antiga fica como .dpkg-old. Rever estes ficheiros é o verdadeiro trabalho posterior:
find /etc -name '*.dpkg-dist' -o -name '*.dpkg-old' -o -name '*.dpkg-new' -o -name '*.ucf-dist'
diff -u /etc/ssh/sshd_config /etc/ssh/sshd_config.dpkg-dist
Para execuções não assistidas, por exemplo dentro de um script de manutenção, defina o comportamento com antecedência. Esta combinação mantém a sua versão e não faz perguntas:
DEBIAN_FRONTEND=noninteractive apt-get -y \
-o Dpkg::Options::="--force-confdef" \
-o Dpkg::Options::="--force-confold" \
upgrade
O --force-confnew seria o contrário e adota sempre a versão do pacote. Num servidor com configuração própria, raramente é isso que pretende.
Atualizações do kernel e a questão do reinício
Na instalação, um kernel novo vai parar a /boot e ao menu de arranque. O kernel em execução permanece inalterado em memória até ao reinício. Um servidor pode, portanto, estar ao mesmo tempo atualizado e vulnerável. A prova mais simples é uma comparação:
uname -r
ls -1 /boot/vmlinuz-*
Se em /boot estiver uma versão superior à que o uname -r comunica, há um reinício pendente. No Ubuntu 24.04 e 22.04 existe adicionalmente um ficheiro de marcação que tem também em conta as atualizações de bibliotecas:
test -f /var/run/reboot-required && cat /var/run/reboot-required.pkgs
O segundo ficheiro indica os pacotes que pediram o reinício. No Debian 13 e no Debian 12 esta marcação não é criada de forma fiável, e ali o caminho certo é o needrestart.
needrestart: que serviços continuam a usar a biblioteca antiga
Uma atualização do OpenSSL ou da glibc substitui o ficheiro no disco. Todos os processos que já o tenham carregado continuam a trabalhar com a versão antiga. O needrestart encontra exatamente esses processos. No Ubuntu 24.04 e 22.04 vem pré-instalado e aparece a seguir a cada upgrade com uma pergunta em ecrã inteiro; no Debian, instale-o à parte:
apt install -y needrestart
needrestart -b
O modo de funcionamento -b devolve uma saída legível por máquina. Duas indicações são decisivas: o NEEDRESTART-KSTA com o valor 1 significa que o kernel em execução é o esperado; qualquer outro valor significa que já está disponível um mais recente. Cada linha NEEDRESTART-SVC indica um serviço que deveria ser reiniciado.
O comportamento controla-se através da variável de ambiente NEEDRESTART_MODE: a reinicia os serviços automaticamente, l apenas os lista, i pergunta. De forma permanente, o mesmo fica em /etc/needrestart/needrestart.conf. Para scripts, a variável é a melhor escolha, porque não altera nada na configuração:
NEEDRESTART_MODE=a DEBIAN_FRONTEND=noninteractive apt-get -y upgrade
Há um limite que convém conhecer: o needrestart olha para os processos do sistema anfitrião. Não renova os serviços que correm dentro de containers, e ali precisa de imagens novas.
A mudança de versão é uma categoria à parte
Passar do Debian 12 para o Debian 13 ou do Ubuntu 22.04 para o 24.04 não é um upgrade no sentido acima descrito. Troca as fontes de pacotes e substitui praticamente todos os pacotes. Aqui aplicam-se sempre três regras: uma versão por cada passagem, nenhuma versão intermédia saltada e, antes de tudo, um backup a partir do qual o servidor possa ser reposto.
No Debian, mude primeiro as fontes. O Debian 12 usa para isso /etc/apt/sources.list, o Debian 13 o ficheiro /etc/apt/sources.list.d/debian.sources no formato mais recente. A seguir vem um procedimento deliberadamente dividido em duas etapas, tal como as notas de lançamento o determinam:
apt update
apt-get upgrade --without-new-pkgs
apt full-upgrade
O passo do meio atualiza primeiro os pacotes que dispensam reestruturação. Isso mantém baixo o número de pacotes movidos em simultâneo e torna uma interrupção reparável. Não se esqueça do componente non-free-firmware: desde o Debian 12 é autónomo e falta nos ficheiros de fontes antigos. Se o seu apt conhecer o comando apt modernize-sources (verificável com apt --version), ele converte o ficheiro de fontes antigo para o novo formato.
No Ubuntu existe para isso uma ferramenta própria, e deve utilizar exclusivamente essa:
apt install -y ubuntu-release-upgrader-core
do-release-upgrade -c
do-release-upgrade
A opção -c apenas verifica e não altera nada. Se é ou não proposta uma mudança depende de Prompt em /etc/update-manager/release-upgrades: com lts aparece só o salto para a versão LTS seguinte, e apenas depois do primeiro lançamento intermédio dessa versão. O caminho de 20.04 para 24.04 passa obrigatoriamente por 22.04.
Um detalhe que apanha muita gente de surpresa: se o do-release-upgrade correr através de SSH, arranca um serviço SSH adicional na porta 1022 como plano de recurso e avisa que talvez tenha de abrir essa porta na firewall. Aproveite isso, mas não confie apenas nisso. A sessão tmux e o acesso pela consola VNC são mais fiáveis.
Limpeza depois do upgrade
Depois de uma passagem maior ficam por ali três tipos de resíduos: ficheiros de pacotes transferidos, pacotes órfãos e restos de configuração de pacotes removidos.
apt autoremove --purge
apt autoclean
O autoclean apaga de /var/cache/apt/archives apenas os ficheiros que, de qualquer forma, já não são disponibilizados. O apt clean esvazia por completo o diretório de cache, liberta portanto mais espaço, mas em contrapartida transforma cada nova instalação numa nova transferência.
Os restos de configuração reconhecem-se pelo estado rc do dpkg, ou seja, removido mas com a configuração ainda presente:
dpkg -l | awk '/^rc/ {print $2}'
O que ali estiver, remove-o definitivamente com apt purge NOME_DO_PACOTE. Com kernels antigos impõe-se mais cuidado, porque um passo em falso deixa o servidor sem conseguir arrancar:
uname -r
dpkg -l 'linux-image-*' | awk '/^ii/ {print $2}'
Nunca remova o kernel que a primeira linha indica e guarde ainda um mais antigo que funcione, para que o menu de arranque tenha um plano de recurso. Na maioria dos casos, o apt autoremove --purge já trata disso corretamente.
Erros frequentes e soluções
E: Could not get lock /var/lib/dpkg/lock-frontend. It is held by process 1234 (unattended-upgr): já está a correr uma segunda operação de pacotes, normalmente a atualização de segurança automática. Não a interrompa, deixe-a chegar ao fim. O procedimento completo, incluindo a reparação, está em resolver o erro do apt Could not get lock.
E: dpkg was interrupted, you must manually run 'dpkg --configure -a' to correct the problem.: uma execução anterior foi interrompida, tipicamente por uma quebra de ligação. Execute exatamente esse comando e repita a seguir o upgrade.
E: Unmet dependencies. Try 'apt --fix-broken install' with no packages (or specify a solution).: um pacote está instalado, mas faltam as suas dependências. O apt --fix-broken install trata de as instalar. Se o erro voltar, a culpa é quase sempre de uma fonte externa que disponibiliza pacotes para outra versão da distribuição.
E: Release file for http://deb.debian.org/debian/dists/trixie/InRelease is not valid yet (invalid for another 5h 3min 2s).: o relógio do servidor está atrasado. Verifique com timedatectl status se é comunicado System clock synchronized: yes, corrija a hora e repita o apt update. O problema não está no repositório.
W: GPG error: ... The following signatures couldn't be verified because the public key is not available: NO_PUBKEY ..., seguido de E: The repository '...' is not signed.: falta a chave de assinatura de uma fonte externa ou essa chave foi substituída. Hoje, a chave pertence a /etc/apt/keyrings/ e é referenciada na indicação da fonte através de signed-by ou do campo Signed-By:. O apt-key está descontinuado e não deve continuar a ser utilizado.
E: Repository '... InRelease' changed its 'Suite' value from 'stable' to 'oldstable': isto acontece normalmente quando sai uma nova versão do Debian e as suas fontes apontam para stable em vez de apontarem para o nome de código. Confirme uma única vez com apt update --allow-releaseinfo-change e passe depois as fontes para o nome de código. Caso contrário, um servidor que siga stable acaba por mudar de versão da distribuição sem que ninguém o pretenda.
E: The repository 'http://... Release' does not have a Release file.: a fonte não disponibiliza nada para a sua versão, normalmente porque uma fonte externa ainda não suporta o nome de código ou porque a distribuição chegou ao fim de vida. Desative a linha em causa e verifique a fonte.
No space left on device a meio da descompactação: o /boot ou o /var estão cheios. Arrume com dpkg --configure -a, liberte espaço e repita. Antes de cada upgrade do kernel vale a pena olhar para df -h /boot.
debconf: unable to initialize frontend: Dialog: é apenas um aviso, não é uma avaria. Surge quando não há um terminal completo, por exemplo dentro de um script. Com DEBIAN_FRONTEND=noninteractive desaparece.
Os quatro sistemas em comparação
| Tema | Debian 13 | Debian 12 | Ubuntu 24.04 | Ubuntu 22.04 |
|---|---|---|---|---|
| Ficheiro de fontes | sources.list.d/debian.sources | sources.list | sources.list.d/ubuntu.sources | sources.list |
| needrestart | instalar à parte | instalar à parte | pré-instalado | pré-instalado |
| Marcação de reinício | pouco fiável, usar o needrestart | pouco fiável, usar o needrestart | /var/run/reboot-required | /var/run/reboot-required |
| Distribuição faseada | não | não | sim | sim |
| Mudança de versão | mudar as fontes e depois em duas etapas | do-release-upgrade | ||
O controlo final
O facto de um comando ter terminado sem erros não significa que o sistema esteja em ordem. Estas seis verificações é que dizem alguma coisa:
- O
apt list --upgradablenão devolve nada além deListing.... - O
apt-mark showholdcontém apenas aquilo que bloqueou de forma consciente. - O
dpkg --auditfica em silêncio. - O
needrestart -bcomunicaNEEDRESTART-KSTA: 1e nenhum serviço pendente. - O
systemctl --failednão lista nada. - O
find /etc -name '*.dpkg-dist'já não encontra nada, porque tratou de todas as divergências.
Se o ponto quatro exigir um reinício, planeie-o e leve-o a cabo. Um servidor que fica meses à espera de um reinício pendente acumula precisamente as falhas contra as quais afinal se atualizou. Verifique depois uma última vez o uname -r e o systemctl --failed. O reinício é o momento em que se vê se tudo volta a arrancar.
Perguntas frequentes
Qual é a diferença entre apt upgrade e apt full-upgrade?
O dist-upgrade significa mudar para a versão seguinte da distribuição?
Porque é que o apt indica "The following packages have been kept back"?
O apt pergunta se deve substituir um ficheiro de configuração. O que devo responder?
Como sei que é preciso reiniciar depois de um upgrade?
Para que preciso do needrestart, se de qualquer forma vou reiniciar?
Como atualizo sem supervisão, sem que a execução fique presa numa pergunta?
Posso ficar sem acesso ao servidor por causa de um 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.

