Migrer depuis JFrog Artifactory¶
Ce guide couvre le déplacement d'un dépôt APT de JFrog Artifactory vers
Repod. Il utilise l'API REST d'Artifactory et l'Artifactory Query Language
(AQL) pour énumérer et télécharger chaque paquet .deb, puis les importe
dans Repod avec un script d'upload en masse.
Artifactory CE vs Repod
Artifactory Community Edition nécessite un compte JFrog pour l'activation et effectue des appels de télémétrie vers l'extérieur. Repod est entièrement autonome : pas de compte, pas de serveur de licence, aucun appel sortant requis. Il stocke tout dans des volumes Docker sur votre propre infrastructure.
Vous migrez aussi des dépôts Maven, PyPI, npm ou Docker ?
Repod héberge des dépôts Maven, PyPI, npm et Docker/OCI aux côtés
d'APT — voir Formats de paquets.
Puisque Repod parle le protocole natif de chaque format, le chemin de
migration le plus rapide pour ceux-ci n'est généralement pas un
script de téléchargement en masse : pointez mvn deploy, twine
upload, ou docker push directement vers Repod (voir
Configuration des clients /
Registre de conteneurs) et republiez depuis
votre pipeline de build, ou utilisez l'importateur intégré de Repod
pour récupérer des artefacts spécifiques directement depuis Maven
Central / PyPI / npmjs.org / Docker Hub sans passer par Artifactory du
tout. L'approche par téléchargement-puis-réupload basée sur AQL de ce
guide est spécifique à la disposition de fichiers .deb d'APT.
1. Quand migrer¶
Ce guide est la bonne approche quand :
- Artifactory est utilisé principalement ou exclusivement comme miroir APT ou hébergeur de paquets internes, et que la complexité de son modèle multi-format n'est plus justifiée.
- Votre équipe souhaite un flux de travail APT dédié avec scan CVE et génération de manifestes intégrés, plutôt que de maintenir un stockage d'artefacts générique.
- Vous voulez réduire les coûts de licence : les licences Artifactory Pro ou Enterprise sont coûteuses ; Repod est open-source et auto-hébergé.
Vous pouvez faire tourner Repod et Artifactory côte à côte pendant la transition et migrer les dépôts une distribution à la fois.
2. Avant de commencer — checklist d'inventaire¶
Rassemblez ces informations avant d'apporter tout changement :
- URL de base d'Artifactory (par ex.
https://artifactory.example.com) et identifiants admin. - Noms de tous les dépôts locaux APT (type
Debianen terminologie Artifactory). - Distributions et composants définis dans les paramètres Debian de chaque dépôt.
- Nombre approximatif de paquets et taille disque totale.
- Nombre et emplacement des machines clientes, et comment
sources.listest géré. - Si Artifactory impose l'authentification sur le chemin de lecture (accès anonyme vs. jetons de déploiement).
Tip
Dans Artifactory, naviguez vers Administration → Repositories → Repositories et filtrez par type « Local » et type de paquet « Debian ». Faites une capture d'écran ou exportez la liste comme feuille de suivi de votre migration.
3. Étape 1 — Lister les paquets avec AQL¶
L'API Storage d'Artifactory peut lister les fichiers de façon récursive,
mais Artifactory Query Language (AQL) offre un filtrage précis et une
pagination avec bien moins de surcharge de réponse. Utilisez AQL pour
énumérer chaque fichier .deb de votre dépôt avant de télécharger quoi
que ce soit.
#!/usr/bin/env bash
# artifactory-list.sh — list all .deb files in an Artifactory local repo via AQL
set -euo pipefail
ART_URL="https://artifactory.example.com"
REPO_NAME="apt-local"
ART_USER="admin"
ART_PASS="changeme"
curl -s -u "${ART_USER}:${ART_PASS}" \
-X POST "${ART_URL}/artifactory/api/search/aql" \
-H "Content-Type: text/plain" \
-d "items.find({
\"repo\": \"${REPO_NAME}\",
\"name\": {\"\$match\": \"*.deb\"}
}).include(\"repo\", \"path\", \"name\", \"size\", \"sha256\")" \
| jq -r '.results[] | "\(.repo)/\(.path)/\(.name)"'
Enregistrez la sortie dans un fichier — elle devient le manifeste de téléchargement :
chmod +x artifactory-list.sh
./artifactory-list.sh > package-manifest.txt
wc -l package-manifest.txt # confirm total count matches your inventory
Alternativement, utilisez l'API Storage plus simple pour un listage rapide de répertoire (pas de pagination, adapté aux dépôts plus petits) :
curl -s -u "${ART_USER}:${ART_PASS}" \
"${ART_URL}/artifactory/api/storage/${REPO_NAME}?list&deep=1&listFolders=0" \
| jq -r '.files[].uri | select(endswith(".deb"))'
Warning
Le point de terminaison Storage API ?list&deep=1 charge
l'intégralité de l'arborescence du dépôt en mémoire sur le serveur
Artifactory avant de répondre. Sur des dépôts de dizaines de milliers
de fichiers, cela peut être lent ou expirer. Préférez AQL pour les
gros dépôts.
4. Étape 2 — Télécharger les fichiers .deb depuis Artifactory¶
Avec package-manifest.txt en main, téléchargez chaque fichier vers un
répertoire de staging local :
#!/usr/bin/env bash
# artifactory-export.sh — download .deb files listed in package-manifest.txt
set -euo pipefail
ART_URL="https://artifactory.example.com"
ART_USER="admin"
ART_PASS="changeme"
MANIFEST="./package-manifest.txt"
OUT_DIR="./artifactory-export"
mkdir -p "$OUT_DIR"
while IFS= read -r path; do
filename=$(basename "$path")
dest="${OUT_DIR}/${filename}"
if [[ -f "$dest" ]]; then
echo "Already exists, skipping: ${filename}"
continue
fi
echo -n "Downloading ${filename} ... "
http_code=$(curl -s -L -u "${ART_USER}:${ART_PASS}" \
-o "$dest" \
-w "%{http_code}" \
"${ART_URL}/artifactory/${path}")
if [[ "$http_code" == "200" ]]; then
echo "OK"
else
echo "FAILED (HTTP ${http_code})"
rm -f "$dest"
fi
done < "$MANIFEST"
echo "Download complete. Files in ${OUT_DIR}/"
Le modèle d'URL de téléchargement direct pour des paquets individuels est :
Le nom du dépôt, le chemin du composant et le nom de fichier proviennent
des résultats AQL stockés dans package-manifest.txt.
Tip
Ajoutez --retry 3 --retry-delay 5 aux options curl si votre
connexion réseau vers Artifactory est instable ou si vous téléchargez
via un VPN.
5. Étape 3 — Mettre en place Repod¶
Si vous n'avez pas encore Repod en cours d'exécution, suivez le guide de démarrage et revenez ici une fois que :
- La stack Docker Compose est démarrée (
frontend :3003,backend :8000,nginx :80). - Une clé de signature GPG a été générée dans Paramètres → GPG.
- Vous disposez d'un jeton API (préfixe
repod_) depuis Paramètres → Jetons API.
6. Étape 4 — Import en masse dans Repod¶
Uploadez les paquets téléchargés vers Repod. Le backend applique une limite de débit de 20 uploads par minute ; le script ci-dessous s'y adapte en conséquence.
#!/usr/bin/env bash
# repod-import.sh — bulk upload .deb files to Repod
set -euo pipefail
REPOD_URL="http://repod.example.com"
API_TOKEN="repod_xxxxxxxxxxxxxxxx"
DEB_DIR="./artifactory-export"
DISTRIBUTION="jammy"
COMPONENT="main"
UPLOAD_DELAY=3 # 20/min rate limit → 3s between uploads
success=0
failed=0
for deb in "${DEB_DIR}"/*.deb; do
filename=$(basename "$deb")
echo -n "Uploading ${filename} ... "
http_code=$(curl -s -o /tmp/repod_response.json -w "%{http_code}" \
-X POST "${REPOD_URL}/upload/" \
-H "Authorization: Bearer ${API_TOKEN}" \
-F "file=@${deb}" \
-F "distribution=${DISTRIBUTION}" \
-F "component=${COMPONENT}")
if [[ "$http_code" == "200" || "$http_code" == "201" ]]; then
echo "OK"
((success++))
else
echo "FAILED (HTTP ${http_code})"
cat /tmp/repod_response.json
((failed++))
fi
sleep "$UPLOAD_DELAY"
done
echo ""
echo "Done. Success: ${success} Failed: ${failed}"
Exécutez dans une session de terminal persistante :
7. Étape 5 — Vérifier¶
Comparez les décomptes et exécutez un test canari avant de toucher aux clients de production.
# Count downloaded files
ls artifactory-export/*.deb | wc -l
# Count packages now in Repod
curl -s -H "Authorization: Bearer ${API_TOKEN}" \
"${REPOD_URL}/packages/?distribution=jammy" | jq '.total'
Testez sur une machine canari isolée :
echo "deb [signed-by=/etc/apt/trusted.gpg.d/repod.gpg] \
http://repod.example.com jammy main" \
| sudo tee /etc/apt/sources.list.d/repod-test.list
curl -fsSL http://repod.example.com/gpg.key \
| sudo gpg --dearmor -o /etc/apt/trusted.gpg.d/repod.gpg
sudo apt update && sudo apt install your-internal-package
8. Étape 6 — Mettre à jour les machines clientes¶
Déployez la nouvelle source APT vers tous les clients à l'aide de votre outillage de gestion de configuration.
sudo rm /etc/apt/sources.list.d/artifactory.list
echo "deb [signed-by=/etc/apt/trusted.gpg.d/repod.gpg] \
http://repod.example.com jammy main" \
| sudo tee /etc/apt/sources.list.d/repod.list
curl -fsSL http://repod.example.com/gpg.key \
| sudo gpg --dearmor -o /etc/apt/trusted.gpg.d/repod.gpg
sudo apt update
- name: Remove Artifactory APT source
ansible.builtin.file:
path: /etc/apt/sources.list.d/artifactory.list
state: absent
- name: Download Repod GPG key
ansible.builtin.get_url:
url: http://repod.example.com/gpg.key
dest: /tmp/repod.gpg.asc
- name: Install dearmored GPG key
ansible.builtin.command:
cmd: gpg --dearmor -o /etc/apt/trusted.gpg.d/repod.gpg /tmp/repod.gpg.asc
creates: /etc/apt/trusted.gpg.d/repod.gpg
- name: Add Repod APT source
ansible.builtin.apt_repository:
repo: "deb [signed-by=/etc/apt/trusted.gpg.d/repod.gpg] http://repod.example.com jammy main"
state: present
filename: repod
9. Étape 7 — Basculer¶
Pointez le nom d'hôte APT canonique vers Repod via un changement DNS ou
une mise à jour du reverse proxy. Vérifiez avec sudo apt update sur
plusieurs machines depuis différents segments réseau avant de déclarer le
succès.
10. Plan de retour arrière¶
Gardez Artifactory en cours d'exécution à son URL d'origine pendant au
moins deux semaines après le basculement. Pour revenir en arrière,
annulez l'enregistrement DNS ou la mise à jour du proxy. Aucun changement
client n'est nécessaire — apt update recommencera automatiquement à
récupérer depuis Artifactory.
Warning
Ne décommissionnez pas Artifactory avant que Repod n'ait servi le trafic de production avec succès pendant au moins deux semaines et que vous ayez vérifié que toutes les versions de paquets sont présentes et installables.
11. Problèmes courants¶
AQL ne renvoie aucun résultat
Confirmez que le nom du dépôt dans la requête AQL correspond exactement (sensible à la casse). Dans Artifactory, ouvrez Administration → Repositories, trouvez votre dépôt APT, et copiez la valeur « Repository Key » telle quelle.
401 Unauthorized sur les téléchargements
Les jetons d'accès Artifactory et les mots de passe sont distincts. Si vous avez créé un jeton d'accès dans l'interface, transmettez-le comme jeton Bearer plutôt qu'en HTTP Basic :
Les paquets atterrissent dans la mauvaise distribution
Artifactory stocke les paquets Debian avec les métadonnées de
distribution dans leurs propriétés. Repod détermine la distribution à
partir des paramètres d'upload (-F "distribution=...") plutôt qu'en
lisant le fichier control du .deb. Assurez-vous que votre script
d'import cible le bon nom de distribution.
Les gros fichiers expirent à l'upload
Augmentez client_max_body_size dans la configuration Nginx de Repod
avant de lancer l'import. Les très gros paquets peuvent aussi nécessiter
un délai d'expiration de requête FastAPI plus long — définissez
--timeout-keep-alive dans la définition du service backend dans
docker-compose.yaml.