Administração Linux

Gerenciamento de pacotes no Linux: apt, dpkg, dnf, rpm, repositórios e assinaturas

Iniciante10 min de leituraAtualizado

Esta página foi traduzida do inglês com a ajuda de IA e conferida com o original. Ler a versão em inglês

O gerenciador de pacotes é a diferença entre um servidor cujo estado você consegue entender e um amontoado de binários copiados à mão. Este guia explica o que um pacote realmente é, por que as ferramentas do Debian e do RHEL diferem no vocabulário mas não na ideia, como a assinatura de repositórios estabelece confiança e como travar, fazer downgrade e inspecionar pacotes. Ele termina com os casos em que não existe pacote e você precisa compilar ou embutir o software por conta própria.

O que você vai aprender

  • Descrever o conteúdo de um .deb ou .rpm e o que a instalação dele muda no disco
  • Usar apt e dnf com desenvoltura para buscar, instalar, atualizar, remover e limpar
  • Adicionar um repositório de terceiros com uma chave de assinatura verificada, em vez de um curl às cegas para o shell
  • Diagnosticar um conflito de dependências e travar, fixar ou fazer downgrade de um pacote de forma deliberada
  • Decidir entre um pacote da distribuição, o gerenciador de pacotes da linguagem e a compilação a partir do código-fonte

Um gerenciador de pacotes faz três coisas que copiar arquivos de um lado para o outro não consegue: registra exatamente quais arquivos pertencem a qual software, sabe do que cada software precisa para funcionar e consegue verificar se o que você baixou é o que os mantenedores publicaram. Todo o resto — os comandos, os caches, os formatos de repositório — existe para servir a essas três propriedades.

Duas famílias de ferramentas dominam. Debian, Ubuntu e seus derivados usam arquivos .deb, com o dpkg por baixo e o apt por cima. Fedora, RHEL, Rocky Linux, AlmaLinux e SUSE usam arquivos .rpm, com o rpm por baixo e o dnf (ou zypper) por cima. Os vocabulários diferem, os conceitos não; por isso este guia apresenta as duas lado a lado e aponta onde o comportamento realmente diverge.

O que existe dentro de um pacote

Um pacote é um arquivo compactado mais metadados. O arquivo compactado é a árvore de arquivos a ser extraída, organizada segundo as convenções descritas em a hierarquia do sistema de arquivos: binários em /usr/bin, bibliotecas em /usr/lib, configuração em /etc, documentação e páginas de manual em /usr/share, arquivos de unit em /usr/lib/systemd/system. A parte interessante são os metadados:

  • Identidade — nome, versão, número de release, arquitetura (amd64, arm64, noarch).
  • Dependências — o que precisa estar presente para o pacote funcionar, geralmente expresso em termos de capacidades virtuais como libssl3 ou httpd-mmn, e não de nomes de pacote, para que alternativas possam satisfazê-las.
  • Conflicts, provides, replaces — como ele se relaciona com outros pacotes.
  • Scripts do mantenedor — pequenos trechos de shell executados antes e depois da instalação ou remoção, que criam contas de sistema, geram chaves, recarregam o systemd ou reiniciam um serviço.
  • Lista de arquivos de configuração — arquivos que o gerenciador nunca deve sobrescrever silenciosamente, porque você pode tê-los editado.
  • Checksums de cada arquivo instalado.

Dá para olhar o conteúdo sem instalar nada:

dpkg --info ./nginx_1.26.0-1_amd64.deb        # metadata
dpkg --contents ./nginx_1.26.0-1_amd64.deb    # file list
rpm -qip ./nginx-1.26.0-1.el9.x86_64.rpm      # metadata
rpm -qlp ./nginx-1.26.0-1.el9.x86_64.rpm      # file list

Essa lista de arquivos de configuração explica um comportamento que confunde quem está começando. Quando uma atualização traz um padrão alterado e você editou o arquivo, o Debian pergunta se você quer manter, substituir ou ver o diff, enquanto o RPM instala a nova versão ao lado da sua como *.rpmnew (ou salva a sua como *.rpmsave). Depois de qualquer atualização grande, vale a pena rodar find /etc -name '*.rpmnew' -o -name '*.dpkg-dist'.

As mesmas operações em dois dialetos

TarefaDebian / UbuntuFamília RHEL
Atualizar os metadadossudo apt updateautomático; sudo dnf makecache para forçar
Instalarsudo apt install nginxsudo dnf install nginx
Remover mantendo a configuraçãosudo apt remove nginxsudo dnf remove nginx
Remover também a configuraçãosudo apt purge nginxsem equivalente exato
Atualizar tudosudo apt upgrade / full-upgradesudo dnf upgrade
Buscarapt search keyworddnf search keyword
Ver detalhesapt show nginxdnf info nginx
Qual pacote é dono de um arquivodpkg -S /usr/sbin/nginxrpm -qf /usr/sbin/nginx
Listar os arquivos de um pacotedpkg -L nginxrpm -ql nginx
Verificar se está instaladodpkg -l nginxrpm -q nginx
Instalar um arquivo localsudo apt install ./pkg.debsudo dnf install ./pkg.rpm
Limpar o cachesudo apt cleansudo dnf clean all
Remover dependências não usadassudo apt autoremovesudo dnf autoremove

Há três pontos em que a diferença é real, e não cosmética. Primeiro, apt update e apt upgrade são etapas separadas, e esquecer a primeira é de longe a causa mais comum de "package not found"; o dnf atualiza os metadados no seu próprio ritmo. Segundo, o apt upgrade se recusa a remover qualquer pacote, então ele segura uma atualização que exija isso — o apt full-upgrade (antes dist-upgrade) é a versão que pode remover coisas e é o que você precisa para migrar de release. Terceiro, o dnf history registra cada transação e dnf history undo 42 desfaz uma delas, algo que o apt não tem como equivalente direto.

$ dnf history list | head -4
ID     | Command line             | Date and time    | Action(s)      | Altered
------------------------------------------------------------------------------
    42 | install nginx php-fpm    | 2026-09-05 14:02 | Install        |   31
    41 | upgrade                  | 2026-09-01 03:11 | Upgrade        |  118

Instalar arquivos locais sempre pelo front-end (apt install ./pkg.deb) e não pelo dpkg -i faz diferença: o front-end busca as dependências, enquanto o dpkg deixa você com um pacote configurado pela metade e um apt --fix-broken install para rodar em seguida.

Repositórios e a cadeia de confiança

Um repositório é um diretório HTTP com pacotes e um índice. O índice é assinado com a chave de um mantenedor, e o checksum de cada pacote fica registrado nele. Sua máquina guarda as chaves públicas correspondentes, então a cadeia funciona assim: a chave confiável verifica a assinatura do índice, o índice contém o checksum e o checksum valida o pacote baixado. Quebre qualquer elo e o gerenciador de pacotes se recusa a instalar.

No Debian e no Ubuntu, as fontes ficam em /etc/apt/sources.list.d/ e as chaves em /etc/apt/keyrings/. O padrão atual e correto associa uma chave a uma fonte com signed-by, em vez de adicionar a chave a um conjunto global de confiança, onde ela poderia assinar qualquer coisa:

sudo install -d -m 0755 /etc/apt/keyrings
curl -fsSL https://download.example.com/gpg.key \
  | sudo gpg --dearmor -o /etc/apt/keyrings/example.gpg
sudo chmod 0644 /etc/apt/keyrings/example.gpg

echo "deb [arch=amd64 signed-by=/etc/apt/keyrings/example.gpg] \
https://download.example.com/debian bookworm main" \
  | sudo tee /etc/apt/sources.list.d/example.list
sudo apt update

O apt-key add, que está obsoleto, grava em um keyring global e foi removido das versões atuais; se as instruções de um fornecedor ainda mandam usá-lo, elas estão desatualizadas. Versões recentes também aceitam um único arquivo .sources no formato deb822, mais fácil de ler e que permite embutir a chave diretamente.

O equivalente na família RHEL é um arquivo .repo em /etc/yum.repos.d/:

[example]
name=Example packages
baseurl=https://download.example.com/el9/$basearch/
enabled=1
gpgcheck=1
gpgkey=https://download.example.com/RPM-GPG-KEY-example

A linha que importa é gpgcheck=1. Desligá-la para fazer uma instalação funcionar é justamente como um mirror comprometido ou corrompido vai parar em produção. Se uma chave estiver realmente indisponível, obtenha-a do fornecedor por um canal confiável e importe com rpm --import, em vez de desativar a verificação.

Como nomes de repositório como bookworm-updates e el9 estão presos a uma release da distribuição, misturar repositórios de releases diferentes produz um sistema que nenhum mantenedor jamais testou. Se você precisa de um pacote mais novo, procure um repositório oficial de backports (bookworm-backports) ou um module stream (dnf module list postgresql) antes de adicionar uma fonte externa.

Resolução de dependências e a bagunça que ela pode causar

O trabalho do resolvedor é encontrar um conjunto de versões de pacotes que satisfaça todos os requisitos declarados. Na maior parte do tempo isso é invisível. Fica visível em algumas situações bem reconhecíveis.

Atualizações retidas. O apt upgrade avisa que "the following packages have been kept back" quando a nova versão exige instalar um pacote adicional ou remover um existente. Rode apt full-upgrade, ou instale aquele pacote específico pelo nome e leia o que ele propõe.

Estado quebrado ou configurado pela metade. Normalmente é resultado de um dpkg -i sem as dependências ou de uma atualização interrompida. Para se recuperar:

sudo apt --fix-broken install
sudo dpkg --configure -a
sudo apt install -f

Versões conflitantes vindas de dois repositórios. Confira de onde vem uma versão candidata antes de instalar:

$ apt policy nginx
nginx:
  Installed: 1.22.1-9
  Candidate: 1.26.0-1
  Version table:
     1.26.0-1 500
        500 https://download.example.com/debian bookworm/main amd64 Packages
 *** 1.22.1-9 500
        500 http://deb.debian.org/debian bookworm/main amd64 Packages

O 500 é uma prioridade; apt-cache policy e dnf repoquery --qf '%{name} %{version} %{reponame}' são as ferramentas para responder "por que eu recebi essa versão?".

Simular antes de se comprometer. Os dois front-ends conseguem mostrar o plano sem executá-lo, o que vale a pena em qualquer servidor que importe:

apt-get install --dry-run some-package
dnf install --assumeno some-package
apt list --upgradable
dnf check-update

Travar, fixar e fazer downgrade

Às vezes você precisa de uma versão específica — um banco de dados que precisa bater com a aplicação, ou um driver que regrediu em uma release mais nova.

sudo apt install nginx=1.26.0-1          # exact version
sudo apt-mark hold nginx                 # exclude from future upgrades
apt-mark showhold
sudo apt-mark unhold nginx

sudo dnf install nginx-1.26.0-1.el9
sudo dnf downgrade nginx
sudo dnf versionlock add nginx           # needs the versionlock plugin

O APT também oferece um controle mais fino por meio de arquivos de pinning em /etc/apt/preferences.d/, que dão um número de prioridade a um repositório ou a um padrão de pacotes para que, por exemplo, um pacote venha dos backports enquanto todo o resto continua no stable:

Package: postgresql*
Pin: release n=bookworm-backports
Pin-Priority: 990

Cada trava e cada pin é dívida técnica com custo de segurança, porque exclui o pacote das atualizações de segurança. Escreva o motivo e uma data de validade em um comentário, e revise-os.

O que esse pacote realmente colocou no meu sistema?

Consultas reversas são a forma de entender um servidor herdado.

dpkg -S /usr/sbin/nginx                      # which package owns this file
dpkg -L nginx | grep '^/etc'                 # its configuration files
dpkg --verify nginx                          # report files that differ from the package
apt-mark showmanual                          # packages you asked for, not pulled in
zcat /var/log/apt/history.log*.gz | less     # what was installed and when

rpm -qf /usr/sbin/nginx
rpm -ql nginx
rpm -V nginx                                 # verification: size, mode, checksum, owner
rpm -q --changelog nginx | head -30
rpm -qa --last | head                        # recently installed

dpkg --verify e rpm -V comparam cada arquivo instalado com os checksums registrados na instalação. Linhas de saída como S.5....T. c /etc/nginx/nginx.conf dizem que o tamanho, o checksum e o timestamp mudaram em um arquivo marcado como configuração — o que é esperado. As mesmas flags em um binário em /usr/sbin não são esperadas e merecem investigação.

Mantendo a máquina atualizada

Atualizações de segurança são o trabalho de rotina de maior valor em qualquer servidor. As duas famílias conseguem aplicá-las sem ninguém por perto.

# Debian / Ubuntu
sudo apt install unattended-upgrades
sudo dpkg-reconfigure -plow unattended-upgrades
sudo unattended-upgrade --dry-run --debug

# RHEL family
sudo dnf install dnf-automatic
sudo systemctl enable --now dnf-automatic.timer
sudo dnf updateinfo list security

Configure a automação para aplicar apenas atualizações de segurança e registrar o que fez. Os reinícios são a parte que o pessoal esquece: um OpenSSL corrigido não adianta nada para um processo que ainda está rodando a biblioteca antiga. O needrestart no Debian e o needs-restarting -r no RHEL informam quais serviços (ou se a máquina inteira) precisam ser reiniciados. Reboots automáticos devem seguir um agendamento que você controla, e não acontecer às 03:00 por padrão.

Quando não existe pacote

De vez em quando, o software de que você precisa não está empacotado para a sua distribuição, ou a versão empacotada é antiga demais. Compilar a partir do código-fonte segue um roteiro bem conhecido:

sudo apt install build-essential pkg-config libpcre2-dev libssl-dev zlib1g-dev
curl -fLO https://example.org/releases/widget-3.2.1.tar.gz
curl -fLO https://example.org/releases/widget-3.2.1.tar.gz.sha256
sha256sum -c widget-3.2.1.tar.gz.sha256
tar -xzf widget-3.2.1.tar.gz && cd widget-3.2.1
./configure --prefix=/usr/local
make -j"$(nproc)"
sudo make install

Instale em /usr/local (o --prefix padrão exatamente por esse motivo) ou em /opt/widget-3.2.1, nunca por cima do /usr da distribuição. Verifique o checksum ou a assinatura antes de extrair, mantenha as dependências de build anotadas em algum lugar e lembre-se de que você acabou de assumir a responsabilidade de acompanhar sozinho os alertas de segurança daquele projeto — nada vai avisar você. O checkinstall consegue empacotar um make install em um .deb rudimentar para que pelo menos a lista de arquivos fique registrada.

Snap, Flatpak e os ecossistemas das linguagens

Dois formatos mais recentes empacotam a aplicação junto com suas dependências. Snap (Ubuntu) e Flatpak (multidistribuição, voltado para desktop) isolam a aplicação das bibliotecas do sistema, o que resolve conflitos de versão e adiciona sandboxing ao custo de espaço em disco, de uma primeira inicialização mais lenta e de um segundo mecanismo de atualização para monitorar. São uma escolha razoável para aplicações desktop e um padrão ruim para componentes de servidor, em que o pacote da distribuição se integra melhor ao systemd, aos logs e ao resto da máquina.

Gerenciadores de pacotes de linguagem — pip, npm, Maven, Cargo, Go modules — pertencem à sua aplicação, não ao sistema operacional. A regra que evita a maior parte da dor de cabeça: nunca rode sudo pip install no Python do sistema, porque as próprias ferramentas da distribuição dependem dele. Use um ambiente virtual, um node_modules local do projeto ou uma imagem de contêiner construída como descrito em fundamentos de Docker. As versões recentes do Python já impõem isso por conta própria, recusando-se a instalar no interpretador do sistema sem uma flag explícita de override.

Erros comuns

  • Instalar com dpkg -i e parar por aí. As dependências não são baixadas; use apt install ./file.deb.
  • Desativar o gpgcheck para passar por um erro. Você acabou de remover a única defesa contra um mirror adulterado.
  • Misturar repositórios de releases diferentes da distribuição. Funciona até que a atualização de uma biblioteca compartilhada quebre metade do sistema.
  • Deixar uma trava no lugar para sempre. As atualizações de segurança param de chegar, sem aviso. Coloque data em toda trava.
  • Rodar apt upgrade em uma máquina remota sem verificar o que vai reiniciar. O próprio SSH, ou a pilha de rede, pode estar na lista; use um multiplexador de terminal para que uma conexão perdida não aborte a transação.
  • sudo pip install ou sudo npm install -g em um servidor. As ferramentas do sistema e sua aplicação passam a compartilhar uma única árvore de dependências, e atualizar uma quebra a outra.
  • Ignorar os arquivos *.dpkg-dist e *.rpmnew. Sua configuração se afasta silenciosamente do que o pacote agora espera.

Principais conclusões

  • Um pacote é um conjunto de arquivos mais metadados: dependências, scripts do mantenedor, uma lista de arquivos de configuração protegidos e checksums por arquivo.
  • apt/dpkg e dnf/rpm diferem muito mais no vocabulário do que nos conceitos; o front-end resolve as dependências e a ferramenta de baixo nível cuida de um único arquivo compactado.
  • A confiança em um repositório se apoia em um índice assinado; adicione fontes de terceiros com uma chave dedicada e signed-by, e nunca desative o gpgcheck.
  • apt policy, dnf repoquery e dnf history explicam de onde veio uma versão e permitem desfazer uma transação.
  • Travas e pins são exceções deliberadas, documentadas e datadas — eles bloqueiam atualizações de segurança enquanto existirem.
  • dpkg -S, rpm -qf, dpkg --verify e rpm -V transformam um servidor desconhecido em algo que você consegue auditar.
  • Prefira pacotes da distribuição para componentes do sistema, ferramentas isoladas por projeto para bibliotecas da aplicação, e /usr/local ou /opt quando precisar compilar por conta própria.

Fontes e leituras complementares

Perguntas frequentes

Qual é a diferença entre apt, apt-get e dpkg?
O dpkg instala e remove um único arquivo .deb e não sabe nada sobre repositórios nem dependências. O apt-get e seu parceiro apt-cache ficam acima do dpkg, baixam dos repositórios e resolvem dependências; a saída deles é estável e segura para scripts. O apt é um front-end mais recente sobre as mesmas bibliotecas, com saída mais amigável, barras de progresso e cores, pensado para uso interativo e não para automação.
É seguro rodar apt upgrade em um servidor de produção?
É seguro no sentido de que ele nunca remove pacotes, mas pode reiniciar serviços e substituir o kernel. Leia a lista antes de confirmar, aplique as mudanças primeiro em um ambiente de homologação e saiba que um kernel novo só entra em vigor depois de um reboot. Verifique se é preciso reiniciar pelo marcador /var/run/reboot-required em sistemas Debian ou com needs-restarting -r em máquinas da família RHEL.
Como impedir que um pacote seja atualizado?
No Debian e no Ubuntu, use apt-mark hold nomedopacote, que o exclui de todas as atualizações até você rodar apt-mark unhold. Em sistemas da família RHEL, adicione exclude=nomedopacote ao /etc/dnf/dnf.conf ou use o dnf versionlock, do pacote python3-dnf-plugin-versionlock. Nos dois casos, registre por que a trava existe, porque uma trava esquecida bloqueia silenciosamente as atualizações de segurança por anos.
Devo instalar bibliotecas da linguagem com apt ou com pip, npm e Maven?
Use o pacote da distribuição para tudo aquilo de que o próprio sistema operacional depende, em especial o interpretador Python e seus módulos de sistema. Use a ferramenta da linguagem dentro de um ambiente isolado por projeto — um virtualenv, node_modules, um repositório Maven — para as dependências da aplicação, de modo que atualizar a distribuição nunca quebre sua aplicação e instalar sua aplicação nunca quebre a distribuição.