Sobre esta presentación

  • Objetivo: Crear paquetes .deb para su consumo en sistemas Ubuntu
    • Ventajas
    • Limitantes
    • Empaquetado manual
    • Empaquetado con programas auxiliares; checkinstall, fpm
    • Distribución propia; manual, apt-ftparchive
    • Empaquetado formal: paquetes fuente (dsc)
    • Repositorios personales diarios (PPA)
    • Alternativas
  • Lo que no se discutirá:
    • Como enviar paquetes a Ubuntu
    • Como convertirse en mantenedor (empaquetador) oficial

Ventajas




  • Resolución de dependencias
  • Verificación de datos a través de firmas digitales y comparación de hashes
  • Soporte de actualizaciones
  • Métodos de distribución (al menos en sistemas Ubuntu/Debian)
  • Herramientas disponibles: dpkg, apt-get, apt-ftparchive, puppet, chef, etc

=)

Limitantes




  • Los paquetes .deb sólo funcionan en sistemas Ubuntu/Debian y derivados
  • Sólo los administradores pueden instalarlos
  • No se pueden empaquetar fácilmente múltiples versiones del mismo programa
  • Las actualizaciones son destructivas y el estado inconsistente entre ellas
  • Las actualizaciones contienen información redundante
  • No se puede reconstruir la lógica del empaquetado a partir del paquete final

=(

Empaquetado manual: panorama general





Empaquetado manual: contenedores ar





  • Los archivos .deb son contenedores ar con 3 componentes:
    • debian-binary: versión del paquete ("2.0\n")
    • control.tar.gz: metadatos; nombre, dependencias, scripts de mantenedores, etc
    • data.tar.gz: archivos del programa
 $ rm -rf pkg; mkdir pkg
 $ (cd pkg && wget http://people.ubuntu.com/~chilicuil/d/bash-completion_2.1-4_all.deb)
 $ (cd pkg && ar xv bash-completion_2.1-4_all.deb)
 bash-completion_2.1-4_all.deb
 x - debian-binary
 x - control.tar.gz
 x - data.tar.xz
        

Empaquetado manual: procedimiento

Los componentes pueden generarse individualmente

 $ rm -rf pkg; mkdir pkg
 $ (cd pkg && echo "2.0" > debian-binary) #primer componente
 $ (cd pkg && wget https://rawgit.com/chilicuil/learn/master/sh/tools/trash -P usr/bin)
 $ (cd pkg && tar czf data.tar.gz usr) #segundo
 $ (cd pkg && cat > control <<END
Package: trash-pkg
Maintainer: Javier Lopez <m@javier.io>
Priority: optional
Architecture: all
Installed-Size: $(du -ks usr|cut -f 1)
Version: 0.1
Description: Rm wrapper around the trash freedesktop specification.
END
)
 $ (cd pkg && tar czf control.tar.gz control) #tercero
        

Empaquetado manual: procedimiento

Ar genera el paquete, en este exacto orden:

 $ (cd pkg && ar -r trash-pkg_0.1_all.deb debian-binary control.tar.gz data.tar.gz)
        

A tener en cuenta:

Empaquetado manual: balance




  • Ventajas
    • Fácil
    • Rápido
    • No se necesita acceso a un sistema Ubuntu/Debian para crear paquetes
  • Desventajas
    • Poca documentación (no se supone que se empaquete así)
    • Imposibilidad de subir el resultado a un PPA (requiere almacenamiento propio, apt-ftparchive)

Empaquetado con checkinstall: panorama general

Empaquetado con checkinstall: procedimiento





  • Si existe un procedimiento estándar para instalar software en Unix, probablemente es ./configure && make && make install
  • Desafortunadamente, con frecuencia make uninstall no se define. El software se puede instalar pero no desinstalar. Checkinstall es útil en esas circunstancias.
 $ rm -rf pkg; mkdir pkg
 $ (cd pkg && wget http://nodejs.org/dist/v0.6.0/node-v0.6.0.tar.gz)
 $ (cd pkg && tar zxf node-v0.6.0.tar.gz && mv node-*/ nodejs)
 $ (cd pkg/nodejs && ./configure)
 $ (cd pkg/nodejs && make)
 $ (cd pkg/nodejs && sudo checkinstall --fstrans=yes --install=no -D \
   --pkgname=node-upstream-0.6.0 --pkgversion=0.6.0)
        

Empaquetado con checkinstall: procedimiento





  • Checkinstall puede crear paquetes a partir de cualquier comando que mueva archivos, no sólo make install
 $ rm -rf pkg; mkdir pkg
 $ (cd pkg && wget https://rawgit.com/chilicuil/learn/master/sh/tools/trash)
 $ (cd pkg && echo "Rm wrapper around the trash freedesktop specification." \
    > description-pak)
 $ (cd pkg && sudo checkinstall --fstrans=yes --install=no -D --pkgname=trash-pkg \
    --maintainer="Javier Lopez \<m@javier.io\>" --pkgarch=all --pkgversion=0.1 \
    --nodoc cp trash /usr/bin/)
        

Empaquetado con checkinstall: balance



  • Ventajas
    • Muy fácil
    • Rápido
    • Disponible en los repositorios oficiales
  • Desventajas
    • Falta de soporte (no se supone que se empaquete así)
    • No se puede copiar el resultado a un PPA (requiere almacenamiento propio, apt-ftparchive)
    • Depende de dpkg/dpkg-deb
    • Se ejecuta con permisos de super usuario (root)

Empaquetado con fpm: panorama general

Empaquetado con fpm: procedimiento



  • Fpm, permite migrar paquetes desde otros sistemas, modificar los existentes, y crear nuevos desde directorios y otros medios
 $ curl -sSL https://get.rvm.io | \
   sed "s/which gp/which xp/g" | $SHELL -s stable --ruby
 $ sudo apt-get install gcc python-setuptools php-pear npm
 $ . /home/admin/.rvm/scripts/rvm
 $ gem install fpm && rm -rf pkg; mkdir pkg
 $ (cd pkg && fpm -s gem -t deb fpm)
 Created package {:path=>"rubygem-fpm_1.3.3_all.deb"}
 $ (cd pkg && fpm -s python -t deb Django)
 Created package {:path=>"python-django_1.7.4_all.deb"}
 $ (cd pkg && fpm -s pear -t deb Mail_Mime)
 Created package {:path=>"php-pear-mail-mime_1.8.9_amd64.deb"}
 $ (cd pkg && fpm -s npm -t deb i3-style)
 Created package {:path=>"node-i3-style_0.2.3_amd64.deb"}
        

Empaquetado con fpm: procedimiento






  • Continuación
 $ rm -rf pkg; mkdir pkg
 $ (cd pkg && wget https://rawgit.com/chilicuil/learn/master/sh/tools/trash)
 $ (cd pkg && fpm -s dir -t deb \
   --description "Rm wrapper around the trash freedesktop specification." \
   --prefix /usr/bin -n trash-pkg -v 0.1 -a all trash)
 Created package {:path=>"trash-pkg_0.1_all.deb"}
 $ (cd pkg && fpm -s deb -t deb -f --edit trash-pkg_0.1_all.deb)
 Editar el archivo control
 Created package {:path=>"trash-pkg_0.1_amd64.deb"}
        

Empaquetado con fpm: balance



  • Ventajas
    • Muy fácil
    • Rápido
    • Potente
    • Soporte de la comunidad fpm
    • No requiere dpkg/Ubuntu/Debian
  • Desventajas
    • Requiere versiones de ruby y gem recientes
    • No se puede copiar el resultado a un PPA (requiere almacenamiento propio, apt-ftparchive)

Distribución propia: manual



  • Los métodos anteriores sólo generan archivos .deb. Para su distribución se requieren repositorios.
    • dpkg -i paquete.deb, no basta porque dpkg no resuelve dependencias
  • dpkg-scanpackages
 $ dpkg-scanpackages pkg > pkg/Packages
 $ echo "deb file:~/pkg $(awk -F"=" '/CODENAME/ {print $2}' /etc/*release) main" | \
   sudo tee /etc/apt/sources.list.d/repositorio.list
 $ sudo apt-get update && sudo apt-get install trash-pkg
 $ #desinstalación completa
 $ sudo apt-get purge trash-pkg && sudo rm -rf /etc/apt/sources.list.d/repositorio.list
 $ sudo apt-get update && sudo apt-get install trash-pkg
        

Distribución propia: apt-ftparchive

  • apt-ftparchive
 $ rm -rf pkg/Packages && sudo apt-get purge trash-pkg
 $ apt-ftparchive packages pkg > pkg/Packages && gzip -9c pkg/Packages > pkg/Packages.gz
 $ apt-ftparchive contents pkg > pkg/Contents && gzip -9c pkg/Contents > pkg/Contents.gz
 $ apt-ftparchive release  pkg > pkg/Release  && gzip pkg/Release > pkg/Release.gz
 $ sudo kill -9 $(pgrep -f SimpleHTTPServer) 2>&1 >/dev/null
 $ (cd pkg && sudo python -m SimpleHTTPServer 80)&
 $ echo "deb http://$(curl ifconfig.pro) /" | \
   tee /etc/apt/sources.list.d/repositorio.list
 $ sudo apt-get update && sudo apt-get install trash-pkg
 $ #desinstalación completa
 $ sudo apt-get purge trash-pkg && sudo rm -rf /etc/apt/sources.list.d/repositorio.list
 $ sudo apt-get update && sudo apt-get install trash-pkg
 $ sudo kill -9 $(pgrep -f SimpleHTTPServer) 2>&1 >/dev/null
        

Distribución propia: apt-ftparchive

Empaquetado formal: panorama general

Empaquetado formal: debian/





  • El empaquetado formal requiere un directorio debian/ con al menos 4 archivos:
    • debian/changelog: nombre, versión e historial del paquete fuente
    • debian/control: definición/descripción de los paquetes binarios
    • debian/rules: reglas para contruir/compilar el programa (Makefile)
    • debian/copyright: listado de licencias del software
    • debian/{compat,watch,install,dirs,postinst,postrm}, etc.
  • Las formas más comunes de generar tal directorio son:
    • Con dh_make o programas similares
    • Copiando los directorios debian/ de otros paquetes

Empaquetado formal: origenes, auxiliares



  • El origen del software que se empaqueta se define en debian/source/format
    • Nativo (3.0 native): Para programas propios de las distribuciones, pero también se pueden usar para scripts, configuraciones o datos que no tengan su propio medio de distribución
    • Externo (3.0 quilt): Para programas distribuidos en contenedores (tar, zip, etc)
  • Auxiliares
    • CDBS: fragmentos de archivos Makefile
    • Debhelper: Scripts en perl que automatizan parte de las operaciones frecuentes en la instalación de software (copiar archivos, crear directorios, links, etc. Algunos de ellos bastante frustantes)
    • Dh: Un envolvedor de debhelper para llamar menos scripts de debhelper explicitamente
    • Sin auxiliares (Makefile): Definición manual de los objetivos; build, binary, binary-arch, binary-indep, clean

Empaquetado formal: parches







Empaquetado formal: curva de aprendizaje




  • Si se consideran
    • 2 formas de generar el directorio debian/
    • 2 tipos de paquetes dependiendo del origen del software (nativo, externo)
    • 4 programas auxiliares de empaquetamiento
    • 1 sistema de parches

Existen por lo menos 32 combinaciones de procedimientos para crear un paquete


En resumen, empaquetar software para Ubuntu/Debian formalmente es díficil, si pueden, evitenlo. Tienen mejores cosas que hacer.

Empaquetado formal: procedimiento




  • Paquete nativo sin auxiliares: debian/changelog (dch --create)
 $ rm -rf pkg; mkdir -p pkg/trash-pkg-0.1/debian
 $ (cd pkg/trash-pkg-0.1 && \
    wget https://rawgit.com/chilicuil/learn/master/sh/tools/trash)
 $ (cd pkg/trash-pkg-0.1 && cat > debian/changelog <<END
trash-pkg (0.1) $(awk -F"=" '/CODENAME/ {print $2}' /etc/*release); urgency=low

  * Version inicial

 -- Javier P.L. <m@javier.io>  $(date -R)
END
)
        

Empaquetado formal: procedimiento


  • Paquete nativo sin auxiliares: debian/control
 $ (cd pkg/trash-pkg-0.1 && cat > debian/control <<END
Source: trash-pkg
Section: utils
Priority: optional
Maintainer: Javier Lopez 
Build-Depends:
Standards-Version: 3.9.4

Package: trash-pkg
Architecture: all
Depends: dash
Description: Rm wrapper around the trash freedesktop specification.
 Long description
END
)
        

Empaquetado formal: procedimiento


  • Paquete nativo sin auxiliares: debian/copyright
 $ rm -rf pkg; mkdir pkg/trash-pkg-0.1
 $ (cd pkg/trash-pkg-0.1 && cat > debian/copyright <<END
Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/

Files: *
Copyright: Copyright (c) 2015, Javier Lopez <m@javier.io>
License: GPL-3

Files: debian/*
Copyright: Copyright (c) 2015, Javier Lopez <m@javier.io>
License: GPL-3

License: GPL-3
 On Debian systems, the text of the GPL3 License can be found in
 '/usr/share/common-licenses/GPL-3'.
END
)
        

Empaquetado formal: procedimiento




  • Paquete nativo sin auxiliares: debian/rules
 $ (cd pkg/trash-pkg-0.1 && wget http://git.io/AebN -qO debian/rules )
 $ (cd pkg/trash-pkg-0.1 && cat debian/rules)
        
  • Generación del paquete: dpkg-buildpackage
  •  $ sudo apt-get install fakeroot lintian devscripts
     $ (cd pkg/trash-pkg-0.1 && dpkg-buildpackage -us -uc -rfakeroot)
     $ (cd pkg/trash-pkg-0.1 && ls ../) #paquete fuente(dsc) y binario(deb)
            

Empaquetado formal: procedimiento



 $ (cd pkg/trash-pkg-0.1 && debuild -us -uc) #paquete fuente(dsc) y binario(deb)
        
  • debian/control
  • debian/changelog
  • debian/rules
    • objetivos locales
  • Sólo el paquete fuente (dsc)
 $ (cd pkg/trash-pkg-0.1 && dpkg-buildpackage -S -us -uc -rfakeroot)
 #construcción del paquete binario desde un entorno aislado
 $ (cd pkg/trash-pkg-0.1 && pbuilder build paquete.dsc)
        

Empaquetado formal: procedimiento





  • Paquete externo con dh/get-orig-source: dh_make
 $ sudo apt-get install dh-make
 $ rm -rf pkg; mkdir -p pkg/trash-pkg-0.1
 $ (cd pkg/ && wget https://rawgit.com/chilicuil/learn/master/sh/tools/trash)
 $ (cd pkg/ && tar -zcf trash-pkg_0.1.orig.tar.gz trash)
 $ (cd pkg/trash-pkg-0.1 && dh_make --single --packagename trash-pkg)
 $ (cd pkg/trash-pkg-0.1 && rm debian/*.ex debian/*.EX)
        

Empaquetado formal: procedimiento




  • Paquete externo con dh/get-orig-source: debian/*
 $ (cd pkg/trash-pkg-0.1 && sed -i -e "/Section:/ s/:.*/: utils/" debian/control)
 $ (cd pkg/trash-pkg-0.1 && sed -i -e "/Description:/ s/:.*/: $(echo \
    Rm wrapper around the trash freedesktop specification.)/" debian/control)
 $ (cd pkg/trash-pkg-0.1 && sed -i -e "/Homepage/d" debian/control)
 $ (cd pkg/trash-pkg-0.1 && echo "trash usr/bin" > debian/install)
 $ (cd pkg/trash-pkg-0.1 && wget http://git.io/AIK4 -qO- >>debian/rules )
 $ (cd pkg/trash-pkg-0.1 && cat debian/rules)
 $ (cd pkg/trash-pkg-0.1 && ./debian/rules get-orig-source)
        

Empaquetado formal: procedimiento


 $ (cd pkg/trash-pkg-0.1 && debuild -us -uc) #paquete fuente(dsc) y binario(deb)
        
  • debian/control
  • debian/changelog
  • debian/rules
    • scripts originales (./configure, Makefile, etc)
    • suite debhelper (dh_*)
    • objetivos locales
  • Sólo el paquete fuente (dsc)
 $ (cd pkg/trash-pkg-0.1 && debuild -S -us -uc -rfakeroot)
 #construcción del paquete binario desde un entorno aislado
 $ (cd pkg/trash-pkg-0.1 && pbuilder build paquete.dsc)
        

Empaquetado formal: balance




  • Ventajas
    • El resultado puede incorporarse eventualmente en Debian/Ubuntu
    • El paquete fuente puede copiarse a un PPA (dput/dupload) o a una granja de empaquetado
    • Apoyo de utilidades especializadas, pbuilder, dh, dch, etc
  • Desventajas
    • Complicado, existen muchos archivos que deben crearse/modificarse
    • Tedioso, existen muchas reglas que deben seguirse
    • Se requiere un sistema con Debian/Ubuntu para crear paquetes

PPA diarios: panorama general

PPA diarios: recetas

A tener en cuenta:

  • Sólo se puede crear un PPA cuando existe un empaquetado formal (debian/)
  • Sólo se puede crear un PPA cuando los datos estan alojados en LP
  • Sólo se pueden copiar datos a LP desde repositorios públicos; git, bzr, svn y cvs
  • Antes de utilizar las granjas de LP se sugiere verificar la validez de la receta: bzr dailydeb receta(requiere bzr branch lp:bzr-builder ~/.bazaar/plugins/builder)

PPA diarios: procedimiento

Ejemplos en ~minos-archive

  • Caso hipotético de trash-pkg
 # bzr-builder format 0.3 deb-version 1:{time}+git{revno}
 lp:~usuario/proyecto/trash-pkg
 nest-part deb lp:~usuario/proyecto/trash-pkg-deb debian debian
        

Alternativas





Alternativas: 0install (universal)

zeroinstall icon
 $ sudo apt-get install gdebi unzip
 $ mkdir ~/.bin && export PATH=$PATH:$HOME/.bin
 $ rm -rf pkg; mkdir pkg
 $ (cd pkg && wget $(printf "%s%s" "http://people.ubuntu.com/~chilicuil/" \
   "d/zeroinstall-injector_2.3.3-1_$(dpkg --print-architecture).deb"))
 $ (cd pkg/ && sudo gdebi *.deb)
 $ (cd pkg/ && wget http://git.io/Asto -O trash.xml && cat trash.xml)
 $ 0install add trash trash.xml
 $ command -v trash && cat /home/admin/.bin/trash
 $ trash -h
        

Alternativas: Nix (unix)

nix icon

 $ sudo apt-get install curl
 $ wget -qO- https://nixos.org/nix/install | $SHELL
 $ . ~/.nix-profile/etc/profile.d/nix.sh
 $ rm -rf pkg; mkdir pkg
 $ (cd pkg && wget -q http://git.io/AZl6 -O trash.nix)
 $ (cd pkg && cat trash.nix && nix-env -i -f trash.nix)
 $ command -v trash
 $ trash -h
        

Alternativas: systemd (linux)



  • Subvolumenes btrfs para instalar/actualizar/administrar so/apps/etc
  • Nuevo esquema de particiones con actualización por deltas
  • Actualizaciones inversas, cifrado/firmas digitales, datos deduplicados
 usr:<compañía>:<arquitectura>:<versión> #para sistemas completos
 usr:com.ubuntu:amd64:16.04 #ejemplo directorio /usr en modo lectura

 root:<máquina>:<compañia>:<arquitectura>:<versión> #instancias de SO
 root:sup:com.ubuntu:amd64:16.04 #/etc, /var, etc en modo lectura/escritura

 runtime:<compañía>:<arquitectura>:<versión>   #librerias, para usuarios
 runtime:org.gnome.amd64:3.20.1 #ejemplo   /usr en modo lectura
 framework:<compañía>:<arquitectura>:<versión> #cabeceras, para desarrolladores
 framework:org.gnome.amd64:3.20.1 #ejemplo /usr/include/ en modo lectura
      

Alternativas: systemd (linux)




  • Modo de uso (hipotético)
  • Al arranque se monta root:usr:home: (del usuario que inicia sesión)
  • Al desarrollar una aplicación se pueden instalar/montar frameworks:
  • Al ejecutar una aplicación se monta app:runtime (esta última dependiendo de las dependencias del programa)
 app:<compañía>:<runtime>:<arquitectura>:<versión>
 app:io.javier_trash:dash:amd64:0.1 #ejemplo, /opt en modo lectura

 home:<usuario>:<id>:<gid>
 home:javier:1000:1000
      

Alternativas: paquetes click (ubuntu >= 14.04)

  • Los archivos .click son contenedores ar con 4 componentes:
    • debian-binary: versión del paquete ("2.0\n")
    • _click-binary: versión del paquete click ("0.4\n")
    • control.tar.gz: metadatos; nombre, dependencias, scripts de mantenedores, etc
    • data.tar.gz: archivos del programa
 $ rm -rf pkg; mkdir pkg
 $ (cd pkg && wget http://people.ubuntu.com/~chilicuil/d/trash.click)
 $ (cd pkg && ar xv trash.click)
 trash.click
 x - debian-binary
 x - _click-binary
 x - control.tar.gz
 x - data.tar.xz
        

Alternativas: paquetes click (ubuntu >= 14.04)

 $ sudo apt-get install click && rm -rf pkg; mkdir -p pkg
 $ (cd pkg && cat > manifest.json <<END
{
    "description": "Trash app",
    "framework": "ubuntu-sdk-14.04",
    "hooks": {
        "trash-app": {
            "desktop": "trash.desktop"
        }
    },
    "maintainer": "Javier Lopez",
    "name": "com.ubuntu.developer.chilicuil.trash",
    "title": "trash",
    "version": "0.1"
}
END
)
        

Alternativas: paquetes click (ubuntu >= 14.04)

 $ (cd pkg && wget https://rawgit.com/chilicuil/learn/master/sh/tools/trash)
 $ (cd pkg && cat > trash.desktop <<END
[Desktop Entry]
Version=1.0
Name=Trash
Comment=Rm wrapper around the trash freedesktop specification.
Exec=sh trash
Icon=utilities-terminal
Terminal=true
Type=Application
Categories=Application;
END
)
 $ click build pkg
WARNING:root:Ignoring missing framework "ubuntu-sdk-14.04"
Successfully built package in './com.ubuntu.developer.chilicuil.trash_0.1_all.click'.
        

Alternativas: paquetes click (ubuntu >= 14.04)





  • Instalación
 $ sudo click install --user=$(whoami) --force-missing-framework \
   com.ubuntu.developer.$(whoami).trash_0.1_all.click
 $ sudo click list
 $ #el registro se hace a través de un proceso de unity8
 $ sh /opt/click.ubuntu.com/com.ubuntu.developer.chilicuil.trash/0.1/trash -h
 $ sudo click unregister --user=$(whoami) com.ubuntu.developer.$(whoami).trash
        

¿Preguntas? ¿o@o?


Javier López - m@javier.io

@chilicuil en twitter/irc