Creando paquetes .deb para Debian y derivados

Mascote do LinuxPro fechando com fita uma caixa marcada com a espiral do Debian na esteira de empacotamento

Distribuir software para Debian, Ubuntu, Mint y derivados sin un .deb es entregar trabajo a medias: sin gestión de dependencias, sin actualización limpia, sin eliminación sin rastro. La buena noticia: crear un paquete .deb decente es más sencillo de lo que sugiere su fama. En esta guía completa irás desde el paquete artesanal con dpkg-deb hasta el paquete profesional con debhelper, pasando por scripts de mantenimiento, lintian y repositorio APT propio.

Anatomía de un .deb

Un .deb es solo un archivo ar con tres miembros: debian-binary (versión del formato), control.tar.zst (metadatos y scripts) y data.tar.zst (los archivos que se instalarán, con sus rutas finales). Se puede inspeccionar cualquier paquete del 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: paquete rápido con dpkg-deb

Perfecto para distribuir un binario propio (un programa en Go, un script) dentro de la empresa. Vamos a empaquetar una utilidad ficticia 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/

El corazón del paquete es el 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

Archivos en /etc merecen tratamiento de configuración — declarados en conffiles, el dpkg preserva las ediciones del admin en las actualizaciones:

echo "/etc/meuapp/meuapp.conf" > meuapp_1.0.0-1_amd64/DEBIAN/conffiles

¿Necesita crear un usuario de sistema o habilitar un servicio? Entran los scripts de mantenimiento (preinst, postinst, prerm, postrm), todos ejecutables:

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

Genere el paquete (el --root-owner-group no necesita fakeroot) y pruébelo:

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: paquete profesional con debhelper

Para publicar de verdad — con changelog, compilación a partir del código fuente y conformidad con la política Debian — el camino es el debhelper. Instale el banco de trabajo:

sudo apt install build-essential devscripts debhelper dh-make lintian

En la raíz de su código fuente (ej.: 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

El directorio debian/ generado tiene cuatro archivos esenciales:

  • debian/control — metadatos del fuente y de los binarios (Build-Depends aqui!)
  • debian/changelog — la versión viene de ahí; edite con dch -i
  • debian/rules — makefile de compilación; con debhelper moderno son 4 líneas
  • debian/copyright — licencia en formato DEP-5

Un debian/rules típico hoy es solo esto (el dh descubre el resto — Makefile, CMake, Go, Python…):

#!/usr/bin/make -f
%:
	dh $@

Si el upstream no tiene sistema de compilación, el debian/install mapea archivos a destinos:

echo "meuapp usr/bin" > debian/install
echo "meuapp.conf etc/meuapp" >> debian/install

¿Tiene unit de systemd? Nómbrelo como debian/meuapp.service y el dh_installsystemd lo instala, habilita y reinicia automáticamente en la actualización. Construya y 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 las advertencias del lintian como una revisión de código: cada etiqueta tiene explicación con lintian-explain-tags <tag>.

Dependencias automáticas

Nunca adivine versiones de bibliotecas. En el debian/control del binario, use las variables mágicas — el dpkg-shlibdeps calcula las dependencias reales analizando los ELF:

Depends: ${shlibs:Depends}, ${misc:Depends}

Los binarios estáticos de Go/Rust prácticamente no tienen Depends — una de las razones por las que empaqueto mis herramientas en Go.

Versiones y actualizaciones

El formato es [epoch:]versão-upstream[-revisão-debian] — p. ej.: 1.0.0-2 es la segunda revisión del empaquetado de la misma versión 1.0.0. El dpkg compara con dpkg --compare-versions; prueba si tienes dudas:

dpkg --compare-versions 1.0.0-2 lt 1.0.1-1 && echo "upgrade ok"

Repositorio APT propio

Distribuir un .deb suelto mediante descarga es la mitad del camino: lo demás es un repositorio para apt upgrade funcionar. La forma moderna y sencilla con 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

Sirve /srv/repo con nginx y, en el 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

Atajo: fpm

Para uso interno, el fpm genera .deb (y .rpm) desde un directorio con un solo comando — sin política Debian, pero lo soluciona 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

Resumen práctico

  • ¿Herramienta interna? dpkg-deb --build o fpm — 10 minutos
  • ¿Software publicado? debhelper + lintian limpio + repositorio firmado con reprepro
  • Config en /etc siempre en conffiles; usuario de sistema en postinst; unidad de systemd mediante dh_installsystemd

En el próximo post de esta pareja: el mismo camino para la familia Red Hat con paquetes .rpm — spec file, rpmbuild, mock y createrepo.