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
libssl3ouhttpd-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
| Tarefa | Debian / Ubuntu | Família RHEL |
|---|---|---|
| Atualizar os metadados | sudo apt update | automático; sudo dnf makecache para forçar |
| Instalar | sudo apt install nginx | sudo dnf install nginx |
| Remover mantendo a configuração | sudo apt remove nginx | sudo dnf remove nginx |
| Remover também a configuração | sudo apt purge nginx | sem equivalente exato |
| Atualizar tudo | sudo apt upgrade / full-upgrade | sudo dnf upgrade |
| Buscar | apt search keyword | dnf search keyword |
| Ver detalhes | apt show nginx | dnf info nginx |
| Qual pacote é dono de um arquivo | dpkg -S /usr/sbin/nginx | rpm -qf /usr/sbin/nginx |
| Listar os arquivos de um pacote | dpkg -L nginx | rpm -ql nginx |
| Verificar se está instalado | dpkg -l nginx | rpm -q nginx |
| Instalar um arquivo local | sudo apt install ./pkg.deb | sudo dnf install ./pkg.rpm |
| Limpar o cache | sudo apt clean | sudo dnf clean all |
| Remover dependências não usadas | sudo apt autoremove | sudo 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 -ie parar por aí. As dependências não são baixadas; useapt install ./file.deb. - Desativar o
gpgcheckpara 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 upgradeem 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 installousudo npm install -gem 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-diste*.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/dpkgednf/rpmdiferem 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 ogpgcheck. apt policy,dnf repoqueryednf historyexplicam 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 --verifyerpm -Vtransformam 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/localou/optquando 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.