- Per creare un RPM è necessario un albero di lavoro rpmbuild, un file SPEC ben definito e le sorgenti organizzate in SOURCES.
- Le sezioni %prep, %build, %install e %files di SPEC controllano l'intero ciclo di decompressione, compilazione, installazione in buildroot e selezione di cosa includere.
- rpmbuild genera pacchetti sia binari che sorgenti, che puoi installare, ispezionare e gestire con gli stessi strumenti che usi per i pacchetti ufficiali.
- La firma degli RPM con GPG e la verifica delle loro firme sui sistemi di destinazione garantiscono l'integrità e la paternità dei pacchetti distribuiti.

Se lavori con distribuzioni come RHEL, CentOS, Fedora o altri derivati di Red Hat, prima o poi dovrai chiederti come Crea il tuo pacchetto .rpm passo dopo passoAvere le tue applicazioni in pacchetti ti consente di installarle, aggiornarle e distribuirle in modo pulito, controllato e automatizzato, proprio come faresti con qualsiasi pacchetto del repository ufficiale.
Potrebbe sembrare "magia nera", ma scoprirai che creare RPM è un processo molto logico: si basa sulla preparazione di un albero di lavoro, sulla scrittura di un file SPEC con le istruzioni per il packaging e sul lasciare che lo strumento faccia il resto. rpm build Fai il lavoro duro. Da lì puoi generare pacchetti semplici (un copione e poco altro) o veri e propri "pacchetti" con binari, librerie, documentazione, configurazione, dipendenze... tutto ciò di cui hai bisogno.
Che cos'è un pacchetto RPM e perché vale la pena crearlo?
Un pacchetto RPM è semplicemente un file che contiene i file del tuo software insieme ai metadati: nome, versione, architettura, dipendenze, script di installazione, ecc. Internamente, i dati vengono archiviati in un contenitore cpio compresso con strumenti quali gzip, bzip2, XZ, LZMA o XAR, a seconda della versione RPM utilizzata.
Il nome di un pacchetto RPM ha solitamente questa forma: nome-versione-rilascio.architettura.rpm. Ad esempio, nginx-1.19.3-1.el7.ngx.x86_64.rpmdove si distinguono quattro elementi fondamentali: il nome del programma, la sua versione, il numero di release del pacchetto e l'architettura per cui è stato compilato (x86_64, noarch, ecc.).
Creare i propri RPM offre diversi vantaggi molto chiari: puoi automatizzare installazioni identiche Su molti server, gestire le dipendenze con lo stesso sistema che già usi (yum, dnf, zypper) e conoscere il programmi di installazione dei pacchetti più popolaricontrollare cosa viene installato e dove, firmare i pacchetti per garantirne la paternità e, se vuoi fare un ulteriore passo avanti, configurarne uno tuo Repository RPM aziendale.
Preparare l'ambiente e gli strumenti necessari
Prima di iniziare a imballare qualsiasi cosa, devi avere il strumenti minimi di sviluppo e i pacchetti relativi a rpm-build. Questo varia leggermente a seconda della distribuzione, ma l'idea generale è la stessa.
Nei sistemi basati su Red Hat (RHEL, CentOS, Rocky, Alma, Fedora prima di dnf), di solito si installa almeno:
- rpm-build y rpmdevtools per utilizzare rpmbuild e utilità ausiliarie.
- Pacchetti di compilazione: gcc, make (Automatizzare la compilazione con Makefile), glibc-devel, automake, autoconfecc., se si intende compilare dal codice sorgente.
- Altri pacchetti di sviluppo specifici (ad esempio, openssl-devel, zlib-devel, pcre-devel nel caso di Nginx).
Su una moderna macchina RHEL/CentOS/derivata Puoi estrarre da:
yum install -y rpm-build rpmdevtools gcc make glibc-devel automake autoconf
Se si utilizza Fedora, oltre agli strumenti di sviluppo, è comune installare il set di strumenti di compilazione e il pacchetto confezionatore fedora:
yum install @development-tools
yum install fedora-packager
In Debian o Ubuntu, è anche possibile generare RPM, sebbene non sia il loro formato nativo. In questo caso, è necessario, come minimo, rpm e rpm2cpio per manipolare e creare pacchetti:
sudo apt -y install rpm rpm2cpio
Negli ambienti desktop come alcune distribuzioni derivate, se vuoi firmare i tuoi pacchetti dovrai anche aggiungere gnupg E se preferisci qualcosa di grafico, strumenti come seahorse e gpgme consentono di gestire comodamente le chiavi GPG.
Creare un utente e l'albero di lavoro rpmbuild
Esiste una regola d'oro quando si creano pacchetti: non compilare o impacchettare mai come radiceSe uno SPEC contiene un percorso errato o uno script con effetti collaterali, è possibile causare seri problemi se viene eseguito con privilegi di superutente.
Si consiglia di creare un utente specifico per il packaging, ad esempio rpm o makerpme usalo sempre quando lavori con rpmbuild. Su RHEL/CentOS, come root, potresti fare qualcosa del genere:
useradd rpm -m
passwd rpm
In Fedora, se si intende utilizzare un mock (un ambiente di compilazione isolato, ad esempio con Contenitori Docker), è una buona idea aggiungere l'utente al gruppo finto per poter effettuare build pulite:
/usr/sbin/useradd makerpm
usermod -a -G mock makerpm
Una volta effettuato l'accesso con quell'utente, il passo successivo è creare il struttura di directory standard che utilizza rpmbuild. Su Red Hat e Fedora, basta eseguire:
rpmdev-setuptree
Questo comando creerà nel tuo casa Cartella rpmbuild con diverse sottodirectory essenziali:
- COSTRUIRE: dove il codice sorgente viene decompresso e il codice viene compilato.
- BUILDROOT (o BUILDROOT sotto BUILD): dove viene simulata l'installazione del contenuto del pacchetto.
- FONTI: dove vengono posizionati i file del codice sorgente, i tarball e le patch.
- SPECS: dove verranno salvati i file
.speccon le istruzioni di imballaggio. - RPM: destinazione dei pacchetti binari generati, organizzati per architetture (x86_64, noarch, ecc.).
- SRPMS: contenitore per i pacchetti sorgente
.src.rpm.
Se utilizzi Debian e non hai rpmdevtools, puoi configurare manualmente qualcosa di equivalente con:
mkdir -p ~/rpmbuild/{BUILD,BUILDROOT,RPMS,SOURCES,SPECS,SRPMS}
Organizzare le fonti in SOURCES con un esempio pratico
Con l'albero pronto, è il momento di preparare il contenuto che si desidera impacchettare. In genere, si crea una directory con il programma o lo script e quindi si crea un tar.gz da quella directory per metterlo in ~/rpmbuild/SOURCES.
Immagina di voler creare un pacchetto di uno script chiamato n (nota responsabile in terminale) o un piccolo esempio chiamato pacchetto-di-test-1.0 che contiene un file README e uno script eseguibile. In tal caso, la directory di lavoro conterrebbe qualcosa del genere:
test-package-1.0/
README.txt
test-check
configure
Un fatto curioso: anche se non hai intenzione di compilare nulla, molti modelli SPEC vengono eseguiti ./configure nella fase %buildSe il file non esiste, verrà visualizzato un errore. Per evitare questo problema, di solito viene creato un file. configure vuoto e assegnagli i permessi di esecuzione:
touch configure
chmod 0744 configure
Una volta che il contenuto è pronto, crea il tarball e copialo in SOURCES:
tar -czvf test-package-1.0.tar.gz test-package-1.0/
cp -p test-package-1.0.tar.gz ~/rpmbuild/SOURCES/
In altri casi, come lo script delle note "n" o il font Vremena, si clona direttamente da un repository Git all'interno di SOURCES, si modifica il nome della cartella (ad esempio, n-fanta-0.0.1), eliminare la directory .git per evitare di includere la cronologia nel file tar.gz e infine generare il file compresso:
tar -czvf n-fanta-0.0.1.tar.gz n-fanta-0.0.1
Il file SPEC: il cuore del pacchetto RPM
il file .spec Qui viene definito tutto ciò che riguarda il pacchetto: nome, versione, licenza, dove si trovano i sorgenti, come viene compilato, come viene installato, quali file sono inclusi e quali script vengono eseguiti durante l'installazione o la disinstallazione.
Normalmente, gli SPEC sono memorizzati in ~/rpmbuild/SPECS ed è consigliabile che il suo nome corrisponda al nome del pacchetto, ad esempio pacchetto-di-test.spec o vremena-font.specPuoi creare un modello minimo con:
cd ~/rpmbuild/SPECS
rpmdev-newspec test-package
Questo genererà uno scheletro chiamato test-package.spec o newpackage.specche puoi poi adattare. In Debian, se non hai rpmdev-newspec, puoi crearne uno tuo. modello.spec scrivilo a mano e riutilizzalo copiandolo ogni volta che inizi un nuovo pacchetto.
Uno SPEC tipico inizia con una zona di Testiera dove sono indicati i dati di base:
- Nome: nome base del pacchetto (in minuscolo e senza spazi).
- Versione: versione del software, solitamente la stessa utilizzata dall'autore.
- Rilasciare: numero di build del tuo imballaggio, molte volte
1%{?dist}. - Sintesi: breve descrizione di una riga, senza punto.
- Licenza: tipo di licenza (GPLv3, MIT, ecc.).
- URL: homepage del progetto.
- Fonte0: percorso o URL del tarball principale (di solito include
%{name}y%{version}). - BuildRequires: pacchetti richiesti per la compilazione.
- Richiede: dipendenze che il sistema deve avere installate quando si utilizza l'RPM.
Da lì, una serie di sezioni delimitato da macro che iniziano con %ognuno con uno scopo chiaro:
- % descrizione: testo più lungo che spiega a cosa serve il pacchetto.
- % prep: preparazione delle fonti (decompressione, applicazione delle patch).
- % build: compilazione o attività equivalenti.
- % dai un'occhiata: test automatizzati, se presenti.
- % install: installazione nell'albero di %{buildroot} forma simulata.
- % File: elenco dei file e delle directory che faranno parte del pacchetto finale.
- % changelogCronologia delle modifiche SPEC.
All'interno di SPEC puoi utilizzare molti Macro RPM che si espandono automaticamente: %{name}, %{version}, %{_bindir} (di solito /usr/bin), %{_sysconfdir} (/ecc.), %{_libdir} (/usr/lib o /usr/lib64), %{_datadir} (/usr/share), ecc. Ciò semplifica la manutenzione dello SPEC nel tempo e su diverse architetture.
Fasi %prep, %build e %check in dettaglio
sezione % prep Di solito inizia con una macro %setup, che estrae la fonte principale da SOURCE0 nella directory BUILD. La cosa più tipica è:
%prep
%setup -q
Se il tarball viene estratto in una directory che non corrisponde al nome predefinito, è possibile specificare il nome in modo esplicito con -n, per esempio %setup -q -n n-fanta-0.0.1Anche qui valgono le patch dichiarate come tali. Patch0, Patch1… utilizzando macro %patch con il livello appropriato (-p1, Ecc.).
Nella sezione % build Qui avviene la compilazione o un suo equivalente. Molti progetti basati su autotools supportano semplicemente:
%build
%configure
make %{?_smp_mflags}
Nei progetti più semplici, come l'esempio del pacchetto di test che contiene solo uno script, potresti anche lasciare la sezione vuota o commentare le righe di %configure y make se non sono necessari, purché non vengano eseguiti nel flusso rpmbuild.
sezione % dai un'occhiata È riservato al lancio di batterie di test automatizzati, solitamente con comandi tipo make test o make checkSi consiglia di tenerlo separato da %build in modo da poter disabilitare i test quando necessario (ad esempio, in build rapide o in ambienti limitati).
Installare nella buildroot e dichiarare i file del pacchetto
sezione % install Qui è dove l'installazione del software viene simulata in un albero di directory vuoto chiamato %{buildroot}La procedura usuale è quella di pulire prima i detriti precedenti e poi utilizzare il classico schema di DEST.DIR:
%install
rm -rf %{buildroot}
make install DESTDIR=%{buildroot}
Se il tuo progetto di esempio è molto semplice e non ha `make install`, puoi usare i comandi. install y mkdir per creare directory e copiare file manualmente, come nel caso di test-package:
%install
rm -rf $RPM_BUILD_ROOT
install -d -m 0755 /var/tmp/test-package
install -m 0644 README.txt /var/tmp/test-package
install -m 0755 test-check /var/tmp/test-package
In pacchetti più elaborati, come il font vremena-fontLa sezione %install è responsabile del posizionamento dei file nei percorsi di sistema standard, ad esempio sotto /usr/share/fontsmantenendo le autorizzazioni appropriate e lasciando tutto pronto in modo che la cache dei font possa essere aggiornata con uno script %post.
Una volta riempito il buildroot con ciò che è necessario, è il momento di elencare ciò che verrà impacchettato nella sezione % FileQui vengono utilizzati percorsi relativi. %{buildroot}, macro e alcuni prefissi speciali:
- %doc per contrassegnare la documentazione (README, LICENZA, ecc.).
- %config o %config(noreplace) per i file di configurazione in /etc.
- %lang per specificare i file di localizzazione in base alla lingua.
Nel caso del font Vremena, ad esempio, la sezione %files elencherebbe ogni file .otf bajo /usr/share/fonts/vremena-serif/Nei pacchetti semplici è sufficiente includere la directory in cui sono stati installati lo script o i file di dati.
Se il pacchetto installa librerie condivise in percorsi di sistema standard (ad esempio, in %{_libdir}), di solito vengono aggiunti un paio di scriptlet allo SPEC %inviare y %postun che eseguono ldconfig per aggiornare la cache del linker dinamico dopo l'installazione o la disinstallazione.
Creazione del pacchetto RPM: binario e sorgente
Con lo SPEC pronto e il tar.gz in FONTIOra puoi evocare rpm build Per generare il pacchetto, solitamente si passa alla directory SPECS ed si esegue:
cd ~/rpmbuild/SPECS
rpmbuild -ba test-package.spec
l'opzione -ba indica che si desidera creare sia l'RPM binario che il .src.rpmSe vuoi solo il binario, puoi usare -bbSe sei interessato solo alla sorgente RPM, -bsDurante il processo, vedrai le fasi %prep, %build, %install, ecc. eseguite e, se tutto va bene, l'output terminerà con qualcosa del tipo esci da 0.
Il risultato verrà memorizzato in:
- ~/rpmbuild/RPMS/ / per RPM binario, ad esempio
test-package-1.0-1.el6.i386.rpmovremena-font-0.1-1.x86_64.rpm. - ~/rpmbuild/SRPMS/ per il pacchetto sorgente corrispondente.
Se stai confezionando qualcosa di più complesso come Nginx con un modulo SPNEGOLa logica è esattamente la stessa, anche se in quel caso si potrebbe partire da un .src.rpm nginx ufficiale, installalo con rpm -UvhModificare lo SPEC generato, aggiungere il modulo dinamico nella sezione build e generare nuovi RPM con rpmbuild -bb nginx.spec.
Firma e verifica i pacchetti RPM con GPG
Se intendi distribuire i tuoi RPM ad altre macchine (o addirittura all'intera organizzazione), è altamente consigliato. firmarli digitalmente con GPG. La firma consente ai sistemi di destinazione di verificare che il pacchetto sia stato effettivamente creato e che non sia stato modificato durante il transito.
Il flusso di base è: si genera un Chiave GPGÈ sufficiente configurare le macro RPM per utilizzarlo, firmare l'RPM e quindi distribuire la chiave pubblica ai client in modo che possano convalidare la firma. Ecco un esempio di configurazione minima: ~/.rpmmacros voluto:
%_signature gpg
%_gpg_path %(echo "$HOME")/.gnupg
%_gpg_name Nombre Apellido (Comentario) <correo@dominio>
%_gpgbin /usr/bin/gpg2
Una volta creata la chiave con gpg2 –gen-key (Seleziona il tipo RSA, nessuna scadenza se preferisci e una passphrase robusta), puoi firmare un pacchetto già creato con:
rpm --addsign rpmbuild/RPMS/x86_64/mi-paquete-1.0-1.x86_64.rpm
L'esecuzione di questo comando ti chiederà la password della chiave GPG. Per vedere quali chiavi private rpm ha a disposizione, puoi controllare con gpg -KE se vuoi essere raffinato, in ~/.rpmmacros Puoi regolare la macro %__gpg_sign_cmd per perfezionare i parametri della firma (algoritmo hash, modalità batch, ecc.).
Sulla macchina di destinazione, prima di verificare la firma sarà necessario importare la chiave pubblica dal firmatario. Ciò avviene esportando la chiave dalla sorgente:
gpg2 -a --export Nombre > RPM-GPG-KEY-Nombre
e poi, come root sulla destinazione:
rpm --import RPM-GPG-KEY-Nombre
Da lì puoi controllare la firma di un pacchetto con:
rpm --checksig mi-paquete-1.0-1.x86_64.rpm
Se tutto è corretto, vedrai un messaggio che indica che i digest e le firme sono validi, qualcosa del tipo firme digest OKCiò fornisce una garanzia piuttosto solida di integrità e paternità.
Il processo di apprendimento della creazione, installazione, ispezione, firma e verifica degli RPM trasforma quello che sembra un mondo complesso in qualcosa di abbastanza gestibile: Tu controlli dove vanno i tuoi fileQuali dipendenze dichiari, come automatizzi l'installazione e come esegui il backup di tutto ciò con firme crittograficheCiò consente di integrare i propri pacchetti nello stesso flusso di lavoro di qualsiasi software ufficiale della distribuzione.
Scrittore appassionato del mondo dei byte e della tecnologia in generale. Adoro condividere le mie conoscenze attraverso la scrittura, ed è quello che farò in questo blog, mostrarti tutte le cose più interessanti su gadget, software, hardware, tendenze tecnologiche e altro ancora. Il mio obiettivo è aiutarti a navigare nel mondo digitale in modo semplice e divertente.