Tag: fpm

Criando pacotes facilmente com o FPM

Criando pacotes facilmente com o FPM

Uma tarefa bastante comum nessa vida de sysadmin linux é criar um pacote deb/rpm/whatever a partir do zero. Pode ser um software que não tem ainda empacotamento para a nossa plataforma, pode ser um software próprio nosso, um script ou um conjunto de scripts.

(Observação: quando o problema é reempacotar/recompilar algo que já existe como pacote, a história é outra. Daí eu sempre tento usar, e ajustar se necessário, o empacotamento que já existe. Em distros baseadas em debian, ao menos, isso costuma ser bem fácil.)

Isso vira uma tarefa mais comum ainda quando usamos ferramentas como Puppet, Ansible, etc., onde utilizar um pacote para instalação de um software qualquer fica muito mais natural, prático e “limpo”, do que ter que rodar configure/make/make-install ou ficar descompactando tgzs/zip através delas.

Eu já fiz pacotes deb from scratch e até já mergulhei também alguma longínqua vez  nos meandros de pacotes RPM. Funciona, e não é lá muito difícil, mas esses processos são meio overkill quando o que eu preciso é pouco mais do que um tar/zip versionado com algumas dependências simples, e quiçá um pre/post install script. Ainda mais se for para consumo interno apenas.

Quem é das antigas vai lembrar do checkinstall. Muito usei ele. E me incomodei com ele. Mas hoje em dia para esse tipo de empacotamento leve, eu só uso o FPM:

https://github.com/jordansissel/fpm

Vantagens do FPM:

  • É fácil, mas muuuuito fácil.
  • Suporta pacotes DEB e RPM, entre outros formatos de saída.
  • … e de entrada também (Python pip -> deb|rpm em um comando, exemplo mais abaixo)
  • Tem um monte de opções para especificar dependências, pre/post scripts, e mais.
  • Mais moderno, mais recursos, mais bem mantido e menos bugs que o checkinstall.

Instalando

Um pouco ironicamente, o FPM é instalado via (ruby) gem, e não por um pacote. Ele precisa do pacote ruby-dev, gcc e make (ruby-devel no Fedora/CentOS/RHEL):

apt-get install ruby-dev make gcc
gem install fpm

Criando pacotes

Vamos começar  por um caso super simples, converter um tar em um pacote. É um caso real: em um projeto para um cliente da Propus era desejado converter o tar.xz da distribuição binária do RabbitMQ em um pacote RPM. Baixado o tar.xz, basta:

# fpm -s tar -t rpm -C rabbitmq_server-3.6.2 --prefix /opt/rabbitmq \
   -n rabbitmq-custom -v 3.6.2 rabbitmq-server-generic-unix-3.6.2.tar.xz

no value for epoch is set, defaulting to nil {:level=>:warn}
no value for epoch is set, defaulting to nil {:level=>:warn}
Created package {:path=>"rabbitmq-custom-3.6.2-1.x86_64.rpm"}

Temos aí:

  • -s: o formato de origem (tar). Ele cuida da descompactação xz/gz automaticamente, não é preciso especificar nada.
  • -t: o formato de destino (rpm).
  • -C: (chdir) diretório daonde serão coletados os arquivos para o pacote. Nesse caso, rabbitmq_server-3.6.2 é o dir raiz presente no tar, mas eu só quero no pacote o que está dentro dele.
  • –prefix: o prefixo dos arquivos dentro do pacote.
  • -n: o nome do pacote.
  • -v: a versão.
  • o argumento final é a origem propriamente dita (o arquivo tar.xz)

Python

Com o FPM também é incrivelmente fácil gerar um pacote deb/rpm a partir de um pacote do PyPI (Python Package Index, aqueles instalados com o pip):

fpm -s python -t deb rt
fpm -s python -t deb -v 0.1.6 businesstime

Pronto, gerados pacotes deb da biblioteca rt (API wrapper do RequestTracker) e da versão 0.1.6 da biblioteca businesstime. Interessante que ele converte até as dependências do pacote no PyPI:

dpkg -I python-rt_1.0.9_all.deb |grep Depends
 Depends: python-requests, python-six

Makefile

Mas o que eu mais uso, disparado, é o FPM junto com um make install. Geralmente eu tenho um Makefile para qualquer projetinho que eu queria gerar um pacote. Já tenho um modelo pronto, que segue abaixo.

Nele eu defino vários metadados como descrição, versão, autor, arquitetura, etc (linhas 22 a 28) que serão passados ao FPM (linha 33). Também já tenho nele um exemplo de chamada para pacote RPM e DEB, definindo dependências e scripts de pós-instalação (a partir das linhas 62 e 79).

O vital no caso do make install é usar a variável $(DESTDIR) como prefixo de todos os caminhos utilizados no install. Ao rodar o make install para usar com o FPM, defino esse DESTDIR para um diretório temporário TMPINSTALLDIR (ver linha 73), e o mesmo diretório é passado ao FPM como o parâmetro -C. Os argumentos finais do comando fpm são os (sub)diretórios que foram criados pelo install dentro do TMPINSTALLDIR. No caso do exemplo, etc, usr e var (ver linha 83).

Eu geralmente tenho ainda um target publish no Makefile, que já faz o upload do pacote para o repositório APT privado, configurado usando o reprepro. Mas isso seria assunto para outro post :D.

Concluindo

Existem muitas formas de gerar pacotes DEB e RPM, mas usar o FPM é disparado a mais fácil, prática e flexível que eu conheço. Empacote!