Aptly : mirroiter Debian proprement

Aptly : mirroiter Debian proprement

Table of Contents

Quand on gère une flotte de serveurs Debian, on finit toujours par se poser la même question : comment maîtriser ce que mes machines vont installer ? Comment être sûr qu'un apt update ne va pas me ramener une version de paquet qui casse tout ? Et surtout, comment faire pour que mes serveurs de prod ne dépendent pas d'un miroir externe qui peut tomber au pire moment ?

La réponse classique, c'est de monter un miroir local. Sauf que mirrorer Debian avec les outils standards (debmirror, apt-mirror...), c'est lourd, c'est rigide, et ça ne répond qu'à la moitié du problème. On a une copie locale, d'accord, mais on n'a toujours aucun contrôle sur ce qui change d'un jour à l'autre.

C'est là qu'aptly entre en jeu.

Ce qu'aptly fait vraiment

aptly, c'est un gestionnaire de dépôts Debian écrit en Go. Il sait faire trois choses fondamentales :

  1. mirrorer un dépôt distant -- comme apt-mirror, mais en mieux
  2. Figer l'état d'un miroir dans un snapshot immuable -- ça, c'est la vraie valeur ajoutée
  3. Publier ce snapshot pour que vos machines puissent l'utiliser

Le workflow de base, c'est ça :

mirror create → mirror update → snapshot create → publish snapshot

Et quand il faut mettre à jour :

mirror update → snapshot create → publish switch

Le publish switch bascule la publication d'un snapshot à un autre. Vos machines continuent de pointer sur la même URL, mais le contenu change de manière contrôlée. Si ça foire, vous rebasculez sur l'ancien snapshot. Pas de panique, pas de retélécharger quoi que ce soit.

Installation

Via les paquets Debian

C'est la méthode standard, celle qu'on va utiliser ici :

sudo apt update
sudo apt install aptly

Sur Debian Trixie, ça installe la version 1.5.0. C'est pas la toute dernière (la 1.6.2 existe), mais c'est largement suffisant pour ce qu'on va faire.

Vérification :

$ aptly version
aptly version: 1.5.0

L'upstream (optionnel)

Si vous voulez absolument la dernière version upstream, vous pouvez ajouter le dépôt officiel d'aptly. Mais franchement, pour un usage classique, la version Debian fait le job. Je mentionne juste l'option pour ceux qui en ont besoin :

sudo mkdir -p /etc/apt/keyrings
wget -O /etc/apt/keyrings/aptly.asc https://www.aptly.info/pubkey.txt

echo "deb [signed-by=/etc/apt/keyrings/aptly.asc] http://repo.aptly.info/release trixie main" \
    | sudo tee /etc/apt/sources.list.d/aptly.list

sudo apt update
sudo apt install aptly

Mais encore une fois, c'est optionnel. On va continuer avec la version des dépôts Debian.

Configuration de base

aptly stocke tout dans ~/.aptly par défaut. En prod, on va plutôt utiliser /var/aptly. On crée le répertoire et on configure aptly pour l'utiliser :

sudo mkdir -p /var/aptly
sudo chown $USER:$USER /var/aptly

Le fichier de config, c'est ~/.aptly.conf (ou /etc/aptly.conf pour une config globale). On va en créer un minimal :

cat > ~/.aptly.conf << 'EOF'
{
  "rootDir": "/var/aptly",
  "architectures": ["amd64"]
}
EOF

On restreint à amd64 parce que c'est ce qu'on utilise. Pas la peine de télécharger du i386, du arm64 ou du armhf si on n'en a pas besoin.

Le rootDir, c'est la racine de tout. Dedans, aptly va créer :

  • db/ -- sa base de données interne
  • pool/ -- les fichiers .deb téléchargés
  • public/ -- les dépôts publiés, ceux qu'on va exposer

Importer les clés GPG

Avant de créer un miroir, aptly a besoin des clés GPG pour vérifier les signatures des dépôts distants. Sur Debian, les clés d'archive sont déjà présentes dans /usr/share/keyrings/. Il suffit de les importer dans le trousseau d'aptly :

gpg --no-default-keyring \
    --keyring /usr/share/keyrings/debian-archive-keyring.gpg \
    --export | \
    gpg --no-default-keyring \
    --keyring trustedkeys.gpg \
    --import

Ça importe les clés dans ~/.gnupg/trustedkeys.gpg, le trousseau qu'aptly utilise par défaut.

Créer un miroir de Debian Trixie

On va mirrorer le dépôt officiel français (ftp.fr.debian.org), avec les sections main et non-free-firmware. Pourquoi non-free-firmware ? Parce que depuis Debian 12, les firmwares non-libres (wifi, GPU...) sont dans cette section, et on en a souvent besoin.

aptly mirror create \
    -architectures=amd64 \
    debian-trixie \
    http://ftp.fr.debian.org/debian/ \
    trixie main non-free-firmware

Quelques remarques :

  • Le flag -architectures=amd64 se place avant la sous-commande mirror. C'est un flag global. Si vous le mettez après, aptly va râler.
  • Le nom du miroir (debian-trixie), c'est vous qui le choisissez. Prenez un nom explicite.
  • L'URL doit finir par un /.
  • On spécifie la distribution (trixie) et les composants (main non-free-firmware).

La commande crée la définition du miroir, mais ne télécharge rien encore. Pour ça, il faut lancer un mirror update.

Remplir le miroir

aptly mirror update debian-trixie

Là, ça télécharge. Et ça prend du temps. Un miroir complet de Debian main + non-free-firmware en amd64, c'est plusieurs dizaines de Go. Prévoyez du café.

Vous pouvez suivre la progression dans le terminal. aptly affiche les paquets au fur et à mesure qu'il les télécharge.

Une fois terminé, vous pouvez voir ce que contient le miroir :

aptly mirror show debian-trixie

Ça vous donne le nombre de paquets, la taille totale, la date de dernière mise à jour, etc.

Créer un snapshot

Le miroir est à jour. Maintenant, on va en faire un snapshot. Un snapshot, c'est une copie figée et immuable de l'état du miroir à un instant T. Une fois créé, il ne bouge plus, quoi qu'il arrive au miroir source.

aptly snapshot create trixie-$(date +%Y%m%d) from mirror debian-trixie

J'utilise la date dans le nom du snapshot. C'est une bonne pratique : ça permet de savoir immédiatement à quoi correspond chaque snapshot.

Vous pouvez lister vos snapshots :

aptly snapshot list

Et voir le détail d'un snapshot :

aptly snapshot show trixie-20260313

Publier le snapshot

Un snapshot qui n'est pas publié, ça ne sert à rien. La publication génère l'arborescence standard Debian (dists/, pool/, fichiers Release signés...) dans /var/aptly/public/.

aptly publish snapshot -distribution=trixie trixie-20260313

Le flag -distribution=trixie indique quelle distribution utiliser dans les métadonnées du dépôt publié. C'est ce que vos machines verront dans leur sources.list.

aptly va vous demander la passphrase de votre clé GPG pour signer le fichier Release. Si vous n'avez pas encore de clé GPG, créez-en une :

gpg --full-generate-key

Choisissez RSA 4096 bits, et renseignez un nom et un email.

Une fois la publication terminée, vous avez un dépôt Debian complet dans /var/aptly/public/. Il ne reste plus qu'à l'exposer via un serveur web.

L'impact des hard links

Un détail important : quand aptly publie un snapshot, il ne copie pas les fichiers .deb. Il crée des hard links depuis le pool vers le répertoire public/.

Ça veut dire quoi concrètement ?

  1. Pas de duplication -- un paquet présent dans plusieurs snapshots n'occupe qu'une seule fois la place sur le disque
  2. Publication instantanée -- créer un hard link, c'est quasi gratuit en temps et en espace
  3. Plusieurs snapshots publiés en même temps -- vous pouvez avoir trixie-20260313 et trixie-20260310 publiés simultanément, ils partagent les fichiers communs

C'est pour ça que le publish switch est si rapide. aptly ne déplace rien, il change juste les liens.

Par contre, attention : si vous supprimez un snapshot publié avec snapshot drop, aptly refuse tant que la publication existe. Il faut d'abord dépublier (publish drop) ou basculer vers un autre snapshot (publish switch).

Mettre à jour le miroir et basculer

Quelques jours passent. Le miroir Debian a évolué. Vous voulez mettre à jour votre dépôt local. Voilà le workflow complet :

# 1. Mettre à jour le miroir
aptly mirror update debian-trixie

# 2. Créer un nouveau snapshot
aptly snapshot create trixie-$(date +%Y%m%d) from mirror debian-trixie

# 3. Basculer la publication vers le nouveau snapshot
aptly publish switch trixie trixie-20260315

Le publish switch fait tout le boulot :

  • Il met à jour les métadonnées (Release, Packages, Contents...)
  • Il ajuste les hard links dans public/
  • Il signe le nouveau Release avec GPG
  • Il nettoie les anciens liens qui ne servent plus

Vos machines qui pointent sur ce dépôt voient le changement au prochain apt update. Pas de coupure, pas de temps d'arrêt.

Si le nouveau snapshot pose problème, vous rebasculez sur l'ancien :

aptly publish switch trixie trixie-20260313

C'est aussi rapide dans un sens que dans l'autre.

Les dépôts locaux (mention rapide)

aptly sait aussi gérer des dépôts locaux, où vous poussez vos propres paquets .deb. Le workflow est similaire :

# Créer un dépôt local
aptly repo create mon-depot

# Ajouter des paquets
aptly repo add mon-depot /chemin/vers/*.deb

# Snapshot
aptly snapshot create mon-depot-v1 from repo mon-depot

# Publier
aptly publish snapshot mon-depot-v1

Je ne développe pas plus ici, parce que le cas d'usage principal d'aptly, c'est quand même le mirroring. Mais sachez que c'est possible.

Exposer le dépôt

Le serveur embarqué (test uniquement)

aptly a un petit serveur HTTP intégré. C'est pratique pour tester, mais la doc officielle est claire : not suitable for real production usage.

aptly serve -listen=:8080

Vous pouvez alors ajouter le dépôt sur une machine de test :

echo "deb http://votre-serveur:8080/ trixie main non-free-firmware" \
    | sudo tee /etc/apt/sources.list.d/aptly-test.list

nginx (production)

En prod, on utilise nginx. Je ne vais pas détailler ici parce que ça fera l'objet d'un second article si besoin, mais l'idée générale :

server {
    listen 80;
    server_name repo.example.com;
    root /var/aptly/public;
    location / {
        autoindex on;
    }
}

Vous activez le vhost, vous rechargez nginx, et c'est bon. Pour HTTPS, ajoutez Let's Encrypt avec certbot.

Côté client, vous ajoutez le dépôt :

echo "deb http://repo.example.com/ trixie main non-free-firmware" \
    | sudo tee /etc/apt/sources.list.d/mon-miroir.list

sudo apt update

Si le dépôt est signé (et il devrait l'être), distribuez votre clé GPG publique aux clients :

gpg --armor --export VOTRE_KEY_ID > /var/aptly/public/repo-key.asc

Sur les clients :

wget -O /etc/apt/keyrings/mon-repo.asc http://repo.example.com/repo-key.asc

echo "deb [signed-by=/etc/apt/keyrings/mon-repo.asc] http://repo.example.com/ trixie main non-free-firmware" \
    | sudo tee /etc/apt/sources.list.d/mon-miroir.list

Automatiser avec cron

Un miroir, ça se met à jour régulièrement. Voici un script cron qui fait le job :

#!/bin/bash
# /etc/cron.daily/aptly-update

set -euo pipefail

MIRROR="debian-trixie"
DATE=$(date +%Y%m%d)

# Mise à jour du miroir
aptly mirror update "$MIRROR"

# Nouveau snapshot
aptly snapshot create "trixie-${DATE}" from mirror "$MIRROR"

# Basculer la publication
aptly publish switch -batch -gpg-key="VOTRE_KEY_ID" trixie "trixie-${DATE}"

# Nettoyer les vieux snapshots (garder les 7 derniers)
aptly snapshot list -raw | grep "^trixie-" | sort | head -n -7 | while read snap; do
    aptly snapshot drop "$snap" 2>/dev/null || true
done

# Nettoyer la base
aptly db cleanup

Le flag -batch est crucial : il permet à GPG de fonctionner sans terminal interactif. Sans ça, le script va bloquer en attendant que vous tapiez la passphrase.

Pour éviter ça, vous pouvez aussi utiliser gpg-agent avec un cache de passphrase, ou stocker la passphrase dans un fichier sécurisé et utiliser -passphrase-file.

Nettoyage et maintenance

aptly conserve tous les paquets téléchargés dans son pool, même ceux qui ne sont plus référencés par aucun snapshot. Pour faire le ménage :

aptly db cleanup

Ça supprime les paquets orphelins. Si vous voulez voir ce qui va être supprimé avant de le faire :

aptly db cleanup -verbose -dry-run

Pour sauvegarder votre installation aptly, c'est simple : sauvegardez /var/aptly en entier. Tout est dedans.

tar -czf aptly-backup-$(date +%Y%m%d).tar.gz /var/aptly

Quelques astuces

Filtrer les paquets lors du mirroring. Si vous ne voulez mirrorer que certains paquets (par exemple, uniquement nginx et ses dépendances), vous pouvez utiliser des filtres :

aptly mirror create -filter='nginx' -filter-with-deps \
    nginx-only \
    http://ftp.fr.debian.org/debian/ \
    trixie main

Le flag -filter-with-deps est important : sans lui, vous récupérez nginx mais pas ses dépendances, et ça ne servira à rien.

Comparer deux snapshots. Pour voir ce qui a changé entre deux snapshots :

aptly snapshot diff trixie-20260313 trixie-20260315

Fusionner des snapshots. Vous pouvez combiner plusieurs snapshots en un seul. Utile si vous avez un miroir Debian et un dépôt local, et que vous voulez les publier ensemble :

aptly snapshot merge trixie-complet trixie-20260315 mon-depot-v1

Conclusion

aptly résout un vrai problème : comment garder le contrôle sur ce que vos machines Debian vont installer. Les miroirs classiques vous donnent une copie locale, d'accord, mais ils ne vous donnent pas la maîtrise des changements. Avec aptly et ses snapshots, vous décidez quand et comment vos serveurs voient les mises à jour.

Le workflow mirror createmirror updatesnapshot createpublish snapshotpublish switch devient vite un réflexe. Et le jour où une mise à jour casse quelque chose, vous serez bien content de pouvoir rebascule sur le snapshot d'hier en une commande.

Les hard links font que tout ça reste léger en espace disque et rapide en exécution. Vous pouvez avoir plusieurs snapshots publiés en parallèle, pour des environnements de test et de prod différents, sans exploser votre stockage.

Bref, si vous gérez des serveurs Debian sérieusement, aptly mérite sa place dans votre boîte à outils.

Les commentaires sont fermés.