Fabrique de dépôts APT pour les paquets Epiconcept sur Debian/Ubuntu
La distribution Debian
de Linux
regroupe ses logiciels installés sous forme de paquets (packages
) gérés par la commande spécifique apt
et ses commandes annexes.
Une des fonctions de apt
est de télécharger les paquets sous forme de fichiers .deb
obtenus depuis des serveurs Web spécialisés appelés des serveurs de dépôts (repositories
).
Chaque dépôt regroupe l'ensemble des paquets d'un fournisseur logiciel pour les différentes versions (releases
) de la distribution Debian
de Linux
.
Ainsi, l'organisation qui développe la distribution Debian
de Linux
gère un dépot accessible sur debian.org.
Malheureusement, la communauté Debian appelle ces différentes versions de la distribution Debian
des distributions, ce qui crée la confusion. Nous appelerons donc ci-après variantes les différentes distributions de Linux
comme Debian
ou Ubuntu
.
La variante Ubuntu
de Linux
étant un sur-ensemble de la variante Debian
, beaucoup de paquets préparés pour une distribution Debian
donnée peuvent être installés sur les distributions de la variante Ubuntu
de Linux
qui lui correspondent.
Il y a en effet plusieurs distributions de la variante Ubuntu
pour une distribution donnée de la variante Debian
.
La particularité de notre fabrique est qu'elle ne gère pas un seul dépôt APT mais plusieurs :
- un dépôt de pré-production
prep
, dont les paquets viennent desources/
(voir ci-dessous) - un dépôt de production standard
prod
, dont les paquets viennent deprep/
(idem) - un nombre quelconque de dépôts de production spécifiques
prod-<tag>
(par exempleprod-mdmdpi
)
L'essentiel de la fabrique est contenu dans trois scripts : deux scripts principaux prep.sh
et prod.sh
et un script auxiliaire update.sh
.
Ces scripts devront être installés sur le serveur de dépôts avec quelques fichiers auxiliaires, comme décrit ci-dessous à la section 2.
La construction et la mise à jour des dépôts APT nécéssitent un jeu de clés GPG qui doivent avoir été générées préalablement au moyen du script gpg/genkey.sh
, préférablement ailleurs que sur le serveur de dépôts APT.
La fabrique se compose principalement des fichiers suivants du répertoire site
de ce dépôt git :
config/relconf
config/dists
config/component
config/obsolete
gpg/key.conf
gpg/key.gpg (généré par gpg/genkey.sh)
prep.sh
prod.sh
update.sh
et elle exploite l'arborescence suivante:
├── config
│ ├── relconf
│ ├── dists
│ ├── component
│ ├── obsolete
│ ├── prod.list (généré par prod.sh)
│ └── prod-<tag>.list (générés par prod.sh)
│
├── gpg
│ ├── key.conf
│ └── key.gpg (généré par genkey.sh)
│
├── prep.sh
├── prod.sh
├── update.sh
│
├── sources (exemple d'arborescence, à fournir)
│ ├── builds
│ │ └── *.deb
│ ├── travis
│ │ └── *.deb
│ └── epibin
│ └── *.deb
│
├── docroot (généré par les scripts)
│ │
│ ├── prep (LE dépôt de pré-production)
│ │ ├── debs
│ │ │ └── ... (paquets)
│ │ ├── dists
│ │ │ └── ... (distributions Debian/Ubuntu)
│ │ └── key.gpg
│ │
│ ├── prod (LE dépôt de production optionnel)
│ │ ├── debs
│ │ │ └── ... (paquets)
│ │ ├── dists
│ │ │ └── ... (distributions Debian/Ubuntu)
│ │ └── key.gpg
│ │
│ └── prod-<tag> (Un autre dépôt de production optionnel)
│ ├── debs
│ │ └── ... (paquets)
│ ├── dists
│ │ └── ... (distributions Debian/Ubuntu)
│ └── key.gpg
│
└── tmp (généré par les scripts)
└── ... (fichiers temporaires normalement absents hors exécution)
-
Le répertoire
config
est utilisé surtout par le script auxiliaireupdate.sh
pour la génération (construction et mise à jour) d'un dépôt. L'utilisateur de la fabrique doit placer ce répertoire sur le serveur (sans le scriptubudeb
qui n'est qu'une aide pour la mise à jour du fichierdists
). -
Le répertoire
gpg
contient le scriptgenkey.sh
de génération du jeu de clés GPG et surtout le fichier de configurationkey.conf
qui contient la passphrase du jeu de clés GPG. Lors de l'exécution degenkey.sh
, trois fichiers sont créés : le jeu completmaster.gpg
, la sous-clé secrète de signaturesigning.gpg
et la clé publiquekey.gpg
. Les fichierskey.conf
etkey.gpg
du répertoiregpg
doivent se trouver sur le serveur de dépôts dansgpg
. La clésigning.gpg
doit aussi être installée sur le serveur pargpg --import signing.gpg
, mais n'est pas utile dans le répertoiregpg
. -
Les scripts
prep.sh
,prod.sh
etupdate.sh
constituent comme on vu la fabrique proprement dite, dont l'utilisation est détaillée dans la section 3 ci-dessous. Seuls les scriptsprep.sh
etprod.sh
sont appelés directement, le scriptupdate.sh
étant seulement appelé par eux pour mettre à jour le répertoiredocroot
. Ces trois scripts doivent donc être placés à coté de (dans le même sur-répertoire que)config/
etgpg/
ainsi quesources/
décrit ci-après. -
Le répertoire
sources
contient les paquets Debian d'origine, rangés éventuellement selon leurs différentes provenances (pour nos dépots: serveur de build, Travis CI et paquets binaires Epiconcept). Il est de la responsabilité de l'utilisateur de la fabrique de fournir le répertoiresources
peuplé avec les répertoires et les fichiers.deb
de son choix. -
Le répertoire
docroot
est destiné, comme son nom l'indique, à être la racine du serveur web de paquets. Il contient les répertoiresprep
etprod
, pour le dépôt de pré-production et chacun des dépôts de production. La raison d'être de la fabrique étant de générer et de mettre à jour ce répertoiredocroot
et ses contenus, l'utilisateur n'a pas à y intervenir ni même à créer le répertoire. -
Le répertoire
tmp
est créé si nécessaire et doit normalement être vide après l'exécution des scripts. L'utilisateur n'a donc pas à s'en préoccuper non plus. -
Enfin, le script
update.sh
alimente un log de mise-à-jour qui signale la date des updates et le détail de leur traitement (surtout les anomalies). Ce log de mise-à-jour, désigné par la variable $Log dansprep.sh
etprod.sh
, est placé dans la pratique dans/var/log/epiconcept/
.
Le script update.sh
utilisant les commandes dpkg-scanpackages
et apt-ftparchive
, il faut avoir respectivement installé (sudo apt install ...
) sur le serveur de dépôts les packages Debian :
- dpkg-dev
- apt-utils
pour que les scripts fonctionnent correctement.
Avant de pouvoir utiliser les scripts prep.sh
et prod.sh
, il faut d'abord générer un jeu de clés GPG. Cette génération se fait par le script gpg/genkey.sh
, qui utilise le fichier de configuration gpg/key.conf
.
Avant la génération proprement dite (de préférence ailleurs que sur le serveur de dépôts APT lui-même), il convient de passer en revue et de modifier s'il y a lieu les 4 dernières lignes du fichier key.conf
:
Name-Real:
Epiconcept Infrastructure HébergementName-Email:
infra@epiconcept.frExpire-Date:
3yPassphrase:
And there were gardens bright with sinuous rills (tirée du poème "Xanadu" de Coleridge)
Il faut AU MINIMUM changer cette passphrase, du fait qu'elle est ici exposée publiquement, avant de générer le jeu de clés, par exemple avec les commandes suivantes :
cd gpg
vi key.conf
./genkey.sh
Si le script genkey.sh semble alors se bloquer, c'est qu'il attend de "l'entropie système", qu'il est possible de lui fournir :
- en tapant sur un autre terminal une commande du type de celle affichée par
genkey.sh
- ou en installant préalablement le package Debian
rng-tools
sur le système de génération des clés
Quand le script se termine, le répertoire contient trois clés :
- une clé principale
master.gpg
, qu'il est impératif de sauvergarder et qu'il vaut mieux ensuite supprimer si elle est générée sur le serveur de dépôts lui-même - une sous-clé secrète
signing.gpg
, qui servira à la signature des fichiersRelease
des distributions dans les dépôts et qui doit être installée sur le serveur de dépôts APT par :gpg --import signing.gpg
, en tant qu'utilisateur qui exécutera les scriptsprep.sh
etprod.sh
- une clé publique
key.gpg
qui sera intégrée aux dépôts APT et installée sur les clients APT par :apt-key add key.gpg
ou par la copie directement dans/etc/apt/trusted.gpg.d/
pour les dernières versions deDebian
(voir la section 6).
Sur le serveur de dépôts, après installation de signing.gpg
, seuls les fichiers key.conf
et key.gpg
sont nécessaires dans le répertoire gpg
.
Enfin, si ce serveur de dépôts est bien, comme recommandé, différent de celui où a été généré le jeu de clés GPG, il faut placer à la fin du fichier $HOME/.gnupg/gpg.conf
de l'utilisateur qui exécutera les scripts les 2 lignes suivantes :
cert-digest-algo SHA256
digest-algo SHA256
Il faut copier dans un répertoire choisi sur le serveur de dépôts les éléments suivants du répertoire site/
de ce dépôt git :
- le répertoire
config/
(sans le scriptubudeb
) - le répertoire
gpg/
(seulement les fichierskey.conf
,key.gpg
etsigning.gpg
(à supprimer après import)) - les scripts
prep.sh
,prod.sh
etupdate.sh
Il faut créer et peupler de paquets .deb
le répertoire sources/
dans le répertoire choisi du serveur de dépôts.
Cela peut se faire en créant dans sources/
des liens symboliques vers différents répertoires contenant des paquets à condition qu'ils soient dans le même système de fichiers que docroot
.
Elle se fait par le script prep.sh
. Quatre commandes sont disponibles :
./prep.sh update
-
Le script
prep.sh
peuple d'abord le répertoiredocroot/prep/debs
(créé au besoin) :debs ├── any │ ├── all │ │ └── *.deb │ └── amd64 │ └── *.deb ├── deb8 │ └── amd64 │ └── *.deb └── deb9 └── amd64 └── *.deb
en normalisant au passage les noms des paquets sous la forme :
<nom-paquet>_<version-paquet>_<archi-paquet>.deb
obtenue en extrayant <nom-paquet>, <version-paquet> et <archi-paquet> de chaque paquet lui-même et en éliminant les paquets obsolètes déclarés dans
config/obsolete
. Les paquets dont le nom danssources/
n'est pas normalisé sont signalés, avec leur nom normalisé, dans le log de mise-à-jour. -
Puis
prep.sh
invoque le script auxiliaireupdate.sh
qui peuple le répertoiredocroot/prep/dists
selon le contenu du fichierconfig/dists
dont voici un extrait :... saucy deb7 13.10 trusty deb8 14.04 LTS utopic deb8 14.10 vivid deb8 15.04 jessie deb8 15.04 Deb wily deb8 15.10 xenial deb9 16.04 LTS ...
-
Pour le premier champ de chaque ligne du fichier
config/dists
,update.sh
crée un répertoire de distribution portant ce nom et ayant la structure :<nom-distrib> ├── main │ ├── binary-all │ │ ├── Packages.gz │ │ └── Packages │ └── binary-amd64 │ ├── Packages.gz │ └── Packages ├── Release └── Release.gpg
-
Le deuxième champ de chaque ligne du fichier
config/dist
indique l'étiquette (chaine de caractères) à rechercher dans la version de chaque paquet pour que, si elle s'y trouve, ce paquet ne soit inclus que dans la distribution indiquée dans le premier champ. Par exemple, les binaires PHP comprenant l'étiquettedeb8
ne sont inclus que dans les distributions deconfig/dists
dont le deuxième champ estdeb8
. -
Le reste de chaque ligne du fichier
config/dist
est un commentaire (ignoré). -
Toute ligne du fichier
config/dist
commençant par un#
, ou vide, est également un commentaire.
-
-
Les architectures
all
etamd64
qui apparaissent en suffixes des répertoiresbinary-all
etbinary-amd64
sont, elles, extraites automatiquement des packages eux-mêmes. Si l'on introduisait par exemple danssources
des paquets pour l'architecturearmh
, celle ci apparaitrait automatiquement dans un répertoirebinary-armh
de l'arborescence de chaque distribution dedist
, à condition toutefois que la sélection ci-dessus par le deuxième champ deconfig/dists
le permette. -
Il est aussi possible de changer le nom du composant
main
en modifiant le contenu du fichierconfig/component
. -
Enfin, la commande
prep.sh update
supprime automatiquement des dépôtsprep
etprod
les paquets qui auraient été supprimés de l'arborescencesources/
depuis la dernière invocation deprep.sh update
.
./prep.sh list
./prep.sh ver <nom-fichier-paquet>
ou
./prep.sh ver <nom-dpkg-paquet>
Le nom-dpkg d'un paquet est le nom du paquet au sens de l'utilitaire dpkg
, c'est à dire jusqu'au premier caractère _
.
./prep.sh ver
./prep.sh ls [ <filtre> ]
L'argument optionnel est une expression régulière étendue (de type egrep
) permettant de ne sélectionner que les paquets de pré-production qui lui correspondent.
Elle se fait par le script prod.sh
. Quatre commandes sont également disponibles :
./prod.sh add <nom-fichier-paquet> [ <nom-fichier-paquet> ... ]
./prod.sh del <nom-fichier-paquet> [ <nom-fichier-paquet> ... ]
./prod.sh ver <nom-fichier-paquet>
ou
./prod.sh ver <nom-dpkg-paquet>
Comme pour prep.sh
, le nom-dpkg d'un paquet est le nom du paquet au sens de l'utilitaire dpkg
, c'est à dire jusqu'au premier caractère _
.
./prod.sh ver
(de manière identique à prep.sh ver ...
).
./prod.sh ls [ <filtre> ]
(de manière identique à prep.sh ls ...
).
La commande prod.sh
accepte un argument -t <tag>
optionnel.
Si cet argument est utilisé, toutes les commandes de prod.sh
s'appliquent à un dépôt prod-<tag>
et non plus simplement prod
.
La liste des paquets de production est également sauvegardée dans config/prod-<tag>.list
et non plus simplement config/prod.list
.
Exemples avec <tag>
= mdmdpi
./prod.sh -t mdmdpi add <nom-fichier-paquet> [ <nom-fichier-paquet> ... ]
./prod.sh -t mdmdpi ver <nom-dpkg-paquet>
Si la variable d'environnement APT_PROD_TAG
est déclarée, sa valeur remplit la même fonction que -t <tag>
.
Exemple:
export APT_PROD_TAG=mdmdpi
Si la variable APT_PROD_TAG
est déclarée et que le l'argument -t <tag>
est utilisé, c'est ce dernier qui prévaut.
Pour pouvoir reproduire le contenu de la fabrique, il faut sauvegarder le répertoire config
et l'arborescence sources/
.
Le répertoire gpg
a normalement été sauvegardé en entier après la génération du jeu de clés GPG.
Après avoir installé la clé GPG de signature par :
gpg --import gpg/signing.gpg
rm gpg/signing.gpg
et avoir restauré les éléments (sauvegardés comme indiqué ci-dessus) sur le serveur désiré, il suffit d'exécuter :
./prep.sh update
./prod.sh add `cat config/prod.list`
pour restaurer complètement les dépôts APT prep
et prod
.
La fabrique de dépôts utilise des liens UNIX durs (et non symboliques) pour relier entre eux les fichiers de sources/
, de docroot/prep/debs/
et de docroot/prod*/debs/
.
Pour diverses raisons, il peut arriver que ces liens soient anormalement cassés.
Les scripts de la fabrique ne fonctionneraient alors plus correctement.
Mais la méthode utilisée pour la restauration s'applique. Il suffit de faire :
rm -r docroot
./prep.sh update
for list in config/prod*.list
do
tag=$(expr $(basename "$list" .list) : 'prod-\{0,1\}\(.*\)$')
test "$tag" && arg="-t $tag" || arg=
./prod.sh $arg add `cat $list`
done
pour rétablir le fonctionnement normal.
Ce dépôt git contient également un répertoire test
permettant de créer sous docker
une image Debian bookworm
(ou la version de Debian indiquée par la variable d'environnement DebVer) de tests de la commande apt
.
Pour créer l'image, lancer la commande test/bake
, qui affiche à la fin la commande d'invocation du conteneur de l'image. Cette commande est également copiée dans logs/run-${DebVer:-bookworm}.sh
.
Pour créer une image docker
sous une autre version de Debian, il faut déclarer DebVer devant la commande test/bake
, par exemple :
DebVer=jessie test/bake
Attention, la validité de la version de Debian n'est pas vérifiée, mais test/bake
s'arrêtera en cas d'erreur de build de l'image docker
.
Le conteneur partage le répertoire test/share
, vu en interne comme /opt/share
, et lance automatiquement le script test/cfg
, présent dans test/share
par le biais d'un hardlink.
Ce script utilise par défaut les dépôts Epiconcept https://apt.epiconcept.fr/prep
(ou .../prod
), mais il est possible de tester un dépôt local à la machine où est installé docker
de la façon suivante :
dpkg -l apache2 >/dev/null || sudo apt-get install apache2
sudo ln -s `realpath site/docroot` /var/www/html/apt
>test/share/local
test/bake
Enfin ce dépôt git contient aussi le script test/bin/debinfo
qui n'est qu'une étude, un proof of concept pour la fabrique de dépôts APT.
Il n'est utilisé que dans l'image de test pour lister les packages à la fin de test/cfg
.
Il s'agit de la configuration nécessaire dans /etc/apt
pour utliser les dépôts de notre fabrique.
-
Import de la clé
- Pour les versions de Debian jusqu'à
buster
(Debian 10) incluse :curl -u username:password https://apt.epiconcept.fr/prep/key.gpg | sudo apt-key add -
- Pour les versions
bullseye
(Debian 11) et supérieurescurl -u username:password https://apt.epiconcept.fr/prep/key.gpg | sudo sh -c "cat >/etc/apt/trusted.gpg.d/epiconcept.asc"
L'authentification
-u username:passwd
n'est pas nécessaire au sein de l'infrastructure d'Epiconcept. - Pour les versions de Debian jusqu'à
-
Configuration du dépôt dans
/etc/apt/sources.list.d
Ci-après,<repo>
désigne le nom du dépôt (prep
,prod
ouprod-<tag>
).- Pour les versions jusqu'à Debian 11 incluse, dans
epiconcept.list
:ce qui peut se faire avec la commande :deb [arch=amd64,all] https://apt.epiconcept.fr/<repo>/ <release-debian> main
echo "deb [arch=amd64,all] https://apt.epiconcept.fr/<repo>/ $(lsb_release -sc) main" > /etc/apt/sources.list.d/epiconcept.list
- Pour les versions Debian 12 et supérieures, dans
epiconcept.sources
:ce qui peut se faire avec la commandeTypes: deb URIs: https://apt.epiconcept.fr/<repo> Suites: <release-debian> Components: main Signed-By: /etc/apt/trusted.gpg.d/epiconcept.asc
bash
:echo -e "Types: deb\nURIs: <repo>\nSuites: <release-debian>\nComponents: main\nSigned-By: /etc/apt/trusted.gpg.d/epiconcept.asc" > /etc/apt/sources.list.d/epiconcept.sources
- Pour les versions jusqu'à Debian 11 incluse, dans
-
Configuration de l'accès au serveur de dépôts
Hors de l'infrastructure d'Epiconcept, il faut également ajouter l'authentification de la machine cliente avec la commandebash
:echo -e "machine apt.epiconcept.fr\nlogin <user>\npassword <mdp>" | sudo tee /etc/apt/auth.conf.d/apt.epiconcept.fr.conf
Le script apt
est destiné à l'accès à distance aux scripts prep.sh
et prod.sh
.
Il doit être copié dans un des répertoires de PATH
sur la machine distante, d'où il sera exécuté.
Il s'utilise avec comme premier argument prep
ou prod
selon le script que l'on veut utiliser.
Le reste des arguments est directement passé au script concerné sur le serveur de dépôts.
Exemples :
apt prep # affichera le message d'utilisation
apt prod # de même
apt prep ls php # affiche les paquets dont le nom comprend la chaine 'php'
apt prod ver # affiche les paquets de production ayant plus d'une version