
Distribuir software para Debian, Ubuntu, Mint e derivados sem um .deb é entregar trabalho pela metade: sem gestão de dependências, sem atualização limpa, sem remoção sem rastro. A boa notícia: criar um pacote .deb decente é mais simples do que a fama sugere. Neste guia completo você vai do pacote artesanal com dpkg-deb ao pacote profissional com debhelper, passando por scripts de manutenção, lintian e repositório APT próprio.
Anatomia de um .deb
Um .deb é só um arquivo ar com três membros: debian-binary (versão do formato), control.tar.zst (metadados e scripts) e data.tar.zst (os arquivos que serão instalados, com seus caminhos finais). Dá para inspecionar qualquer pacote do sistema:
ar t /var/cache/apt/archives/htop_*.deb # lista os 3 membros
dpkg-deb --info htop_*.deb # metadados (control)
dpkg-deb --contents htop_*.deb # arquivos e destinos
Método 1: pacote rápido com dpkg-deb
Perfeito para distribuir um binário próprio (um programa em Go, um script) dentro da empresa. Vamos empacotar um utilitário fictício meuapp:
mkdir -p meuapp_1.0.0-1_amd64/{DEBIAN,usr/bin,usr/share/man/man1,etc/meuapp}
cp meuapp meuapp_1.0.0-1_amd64/usr/bin/
gzip -9 -c meuapp.1 > meuapp_1.0.0-1_amd64/usr/share/man/man1/meuapp.1.gz
cp meuapp.conf meuapp_1.0.0-1_amd64/etc/meuapp/
O coração do pacote é o DEBIAN/control:
cat > meuapp_1.0.0-1_amd64/DEBIAN/control << 'EOF'
Package: meuapp
Version: 1.0.0-1
Section: utils
Priority: optional
Architecture: amd64
Depends: libc6 (>= 2.34), ca-certificates
Maintainer: Nilton Oliveira
Homepage: https://www.linuxpro.com.br
Description: Utilitário de exemplo do LinuxPro
Linha longa da descrição: cada linha do corpo
começa com um espaço. Uma linha só com " ." separa parágrafos.
EOF
Arquivos em /etc merecem tratamento de configuração — declarados em conffiles, o dpkg preserva as edições do admin nos upgrades:
echo "/etc/meuapp/meuapp.conf" > meuapp_1.0.0-1_amd64/DEBIAN/conffiles
Precisa criar usuário de sistema ou habilitar um serviço? Entram os scripts de manutenção (preinst, postinst, prerm, postrm), todos executáveis:
cat > meuapp_1.0.0-1_amd64/DEBIAN/postinst << 'EOF'
#!/bin/sh
set -e
if [ "$1" = "configure" ]; then
getent passwd meuapp >/dev/null || useradd --system --no-create-home --shell /usr/sbin/nologin meuapp
fi
EOF
chmod 755 meuapp_1.0.0-1_amd64/DEBIAN/postinst
Gere o pacote (o --root-owner-group dispensa fakeroot) e teste:
dpkg-deb --build --root-owner-group meuapp_1.0.0-1_amd64
sudo apt install ./meuapp_1.0.0-1_amd64.deb # apt resolve as dependências
dpkg -L meuapp # confere o que foi instalado
sudo apt remove meuapp
Método 2: pacote profissional com debhelper
Para publicar de verdade — com changelog, compilação a partir do código-fonte e conformidade com a política Debian — o caminho é o debhelper. Instale a bancada:
sudo apt install build-essential devscripts debhelper dh-make lintian
Na raiz do seu código-fonte (ex.: meuapp-1.0.0/):
cd meuapp-1.0.0
dh_make --single --native --packagename meuapp_1.0.0 --email nilton@example.com
rm debian/*.ex debian/*.EX # limpa os exemplos
O diretório debian/ gerado tem quatro arquivos essenciais:
debian/control— metadados do fonte e dos binários (Build-Dependsaqui!)debian/changelog— versão vem daqui; edite comdch -idebian/rules— makefile do build; com debhelper moderno são 4 linhasdebian/copyright— licença no formato DEP-5
Um debian/rules típico hoje é só isto (o dh descobre o resto — Makefile, CMake, Go, Python…):
#!/usr/bin/make -f
%:
dh $@
Se o upstream não tem sistema de build, o debian/install mapeia arquivos para destinos:
echo "meuapp usr/bin" > debian/install
echo "meuapp.conf etc/meuapp" >> debian/install
Tem unit do systemd? Nomeie como debian/meuapp.service e o dh_installsystemd instala, habilita e dá restart no upgrade sozinho. Construa e valide:
dpkg-buildpackage -us -uc -b # sem assinatura, só binário
lintian ../meuapp_1.0.0_amd64.changes # o "linter" oficial da política Debian
Trate os avisos do lintian como um code review: cada tag tem explicação com lintian-explain-tags <tag>.
Dependências automáticas
Nunca chute versões de bibliotecas. No debian/control do binário, use as variáveis mágicas — o dpkg-shlibdeps calcula as dependências reais analisando os ELF:
Depends: ${shlibs:Depends}, ${misc:Depends}
Binários Go/Rust estáticos praticamente não têm Depends — uma das razões de eu empacotar minhas ferramentas em Go.
Versões e upgrades
O formato é [epoch:]versão-upstream[-revisão-debian] — ex.: 1.0.0-2 é a segunda revisão do empacotamento da mesma versão 1.0.0. O dpkg compara com dpkg --compare-versions; teste na dúvida:
dpkg --compare-versions 1.0.0-2 lt 1.0.1-1 && echo "upgrade ok"
Repositório APT próprio
Distribuir .deb avulso por download é metade do caminho — o resto é um repositório para apt upgrade funcionar. O jeito moderno e simples com reprepro:
sudo apt install reprepro
mkdir -p /srv/repo/conf
cat > /srv/repo/conf/distributions << 'EOF'
Codename: stable
Suite: stable
Components: main
Architectures: amd64 arm64
SignWith: SEU_KEY_ID_GPG
EOF
reprepro -b /srv/repo includedeb stable meuapp_1.0.0-1_amd64.deb
Sirva /srv/repo com nginx e, no cliente:
curl -fsSL https://repo.example.com/chave.gpg | sudo tee /usr/share/keyrings/meurepo.gpg > /dev/null
echo "deb [signed-by=/usr/share/keyrings/meurepo.gpg] https://repo.example.com stable main" |
sudo tee /etc/apt/sources.list.d/meurepo.list
sudo apt update && sudo apt install meuapp
Atalho: fpm
Para uso interno, o fpm gera .deb (e .rpm) de um diretório em um comando — sem política Debian, mas resolve rápido:
gem install fpm
fpm -s dir -t deb -n meuapp -v 1.0.0 --description "Meu utilitário"
--depends ca-certificates meuapp=/usr/bin/meuapp
Resumo prático
- Ferramenta interna?
dpkg-deb --buildoufpm— 10 minutos - Software publicado?
debhelper+lintianlimpo + repositório assinado comreprepro - Config em
/etcsempre emconffiles; usuário de sistema nopostinst; unit do systemd viadh_installsystemd
No próximo post desta dupla: o mesmo caminho para a família Red Hat com pacotes .rpm — spec file, rpmbuild, mock e createrepo.