- Le packaging RPM repose sur des fichiers .spec bien structurés, des dépendances claires et une utilisation appropriée des macros de compilation.
- Des outils comme rpmbuild, mock et rpmlint vous permettent de créer des paquets propres, reproductibles et validés pour différentes distributions et architectures.
- La signature GPG des paquets et des métadonnées, ainsi que l'utilisation de createrepo, sont essentielles pour créer vos propres dépôts fiables et faciles à utiliser.

Si vous travaillez avec des distributions basées sur RPM, vous devrez tôt ou tard apprendre à créer, signer et distribuer correctement les paquets .rpm. Cela est important non seulement pour empaqueter vos propres logiciels, mais aussi pour la maintenance des environnements d'entreprise où le contrôle des installations et de leur provenance est quasiment indispensable.
Dans cet article, nous verrons en détail comment créer des paquets RPM, les signer avec GPG et les publier dans votre propre dépôt . Nous aborderons également l'utilisation de la commande rpm et des gestionnaires de paquets de haut niveau (yum, dnf et zypper). L'objectif est de vous permettre d'acquérir une compréhension globale, depuis la théorie du fichier .spec jusqu'à un flux de travail professionnel utilisant des outils comme mock et createrepo.
Qu'est-ce qu'un paquet RPM et pourquoi est-il encore si important ?
Un paquet RPM est bien plus qu'un simple fichier .rpm : c'est un conteneur renfermant des binaires, des fichiers de configuration, des métadonnées et des scripts d'installation que le gestionnaire RPM sait interpréter. Initialement appelé Red Hat Package Manager, il est aujourd'hui un projet indépendant sous licence GPL, utilisé dans RHEL, Fedora, AlmaLinux, Rocky Linux, openSUSE, ALDOS et même d'autres systèmes comme AIX.
Ce format permet une installation, des mises à jour, une vérification et une désinstallation logicielles cohérentes . Il inclut des informations sur les dépendances, les licences, l'architecture, les fichiers installés, les scripts de pré/post-installation et la vérification d'intégrité à l'aide de signatures GPG.
L'élément central du packaging est le fichier de spécification .spec , qui sert de recette pour rpmbuild : il définit comment décompresser les sources, appliquer les correctifs, compiler, installer dans un arbre temporaire et enfin générer les paquets binaires et sources.
Commande rpm : la base de la gestion des paquets
Bien que nous utilisions aujourd'hui presque systématiquement yum, dnf ou zypper, la commande rpm demeure l'outil de bas niveau pour la gestion des paquets sur les systèmes Red Hat et leurs dérivés. Elle interagit directement avec les fichiers .rpm et les informations locales stockées dans la base de données des paquets.
Avant de l'utiliser, vous devez avoir installé le système RPM ; de plus, dans les distributions Debian, il est conseillé de ne pas mélanger rpm avec dpkg/apt dans le même environnement , car des conflits de dépendances difficiles à résoudre peuvent apparaître.
La structure d'utilisation de base est très simple : paquet rpm.rpm . Plusieurs options permettent de gérer ce format général, en indiquant si vous souhaitez installer, supprimer, interroger ou vérifier des paquets.
Parmi les options les plus courantes de la commande rpm, on trouve : `-i/--install` pour installer, `-e/--erase` pour supprimer, `-U/--upgrade` pour mettre à niveau, `-q/--query` pour interroger et `-V/--verify` pour vérifier l’intégrité . Toutes ces options peuvent être combinées avec des modificateurs tels que `-v` (affichage détaillé) ou `-h` (barre de progression).
Opérations de base avec rpm : installer, interroger et vérifier
Pour installer un paquet manuellement, exécutez simplement `rpm -ivh nom-du-paquet.rpm` , où `-i` lance l'installation, `-v` affiche des informations supplémentaires et `-h` dessine une barre de progression. Cette installation ne résout pas automatiquement les dépendances : si des paquets sont manquants, rpm l'indiquera et vous devrez les installer vous-même.
Si vous possédez déjà une version précédente, vous pouvez la mettre à jour avec `rpm -Uvh package.rpm` . Cette option installe la nouvelle version et supprime l'ancienne. En revanche, `rpm -F` ne mettra à jour le paquet que s'il est déjà installé ; s'il n'est pas présent sur le système, il ne sera pas ajouté.
La désinstallation s'effectue avec la commande `rpm -e nom-du-paquet` . Si d'autres paquets dépendent de ce logiciel, rpm vous avertira et vous devrez résoudre le problème manuellement, soit en supprimant les paquets dépendants, soit en laissant le paquet installé.
Pour examiner les paquets installés sur votre système, utilisez `rpm -qa` afin de lister tous les paquets installés. Les commandes comme `rpm -qi nom-du-paquet` affichent des informations détaillées (version, architecture, date d'installation, résumé, responsable du paquet), tandis que `rpm -ql nom-du-paquet` liste les fichiers installés par un paquet spécifique.
Il est également possible de vérifier les paquets qui n'ont pas encore été installés : rpm -qip fichier.rpm affiche les informations du paquet et rpm -qlp fichier.rpm liste le contenu du fichier .rpm sans avoir besoin de l'installer.
Pour savoir quel paquet est propriétaire d'un fichier spécifique sur le système, utilisez la commande `rpm -qf /chemin/vers/fichier` . C'est très pratique lorsque vous trouvez un fichier dans `/usr/bin` ou `/etc` et que vous souhaitez connaître le paquet qui l'a créé.
Yum, dnf et zypper : gestionnaires de haut niveau pour RPM
Travailler uniquement avec RPM est possible, mais au quotidien, il est bien plus pratique d'utiliser des gestionnaires de paquets qui résolvent automatiquement les dépendances . Les principaux gestionnaires de paquets RPM que nous utilisons sont yum, dnf et zypper.
yum (Yellowdog Updater Modified) a longtemps été l'outil de référence pour Red Hat, CentOS et leurs dérivés. Il permet de rechercher, d'installer, de mettre à jour et de désinstaller des paquets, ainsi que d'effectuer des opérations sur les dépôts, de manière plus conviviale que rpm.
Avec yum, vous pouvez rechercher des logiciels avec yum search PATRON , les installer avec yum install nom-du-package, les mettre à jour avec yum update nom-du-package (ou l'ensemble du système si vous ne spécifiez pas de nom), et les supprimer avec yum remove nom-du-package.
Pour résoudre les dépendances, yum propose la commande `yum whatprovides` , qui indique quel paquet inclut un fichier ou une bibliothèque donné(e). C'est très pratique lorsque rpm vous signale que `libgimpui-2.0.so.0` est manquant(e) et que vous ne savez pas quel paquet installer.
La configuration des dépôts yum se trouve dans le répertoire `/etc/yum.repos.d/` , où chaque fichier `.repo` décrit un dépôt. Vous pouvez lister les dépôts actifs avec la commande `yum repolist all` et les modifier avec l' outil `yum-config-manager` pour activer, désactiver ou ajouter de nouvelles sources de logiciels.
dnf est le successeur moderne de yum dans Fedora et les distributions récentes. Il conserve une syntaxe très similaire (dnf install, dnf search, dnf upgrade, dnf remove) mais avec un moteur plus performant et une meilleure gestion des dépendances. Il inclut également des commandes utiles telles que `dnf repoquery -l package` pour lister les fichiers d'un paquet, ou `dnf provides file` pour savoir qui fournit un fichier spécifique.
Les dépôts DNF utilisent également des fichiers `.repo` dans `/etc/yum.repos.d/ ` et sont gérés par `dnf config-manager`, ce qui permet d'ajouter, d'activer ou de désactiver facilement des dépôts. La syntaxe est très similaire à celle de `yum`, ce qui facilite la migration d'un outil à l'autre.
zypper est l'outil équivalent sous SUSE et openSUSE. Il permet d'actualiser les index de paquets avec `zypper refresh`, de rechercher avec `zypper search`, d'installer avec `zypper install` et de mettre à jour avec `zypper update` , comme avec les autres gestionnaires de paquets.
L'un des avantages de zypper est sa capacité à installer directement des fichiers .rpm locaux (`zypper in /chemin/vers/fichier.rpm`) et à résoudre les dépendances en récupérant les paquets depuis les dépôts configurés. De plus, des commandes comme `zypper se -i` affichent uniquement les paquets installés, tandis que `zypper info package` fournit des informations détaillées sur les métadonnées, l'état, le dépôt source et la description.
Pour gérer les dépôts, utilisez `zypper repos` pour les lister, et `zypper modifyrepo` avec `-eo -d` pour activer ou désactiver chaque dépôt, en contrôlant également leur actualisation automatique avec `-fo -F`. La structure interne des fichiers `.repos` est très similaire à celle de yum/dnf.
Préparer l'environnement de construction du package RPM
Avant de créer votre premier fichier .rpm, vous avez besoin d'un environnement bien organisé et de quelques outils préinstallés. Il est essentiel que rpm-build, rpm-sign, le compilateur et les macros de la distribution soient correctement configurés.
Sur les systèmes comme ALDOS qui utilisent yum, vous pouvez installer tous les composants de base avec `yum -y install rpm-build rpm-sign gnupg2 gcc make aldos-rpm-macros` . Sur Fedora, RHEL, AlmaLinux ou Rocky Linux, la procédure est similaire avec `dnf` pour installer rpm-build, rpm-sign, gnupg2, gcc, make et redhat-rpm-macros.
Pour une expérience plus complète, il est conseillé d'ajouter des paquets tels que cmake-rpm-macros, python-srpm-macros, meson, cmake, rpmlint, desktop-file-utils et rpmdevtools . En particulier, rpmlint est très utile pour détecter les erreurs courantes dans les fichiers .spec et les paquets générés.
L'arborescence de travail standard est créée par l' utilitaire rpmdev-setuptree (inclus dans rpmdevtools), qui monte l'arborescence ~/rpmbuild avec les sous-répertoires BUILD, BUILDROOT, RPMS, SOURCES, SPECS et SRPMS. Sous Debian, vous devrez générer cette arborescence manuellement avec la commande : mkdir -p ~/rpmbuild/{BUILD,BUILDROOT,RPMS,SOURCES,SPECS,SRPMS}.
Il est recommandé de toujours placer le code source, les correctifs et les ressources dans le répertoire SOURCES/ et les fichiers .spec dans le répertoire SPECS/ . Les paquets binaires finaux apparaîtront dans les répertoires RPMS/ et les fichiers .src.rpm dans le répertoire SRPMS/ une fois la compilation terminée.
Anatomie d'un fichier .spec moderne
Le fichier .spec est un script déclaratif comportant plusieurs sections que rpmbuild exécute séquentiellement. La première partie est l'en-tête, où vous définissez les métadonnées de base du paquet : nom, version, publication et résumé , ainsi que les licences et les sources.
Par exemple, un en-tête classique comprendrait des champs tels que la licence avec les identifiants SPDX, l'URL du projet et Source0 pointant vers l' archive officielle du code source. Il est conseillé d'utiliser des macros comme %{name} et %{version} pour faciliter la maintenance lors des changements de version.
Un autre aspect important est la gestion de l'architecture . Si votre logiciel n'est compatible qu'avec les architectures x86_64 et arm64, vous pouvez le limiter avec ExclusiveArch: x86_64 arm64 ou exclure les architectures 32 bits avec des directives telles que ExcludeArch: %{ix86}.
Les correctifs sont déclarés à l'aide des directives Patch0, Patch1, etc., pointant vers des fichiers situés dans SOURCES/. Ces correctifs seront appliqués ultérieurement dans la section %prep, où %autosetup -p1 est couramment utilisé de nos jours pour décompresser les sources et appliquer automatiquement les correctifs.
Dans la section des dépendances, BuildRequires liste tous les paquets nécessaires à la compilation du projet : compilateurs, bibliothèques de développement, macros spécifiques, outils de construction comme Meson ou CMake, et utilitaires de validation. Omettre un seul de ces paquets entraînera l’échec de la compilation.
Les dépendances d'exécution sont indiquées par Requires, Recommends et Suggests. Requires spécifie les dépendances strictement nécessaires au fonctionnement du paquet, tandis que Recommends/Suggests offrent plus de flexibilité et requièrent RPM 4.12 ou une version ultérieure. Pour assurer la compatibilité avec des systèmes plus anciens comme ALDOS (RPM 4.11.3), il est nécessaire d'utiliser des instructions conditionnelles dans le fichier .spec afin d'éviter toute erreur de compilation.
Vous pouvez également définir des relations entre les paquets à l'aide des propriétés `Conflicts`, `Obsoletes` et `Provides` . `Conflicts` empêche l'installation simultanée de deux paquets incompatibles ; `Obsoletes` indique qu'un paquet en remplace un autre (utile pour renommer) ; `Provides` permet de déclarer des capacités virtuelles afin que d'autres paquets puissent dépendre de fonctionnalités génériques, et non d'un nom spécifique.
La section %description contient une description détaillée du paquet . Il est recommandé de rédiger des lignes courtes pour une lisibilité optimale dans les terminaux. Il est possible de définir des descriptions en plusieurs langues, par exemple en utilisant %description -l pour l'espagnol.
Systèmes de construction : Meson, Autotools et CMake
Dans les fichiers .spec modernes, il est courant d'utiliser des macros spécifiques pour intégrer Meson, Autotools ou CMake sans avoir à écrire manuellement de longues commandes de compilation. Cela simplifie considérablement les sections %build, %install et %check.
Avec Meson, système recommandé pour les nouveaux projets, vous pouvez utiliser %meson pour la configuration, %meson_build pour la compilation et %meson_install pour l'installation dans le répertoire BUILDROOT. Les options sont transmises directement à Meson (par exemple, -Dopcion=true, -Ddocs=enabled/disabled).
Pour les projets plus anciens basés sur Autotools, des macros telles que %configure (qui lance le script de configuration avec les chemins corrects) et %make_build / %make_install sont utilisées , qui sont responsables de la compilation et de l'installation tout en respectant l'environnement de construction rpmbuild.
CMake, très répandu dans les projets C++ et de bureau, utilise des macros équivalentes : %cmake, %cmake_build et %cmake_install . Ainsi, le fichier .spec reste clair et lisible, et il n’est pas nécessaire de réécrire de longues commandes dans chaque paquet.
De plus, il existe des macros d'assistance comme %bcond_with/%bcond_without pour définir des options de compilation facultatives (par exemple, la documentation) qui sont activées ou désactivées au moment de la compilation avec des indicateurs comme –with docs.
Sous-packages, liste des fichiers et macros utiles
Dans de nombreux cas, il est utile de diviser un grand projet en plusieurs paquets : bibliothèques, en-têtes de développement, documentation, utilitaires en ligne de commande , etc. Cela se fait avec la directive %package, qui définit des sous-paquets avec leur propre nom, résumé et description.
Chaque sous-paquet doit avoir sa propre section %description et, surtout, sa propre section %files, où vous listez précisément les fichiers qui le composent . Tout élément non listé dans %files ne sera pas inclus dans le paquet RPM final.
Dans %files, des macros spéciales sont utilisées telles que %license pour marquer les fichiers de licence, %doc pour la documentation, %config(noreplace) pour les fichiers de configuration , %dir pour inclure les répertoires vides, %ghost pour les fichiers créés au moment de l'exécution et %attr pour définir les permissions, le propriétaire et le groupe.
En suivant ce schéma, vous pouvez avoir un paquet principal contenant les exécutables et les fichiers de bureau, un sous-paquet appelé libproyecto contenant la bibliothèque partagée, et un autre appelé libproyecto-devel contenant les en-têtes et les fichiers .pc issus de pkg-config. Cela permet à l'utilisateur d'installer uniquement ce dont il a réellement besoin.
Les scripts de maintenance tels que %post, %postun ou %posttrans permettent d'exécuter des commandes après l'installation ou la désinstallation, comme la mise à jour des caches d'icônes avec gtk-update-icon-cache ou l'actualisation de la table des bibliothèques avec ldconfig . Sur les systèmes modernes, certaines de ces étapes sont automatisées et sont donc souvent intégrées à des instructions conditionnelles afin d'éviter les tâches redondantes.
Flux de travail de construction avec rpmbuild et mock
Une fois le fichier .spec et le code source en place, le flux de travail de base avec rpmbuild est simple : rpmbuild -ba fichier.spec génère le paquet source et les binaires en une seule étape. Mais vous pouvez également exécuter des phases partielles.
Par exemple, `rpmbuild -bp fichier.spec` effectue la préparation (`%prep`) et laisse les sources décompressées et patchées dans `BUILD/`, ce qui est utile pour le débogage des problèmes liés aux correctifs. `rpmbuild -bi` compile et installe dans `BUILDROOT` sans créer les fichiers `.rpm`, idéal pour vérifier la phase d'installation.
Pour générer uniquement le paquet source .src.rpm, utilisez rpmbuild -bs fichier.spec , tandis que -ba est l'option que la plupart des responsables de paquets utilisent dans l'intégration continue ou les scripts, car elle produit tout en une seule fois.
Cependant, compiler sur son propre système présente un risque évident : celui d’ introduire des dépendances cachées, car votre machine possède des paquets supplémentaires non déclarés dans les dépendances de compilation. Pour éviter cela, on utilise mock, un outil qui crée des environnements de compilation propres au sein de chroots.
Avec `mock`, vous définissez des profils pour chaque distribution/architecture (par exemple, aldos-14-x86_64) et exécutez des commandes comme `mock -r profile --rebuild package.src.rpm` . Cela génère les RPM dans `/var/lib/mock/profile/result/`, en garantissant que seuls les paquets déclarés dans le fichier `.spec` sont utilisés.
Dans les flux de travail avancés, on utilise souvent des scripts Bash pour vider le cache de simulation, compiler pour différentes architectures, supprimer les informations de débogage inutiles, déplacer les paquets vers un dépôt local et régénérer les métadonnées avec `createrepo` . Il est essentiel de ne jamais laisser de paquets importants dans `/var/lib/mock/*/result`, car ce répertoire est nettoyé lors des exécutions suivantes.
Créez et signez votre propre dépôt RPM
Lorsque vous accumulez plusieurs de vos propres paquets, la solution la plus pratique consiste à configurer un dépôt RPM accessible via HTTP/HTTPS et à l'utiliser depuis vos machines à l'aide de yum ou dnf, comme n'importe quel dépôt officiel.
Une méthode pratique consiste à organiser votre machine de travail selon une structure de répertoires similaire à celle des principales distributions, par exemple /home/user/devel/repo/Fedora/15/{i386,x86_64}/{os,debug} et Fedora/15/source/SRPMS . Copiez ensuite les paquets binaires et les fichiers src.rpm dans les dossiers correspondants.
L'étape suivante consiste à générer une clé GPG spécifique pour signer les paquets et les métadonnées du dépôt . À l'aide de la commande `gpg --gen-key`, vous créez une clé RSA de 4096 bits, vous lui attribuez un nom facilement identifiable pour votre dépôt, puis vous exportez la clé publique dans le fichier `RPM-GPG-KEY-myrepo` situé dans le dépôt lui-même.
Dans votre répertoire utilisateur, ajoutez les lignes `%_signature gpg` et `%_gpg_name nom-de-la-clé` à `~/.rpmmacros` afin que rpm sache quelle clé utiliser pour la signature. Vous pourrez ensuite signer tous les fichiers `.rpm` présents dans votre arborescence à l'aide de la commande `find` suivie de `rpm --resign`.
Pour générer les informations du dépôt , on utilise `createrepo` ou `createrepo_c` . Il est courant d'automatiser ce processus avec un script qui parcourt toutes les architectures, exécute `createrepo -v` sur chacune d'elles, puis recherche tous les fichiers `repomd.xml` résultants pour les signer avec `gpg --armor --detach-sign`, garantissant ainsi l'intégrité des métadonnées.
Une fois les métadonnées générées, vous répliquez le contenu sur le serveur web (un VPS ou le serveur interne de l'entreprise) avec rsync -avz --delete via SSH, et vous pouvez éventuellement programmer une tâche cron pour que tout reste synchronisé avec la machine de compilation de temps en temps.
Côté client, il suffit de créer un fichier `/etc/yum.repos.d/ myrepo.repo` contenant les sections `<package_name>` et `<package_name>`, pointant respectivement vers les URL de base où sont hébergés les paquets et la clé publique GPG. Les commandes `enabled` et `gpgcheck` déterminent si le dépôt est actif et si la vérification de signature est requise.
Exemple pratique : un simple RPM (polices)
Pour illustrer ces concepts, un exemple simple consiste à empaqueter une collection de polices open source comme Vremena dans un fichier .rpm ultra-basique, adapté aux distributions Red Hat et dérivées, bien que pouvant également être compilé à partir de Debian.
Sous Debian, vous installerez les outils minimaux avec `apt -y install rpm rpm2cpio` et créerez manuellement l'arborescence `~/rpmbuild`. Si vous utilisez des paquets .deb, consultez la documentation sur la création et la signature de paquets .deb . Sous Red Hat, vous installerez également `rpmdevtools` et exécuterez `rpmdev-setuptree` pour générer la structure.
Ensuite, vous devez créer un fichier .spec nommé vremena-font.spec, soit en le partant de zéro sous Debian, soit en utilisant rpmdev-newspec rpmbuild/SPECS/vremena-font.spec sous Red Hat pour générer un modèle. Dans ce fichier spec, vous définissez le nom, la version, la publication, le résumé, la licence et une section %description qui décrit les polices incluses dans le paquet.
Dans %install, vous devez créer le répertoire de destination dans %{buildroot}, par exemple avec la commande `mkdir -p %{buildroot}/usr/share/fonts/vremena-serif/` , et y copier les fichiers .otf. Il est important d'utiliser des chemins relatifs à %{buildroot} car rpmbuild s'exécute dans un environnement simulé (chroot) avant la création du paquet.
La section %post exécute la commande fc-cache /usr/share/fonts/ afin que le système régénère le cache des polices et que les nouvelles polices soient immédiatement disponibles. Dans %files, vous listez les fichiers .otf installés, et dans %changelog, vous documentez la création de la première version du paquet.
Une fois tous les éléments prêts, la commande `rpmbuild -ba rpmbuild/SPECS/vremena-font.spec` créera le fichier .rpm dans le répertoire RPMS/x86_64 ou l'architecture correspondante. Sur un système Red Hat, l'installation avec `rpm -i vremena-font-0.1-1.x86_64.rpm` permettra d'obtenir des polices fonctionnelles.
Signature et vérification des paquets avec GnuPG
Dans un contexte professionnel, il est essentiel que les paquets soient signés cryptographiquement avec GPG afin de garantir leur intégrité et leur provenance de la source attendue. De plus, de nombreux dépôts sont configurés avec `gpgcheck=1` pour rejeter les paquets sans signature valide.
Une fois votre clé GPG prête et configurée dans ~/.rpmmacros, vous pouvez signer tous les fichiers .rpm générés avec la commande rpm --addsign ~/rpmbuild/RPMS/*/*.rpm ~/rpmbuild/SRPMS/*.rpm . Cela ajoute la signature à chaque paquet à l'aide de la clé privée.
Les clients peuvent vérifier l'authenticité avec la commande `rpm -K package.rpm` , qui indique si la signature est valide et si l'intégrité du fichier est préservée. Si la clé publique n'est pas importée dans le système, elle doit d'abord être ajoutée à l'aide de `gpg --import` ou du mécanisme équivalent propre à la distribution.
Dans les flux de travail où un dépôt est publié, la clé publique est généralement distribuée sous forme de fichier RPM-GPG-KEY accessible via HTTP et référencée dans les fichiers .repo afin que les clients puissent facilement importer la clé avant de consommer le dépôt.
En bref, la maîtrise de la création de paquets RPM, de la signature GPG, des builds isolés avec mock et de la mise en place de vos propres dépôts vous offre un contrôle énorme sur la manière dont les logiciels sont installés et mis à jour sur vos systèmes Linux , transformant ce qui était autrefois un fouillis chaotique de binaires disparates en un flux ordonné, reproductible et sécurisé.
Écrivain passionné par le monde des octets et de la technologie en général. J'aime partager mes connaissances à travers l'écriture, et c'est ce que je vais faire dans ce blog, vous montrer toutes les choses les plus intéressantes sur les gadgets, les logiciels, le matériel, les tendances technologiques et plus encore. Mon objectif est de vous aider à naviguer dans le monde numérique de manière simple et divertissante.
