Atualização automática sem quebrar a produção
Atualizar tudo sozinho é arriscado e não atualizar nunca é pior. O meio-termo é aplicar automaticamente só o que corrige segurança, e reservar o resto para uma janela sua.
Equipe EasyOps Cloud · · 7 min de leitura
Existem dois jeitos ruins de lidar com atualização de servidor. O primeiro é atualizar tudo automaticamente e descobrir numa segunda-feira que a versão nova do PHP quebrou a aplicação. O segundo é não atualizar nunca e acumular vulnerabilidades conhecidas por anos.
O meio-termo é simples de configurar e resolve os dois problemas: aplicar automaticamente apenas correções de segurança, e reservar as demais atualizações para uma janela que você escolhe.
A distinção entre os dois tipos de atualização é a chave, e existe de verdade nas distribuições.
Segurança é diferente de versão nova
Repositórios de distribuições sérias separam correção de segurança das demais atualizações. A diferença é de política, não só de rótulo:
Correção de segurança é o mínimo necessário para fechar uma falha, aplicado sobre a versão que você já usa. Debian e Ubuntu chamam isso de *backport*: a correção é trazida para a versão antiga, sem mudar comportamento.
Atualização comum pode trazer recurso novo, mudar padrão de configuração e alterar comportamento.
É por isso que aplicar segurança automaticamente é razoavelmente seguro, enquanto aplicar tudo não é. O compromisso da distribuição, dentro de uma versão estável, é justamente não quebrar com correção de segurança.
Isso não é garantia absoluta — regressões acontecem —, mas a probabilidade é baixa o suficiente para que o risco de não aplicar seja maior.
Debian e Ubuntu
sudo apt install unattended-upgrades apt-listchanges
sudo dpkg-reconfigure -plow unattended-upgradesA configuração que importa:
// /etc/apt/apt.conf.d/50unattended-upgrades
Unattended-Upgrade::Allowed-Origins {
"${distro_id}:${distro_codename}-security";
"${distro_id}ESMApps:${distro_codename}-apps-security";
};
Unattended-Upgrade::Package-Blacklist {
"postgresql-16";
"docker-ce";
};
Unattended-Upgrade::Mail "ops@suaempresa.com.br";
Unattended-Upgrade::MailReport "on-change";
Unattended-Upgrade::Remove-Unused-Kernel-Packages "true";
Unattended-Upgrade::Automatic-Reboot "false";Repare que apenas as origens terminadas em -security estão liberadas.
Acrescentar ${distro_codename}-updates transforma isso em "atualizar tudo", que
é justamente o que estamos evitando.
A lista de bloqueio é onde vão os pacotes que você prefere atualizar à mão — banco de dados, runtime da aplicação, Docker. São os que, se der errado, dão mais trabalho.
E ative o agendamento:
// /etc/apt/apt.conf.d/20auto-upgrades
APT::Periodic::Update-Package-Lists "1";
APT::Periodic::Unattended-Upgrade "1";
APT::Periodic::AutocleanInterval "7";Teste sem aplicar nada:
sudo unattended-upgrade --dry-run --debugEssa saída mostra exatamente o que seria instalado e quais pacotes foram bloqueados. Vale rodar depois de qualquer mudança na configuração.
RHEL, AlmaLinux e Rocky
sudo dnf install dnf-automatic# /etc/dnf/automatic.conf
[commands]
upgrade_type = security
apply_updates = yes
reboot = never
[emitters]
emit_via = stdiosudo systemctl enable --now dnf-automatic.timer
systemctl list-timers dnf-automatic.timerO upgrade_type = security é o equivalente ao filtro de origem do Debian.
O reinício, que é a parte delicada
Correção de kernel e de bibliotecas centrais só passa a valer depois de reiniciar. Isso cria um dilema real: reiniciar automaticamente é arriscado, e nunca reiniciar anula parte do benefício.
A recomendação é não reiniciar sozinho, e sim saber quando é necessário:
# Debian e Ubuntu
ls -la /var/run/reboot-required 2>/dev/null
cat /var/run/reboot-required.pkgs 2>/dev/null
# RHEL e derivados
sudo dnf needs-restarting -rUm aviso semanal transforma isso em rotina, em vez de deixar a decisão para o esquecimento:
#!/usr/bin/env bash
# /usr/local/bin/check-reboot.sh
if [ -f /var/run/reboot-required ]; then
echo "Reinício pendente em $(hostname):"
cat /var/run/reboot-required.pkgs 2>/dev/null
fiSe você optar por reinício automático, ao menos restrinja a janela:
Unattended-Upgrade::Automatic-Reboot "true";
Unattended-Upgrade::Automatic-Reboot-WithUsers "false";
Unattended-Upgrade::Automatic-Reboot-Time "04:00";Isso só faz sentido em máquina redundante, onde a saída de uma não interrompe o serviço. Em servidor único, é trocar um risco conhecido por outro.
Vale saber que existe atualização de kernel sem reinício — livepatch no Ubuntu, kpatch
no RHEL. Elas cobrem parte das correções e adiam o reinício, sem eliminá-lo.
Serviço que precisa recarregar
Atualizar uma biblioteca não faz os processos que já a carregaram passarem a
usar a versão nova. Um openssl corrigido não protege o nginx que continua
rodando com a versão antiga em memória.
sudo apt install needrestart
sudo needrestart -bEle lista os serviços que precisam reiniciar. Em modo automático, recarrega o que for seguro:
# /etc/needrestart/needrestart.conf
$nrconf{restart} = 'a';
$nrconf{blacklist} = [ qr(^postgresql), qr(^mysql) ];A lista de bloqueio evita que o banco seja reiniciado no meio do expediente — o que seria uma indisponibilidade não planejada causada justamente pela ferramenta de automação.
Testar antes, quando o risco for maior
Para atualização manual maior — versão de banco, de runtime, ou o full-upgrade
periódico —, a sequência que evita surpresa:
# 1. Ver o que mudaria, sem aplicar
sudo apt update
apt list --upgradable
sudo apt full-upgrade -s | grep -E '^(Inst|Remv)'Preste atenção especial às linhas Remv. Um pacote que seria removido para
satisfazer dependência é o sinal de alerta mais confiável de que algo vai
quebrar.
# 2. Snapshot antes de aplicar
# 3. Aplicar
sudo apt full-upgrade
# 4. Conferir os serviços
systemctl --failedO snapshot é o que torna essa operação reversível. Uma atualização que deixa a máquina sem subir é rara, e quando acontece a alternativa é reinstalar.
Para segurar um pacote específico em uma versão conhecida:
sudo apt-mark hold postgresql-16
apt-mark showholdPacote retido não é atualizado nem por segurança. Vale revisar a lista periodicamente, senão a retenção temporária vira dívida permanente — que é exatamente como se acumula o problema descrito no artigo sobre fim de suporte.
O que acompanhar depois
Automação silenciosa precisa de verificação, senão você não sabe se ela funciona:
# O que foi aplicado automaticamente
sudo grep -h 'Packages that will be upgraded' \
/var/log/unattended-upgrades/unattended-upgrades.log | tail
# Quando rodou pela última vez
systemctl status unattended-upgrades.service
systemctl list-timers apt-daily-upgrade.timerVale conferir uma vez por mês que o log tem entradas recentes. Automação que parou de rodar é pior que não ter automação, porque gera confiança sem entregar o resultado — e o descobrimento costuma acontecer numa auditoria, meses depois.
O arranjo completo cabe em quinze minutos de configuração: segurança automática, lista de bloqueio para o que é crítico, reinício manual em janela conhecida e uma conferência mensal. É bem menos trabalho que a alternativa de atualizar tudo à mão — e muito menos que a de não atualizar.
O que fazer quando uma atualização quebra
Vai acontecer eventualmente, e a diferença entre um susto e um incidente longo é ter o caminho de volta claro antes de precisar dele.
O primeiro passo é identificar o que mudou. O histórico do gerenciador de pacotes responde com precisão:
# Debian e Ubuntu
grep -E 'Upgrade|Install' /var/log/apt/history.log | tail -20
zgrep -h 'Upgrade' /var/log/apt/history.log.*.gz | tail
# RHEL e derivados
sudo dnf history list | head
sudo dnf history info 42Com o pacote identificado, dá para voltar apenas ele, o que é bem menos invasivo que restaurar a máquina inteira:
# Ver as versões disponíveis no repositório
apt-cache policy nome-do-pacote
# Instalar uma versão específica
sudo apt install nome-do-pacote=1.2.3-1ubuntu2
# E segurar, para não voltar a subir na próxima rodada
sudo apt-mark hold nome-do-pacoteEm RHEL e derivados, a reversão é ainda mais direta, porque o histórico é transacional:
sudo dnf history undo 42Se a máquina não subir, o snapshot é a saída — e é por isso que ele vem antes de atualização manual grande. Vale lembrar que o console no browser continua acessível com a rede fora, o que permite diagnosticar uma máquina que não completa o boot sem depender de SSH.
Depois de resolver, registre o que aconteceu: qual pacote, qual versão, qual sintoma. Essa anotação é o que evita repetir o mesmo problema no próximo servidor — e o que justifica a entrada na lista de bloqueio para quem vier depois.
O arranjo que se sustenta
- Segurança automática, só das origens
-security. - Lista de bloqueio com banco, runtime e container.
needrestartpara recarregar serviço após correção de biblioteca, exceto os bancos.- Reinício manual, em janela conhecida, com o aviso semanal do que está pendente.
- Snapshot antes de qualquer atualização maior feita à mão.
- Conferência mensal de que a automação continua rodando.
O objetivo não é eliminar o trabalho de atualizar, é reduzi-lo ao que exige julgamento. Correção de segurança não exige julgamento — ela precisa ser aplicada. O que exige decisão é a versão maior do banco, e essa continua sendo sua.
Uma última consideração sobre containers, que ficam de fora de tudo isso. O unattended-upgrades
atualiza o sistema hospedeiro e não toca no que roda dentro das imagens. Uma
máquina impecavelmente atualizada pode estar servindo uma aplicação sobre uma
base de dois anos atrás, com todas as falhas conhecidas do período.
Para esse caso, o equivalente é reconstruir a imagem periodicamente a partir da base atualizada e reimplantar — mesmo quando o código da aplicação não mudou. Vale agendar como rotina mensal, junto da conferência acima, porque é o ponto cego mais comum em servidor que parece bem mantido.