Bonjour à tous ! Aujourd’hui le dernier article de cette saison aura pour but de vous montrer comment créer votre propre référentiel APT (aussi appelé PPA (Personal Package Archive)). Comme vous vous en doutez surement, créer votre propre référentiel apt a pour but de distribuer vos programmes/logiciels au format .deb. (Sauf si vous faites adouber par la Debian Familly ou Cannonical (Ubuntu) et que votre soft peut être référencé dans les repository officiel de votre distribution préférée.

Dans le cadre de cet article, je ne montrerais pas comment packager un programme (j’entends par la créer un fichier au format .deb), car j’utiliserai des petits programmes déjà pré packagé connu comme :

  • sl
  • fortune

Pour réaliser mes tests, j’utilise une VM Ubuntu 22.04 pour la construction du repository, ainsi que pour réaliser les différents tests.

Bonne lecture !

I. Conception architecturale de notre référentiel

Voici l’architecture finale de mon référentiel. C’est un simple répertoire qui contient différents fichiers. Tout sera stocké dans un seul dossier afin d’éviter de se compliquer la vie. Les fichiers intéressants avec lesquels nous allons interagir sont les suivants : (soulignés en gras)

ppa
├── archidote.list
├── InRelease
├── LICENSE
├── new-packets-sync-ppa.sh
├── Packages
├── Packages.gz
├── pubkey.gpg
├── README.md
├── Release
├── Release.gpg
├── yyyyyyyyyyyyyyyyyyyyyy.deb
├── yyyyyyyyyyyyyyyyyyyyyy.deb
└── zzzzzzzzzzzzzzzzzzzzzz.deb

Ci-après, voici une description du rôle des fichiers les plus importants :

  • archidote.list : va contenir le lien vers mon repository, distant qui sera hébergé sur une Github.
  • Packages.* (deux fichiers) :
    • Version « plain text »
    • version compressé du fichier
    • Son but est de répertorier tous les fichiers .deb du répertoire courant. Par ailleurs, il stocke un ensemble de métadonnées comme :
      • Le nom du packet .deb (ex : sl)
      • Version du logiciel
      • son architecture
      • etc.
      • Le fichier Packages contient aussi l’empreinte numérique des fichier .deb, afin de garantir leur authenticité. Les algorithmes actuellement utilisés sont :
        • MD5sum (déprécié, gardé pour la rétrocompatibilité)
        • SHA1 (déprécié, gardé pour la retrocompatibilité)
        • SHA256
  • Release* : Il existe aussi deux versions de ce fichier :
    • « Plain Text »
    • une version signée par notre clé publique pour sécuriser le repository et le garantir intègre.
    • Le fichier Release fait le lien avec le fichiers packages, et indique à l’utilisateur l’architecture du référentiel ainsi que des informations concernant l’état du référentiel (update / not yet updated)

ATTENTION Durant le déroulé de ce didacticiel, n’oubliez pas d’adapter les valeurs, noms de variables etc. en fonction de votre contexte. En effet, j’utilise mon propre référentiel à titre d’exemple ! (Attention au copier/coller trop rapide ^^) Les modifications attendues de votre part, seront surlignées en gras dans les blocs de code.

II. Créer un référentiel GitHub avec vos packages deb

Créez un référentiel GitHub. Dans mon cas, je vais le nommer tout bonnement « ppa ».

Puis, vous devez créer une « Github Pages » : Rendez-vous dans les paramètres de votre repository, laissez vous guider par Github :

Grâce à une Github page, vos utilisateurs pourrons accéder plus facilement au référentiel. Cela n’est rien d’autre qu’un site web rattaché à votre repository.

Pour plus d’info : https://docs.github.com/en/pages/getting-started-with-github-pages/about-github-pages

Maintenant, clonez le référentiel et placez tous vos packages Debian à l’intérieur :

git clone [email protected]:archidote/ppa.git
cd ppa/

En guise d’exemple, nous allons télécharger deux petits packages apt « fun », que nous allons redistribuer par la suite sur notre référentiel.

Ils seront installables via la commande apt install <package name> à la fin de l’article pour vous, si-vous n’avez pas fait d’erreur de paramétrage.

wget http://archive.ubuntu.com/ubuntu/pool/universe/f/fortune-mod/fortune-mod_1.99.1-7.1_amd64.deb
wget http://archive.ubuntu.com/ubuntu/pool/universe/s/sl/sl_5.02-1_amd64.deb

III. Créer un trousseau de clé GPG

Pour rappel, voici quelles sont les différences entre OpenPGP, PGP et GPG ?

  • OpenPGP : la norme approuvée par l’IETF (Internet Engineering Task Force) qui décrit toute technologie de chiffrement utilisant des processus interopérables avec PGP.
  • PGP : une solution de chiffrement propriétaire appartenant à Symantec.
  • GPG : C’est une autre solution très répandue qui se base sur la norme OpenPGP en fournissant une interface CLI/GUI permettant aux utilisateurs de chiffrer plus facilement leurs fichiers. Ce n’est en aucun cas une nouvelle méthode de chiffrement.
    • GnuPG est l’implémentation GNU du standard OpenPGP défini dans la RFC 4880, distribuée selon les termes de la licence publique générale GNU. Ce logiciel permet la transmission de messages électroniques signés et chiffrés, garantissant ainsi leur authenticité, intégrité et confidentialité. source : wikipedia.fr

Source : https://www.goanywhere.com/fr/blog/openpgp-pgp-gpg-differences

Dans la perspective de valider l’intégrité de notre repository, nous devons le signer avec une paire de clés PGP :

Installez les deux programmes suivants :

sudo apt install gnupg dpkg-dev

Puis, générez une clé :

gpg --full-gen-key

Suivez les indications suivantes :

Please select what kind of key you want:
   (1) RSA and RSA (default)
   (2) DSA and Elgamal
   (3) DSA (sign only)
   (4) RSA (sign only)
Your selection? 1
RSA keys may be between 1024 and 4096 bits long.
What keysize do you want? (3072) 4096
Please specify how long the key should be valid.
0 = key does not expire
<n> = key expires in n days
<n>w = key expires in n weeks
<n>m = key expires in n months
<n>y = key expires in n years
Key is valid for? (0) 0
Key does not expire at all
Is this correct? (y/N) y

Entrez votre nom et email :

Real name: archidote
Email address: [email protected]
Comment: repository
You selected this USER-ID:
"archidote <[email protected]>"

Change (N)ame, (C)omment, (E)mail or (O)kay/(Q)uit? O

À ce stade, la commande gpg commencera à créer votre clé et vous demandera une « passphrase »pour une protection supplémentaire. Pour améliorer la sécurité de votre référentiel, indiquez une passphrase. Cela n’est pas obligatoire.

We need to generate a lot of random bytes. It is a good idea to perform
some other action (type on the keyboard, move the mouse, utilize the
disks) during the prime generation; this gives the random number
generator a better chance to gain enough entropy.
We need to generate a lot of random bytes. It is a good idea to perform
some other action (type on the keyboard, move the mouse, utilize the
disks) during the prime generation; this gives the random number
generator a better chance to gain enough entropy.
gpg: key B58FBB4C23247554 marked as ultimately trusted
gpg: directory '/home/assafmo/.gnupg/openpgp-revocs.d' created
gpg: revocation certificate stored as '/home/assafmo/.gnupg/openpgp-revocs.d/31EE74534094184D9964EF82B58FBB4C23247554.rev'
public and secret key created and signed.

pub rsa4096 2019-05-01 [SC]
31EE74534094184D9964EF82B58FBB4C23247554
uid My Name <[email protected]>
sub rsa4096 2019-05-01 [E]

Vous pouvez sauvegarder votre clé privée en utilisant la commande suivante (ne jamais versionner/exposer une clé privée dans un répertoire git ou qui n’est pas soumis à des contrôles d’accès, pour des raisons évidentes de sécurité. Je la sauvegarde plus par principe que par utilité ici dans le dossier dans /home/user) :

gpg --export-secret-keys "[email protected]" > ../my-private-key.asc

Essayez de l’importer en utilisant:

gpg --import my-private-key.asc

Si tout fonctionne pour vous, c’est que votre clé a bien été crée correctement.

A. Extraction de notre clé publique (pubkey.gpg) depuis notre trousseau

Créez la clé pubkey.gpg au sein de votre repository :

gpg --armor --export "[email protected]" > pubkey.gpg

Remarque : Le trousseau est référencé par l’adresse e-mail que vous avez saisie à l’étape précédente. C’est son identifiant qui lui est unique.

IV. Création des fichiers requis pour que le repository soit plainement fonctionelle

A. Création des fichiers Packages et Packages.gz

Pour rappel, nous avons deux programmes au format .deb que nous allons distribuer par l’intermédiaire de notre PPA :

  • sl
  • fortune

Nous allons générer le fichier Packages à l’aide de la commande suivante :

dpkg-scanpackages --multiversion . > Packages

Générez une archive .gz de ce fichier via :

gzip -k -f Packages

B. Création des fichiers ReleaseRelease.gpg et InRelease

Depuis le dossier de votre référentiel, exécutez les trois commandes ci-dessous :

apt-ftparchive release . > Release
gpg --default-key "[email protected]" -abs -o - Release > Release.gpg
gpg --default-key "[email protected]" --clearsign -o - Release > InRelease

C. Création du fichier source.list

nano archidote.list
deb [signed-by=/etc/apt/keyrings/archidote-repo.gpg] https://archidote.github.io/ppa ./

Ce fichier sera installé ultérieurement dans le dossier /etc/apt/sources.list.d/ de vos utilisateurs, lorsqu’ils l’importeront. Ce dernier permettra d’indiquer l’adresse distante du repository. Il est important que votre de bien conserver la même nomenclature !

V. On y est presque !

« Stagez », « Validez » et « poussez » vers GitHub les modifications :

git add -A
git commit -m "my ppa repo is now hosted on github"
git push -u origin master

Il faut attendre quelques secondes/minutes, pour que votre « Github Pages » soit mise à jour. En effet, Github utilise une github action pour synchroniser votre repository, avec la « github page ».

Attendez donc quelques instants avant de passer à la suite. (cf la section « Github Actions de votre repository »)

VI. Alors ce repository, il fonctionne ?

Installez le repository distant (sur votre machine, ou sur une autre) afin de tester si votre réferentiel fonctionne correctement.

Importez la clé publique de votre repository :

wget -O- https://archidote.github.io/ppa/pubkey.gpg | gpg --dearmor | sudo tee /etc/apt/keyrings/archidote-repo.gpg

Oui je n’utilise pas apt-key pour ajouter la clé publique au format .gpg car cette commande est considéré comme déprécié depuis début 2022… source : https://www.linuxuprising.com/2021/01/apt-key-is-deprecated-how-to-add.html

Note : si la commande beug avec sudo, éxecutez celle-ci « as root ».

Notre clé a bien été importé dans le dossier /etc/apt/keyrings/

Par la suite, importez le lien de votre repository dans un fichier .list stocké dans : /etc/apt/sources.list.d

sudo curl -s --compressed -o /etc/apt/sources.list.d/archidote.list "https://archidote.github.io/ppa/archidote.list"

Afin de tester si notre repository distant fonctionne bien, nous allons tenter de mettre à jour nos dépendances à l’aide de la commande suivante : apt update

STOP ! Mais avant, vous devez exclure de manière temporaire les repositorys officiels de votre distribution. Pourquoi ? Car les paquet sl et fortune, sont déjà présents par défaut dans les repository officiel d’ubuntu. Afin de s’assurer que tout fonctionne bien, nous souhaitons nous assurer que l’installation de ceux-ci passe par notre repository exclusivement !

cd /etc/apt
sudo mv sources.list sources.list.old
sudo apt update 

Comme vous pouvez le voir, la commande apt a bel et bien pu atteindre notre référentiel distant. De plus, apt a bien détecté que notre référentiel était intègre du fait que nous avons importez la clé publique de celui-ci au préalable. Enfin, comme le montre la capture d’écran ci-dessus, apt détecte nos fichiers :

  • Packages
  • InRelease

Note : apt va mettre en cache ses deux fichiers afin d’optimiser le temps d’exécution de la commande apt update par la suite. Toutefois, si apt détecte que les fichiers ont changés, alors par conséquent, il les mettra à jour.

VII. Est-il possible d’installer un de nos paquets désormais ?

Essayons donc d’installer ce fameux programme sl !

sudo apt install sl

La capture ci-dessous vous montre que le programme sl a bien été téléchargé depuis notre référentiel !

Voilà le résultat de cette commande ^^

Si vous essayez d’installer fortune, vous verrez que vous aurez un problème de dépendances « cassées ». Normal, nous n’avons pas toutes les sous-dépendances associées à ce programme pour que celui-ci fonctionne. (librecode0)

VIII. Comment ajouter de nouveaux packet à notre repository dans le futur ?

Placez simplement vos nouveaux fichier .deb dans votre dossier racine

cd  ~/ppa

Je vais télécharger le programme cowsay au format .deb

wget http://archive.ubuntu.com/ubuntu/pool/universe/c/cowsay/cowsay_3.03+dfsg2-8_all.deb

Puis exécutez le script suivant (Il n’y a rien de compliqué, c’est juste des commandes chainées dans un script ^^ mais prenez le temps de comprendre a minima ce qu’il fait)

nano new-packets-sync-ppa.sh
#!/bin/bash 

email="[email protected]"
date=$(date '+%Y-%m-%d %H:%M:%S')

# Packages & Packages.gz
dpkg-scanpackages --multiversion . > Packages
gzip -k -f Packages

# Release, Release.gpg & InRelease
apt-ftparchive release . > Release
gpg --default-key "$email" -abs -o - Release > Release.gpg
gpg --default-key "$email" --clearsign -o - Release > InRelease

# Commit & push PPA repo to github
git add -A
git commit -m "update : $date"
git push
chmod u+x new-packets-sync-ppa.sh
./new-packets-sync-ppa.sh
Notre repository référence maintenant trois packages !
sudo apt install cowsay 

Encore un article techniquement difficile à rédiger, j’espère qu’il vous aura plu ^^. Il est temps pour moi que je parte en vacances !

On se retrouve fin août !

++

Geoffrey

sources :


Geoffrey Sauvageot-Berland

Ingénieur diplômé par l’état en Informatique et Cybersécurité. Généraliste, à l'origine administrateur systèmes et réseaux, j’occupe actuellement un poste d’auditeur en sécurité offensive. J’apprécie également la programmation/automatisation. Fondateur du blog : "Le Guide du SecOps", anciennement "Le Guide du SysOps"