Configuration des clients¶
Configurer les machines pour installer des paquets depuis votre dépôt Repod.
Prérequis¶
- Le serveur du dépôt Repod est démarré et accessible depuis la machine cliente
- Au moins un paquet a été uploadé et publié avec succès
- La clé publique GPG du dépôt est disponible (dans Paramètres → GPG)
Clients APT (Debian / Ubuntu)¶
Étape 1 — Importer la clé de signature GPG¶
Le client APT vérifie la signature du fichier InRelease du dépôt. Importer
la clé de signature une fois par machine :
Étape 2 — Ajouter la source APT¶
# Remplacer 'jammy' par le nom de code de votre distribution cible
echo "deb http://VOTRE_HOTE:80/repos jammy main" \
| sudo tee /etc/apt/sources.list.d/repod.list
Étape 3 — Mettre à jour et installer¶
Vérifier la configuration¶
# Vérifier que le dépôt est reconnu
apt-cache policy monpaquet
# Devrait afficher "http://VOTRE_HOTE:80/repos jammy/main" comme candidat
Plusieurs distributions¶
# Paquets Ubuntu 22.04
deb http://VOTRE_HOTE:80/repos jammy main
# Paquets Ubuntu 24.04 (si vous maintenez des paquets séparés par version)
deb http://VOTRE_HOTE:80/repos noble main
Rôle Ansible¶
---
- name: Configurer le dépôt APT Repod
hosts: all
become: true
tasks:
- name: Importer la clé GPG Repod
ansible.builtin.get_url:
url: "http://VOTRE_HOTE:80/repos/gpg.key"
dest: /tmp/repod.asc
- name: Convertir et installer la clé
ansible.builtin.shell: |
gpg --dearmor < /tmp/repod.asc > /etc/apt/trusted.gpg.d/repod.gpg
- name: Ajouter la source APT
ansible.builtin.apt_repository:
repo: "deb http://VOTRE_HOTE:80/repos {{ ansible_distribution_release }} main"
filename: repod
state: present
update_cache: yes
Clients RPM — DNF (AlmaLinux / RHEL / Rocky / Fedora)¶
Étape 1 — Importer la clé de signature GPG¶
Vérifier que la clé a bien été importée :
Étape 2 — Créer le fichier de dépôt¶
[repod]
name=Repod Private Repository
baseurl=http://VOTRE_HOTE:80/repos/almalinux9/x86_64/
enabled=1
gpgcheck=1
gpgkey=http://VOTRE_HOTE:80/repos/gpg.key
repo_gpgcheck=0
metadata_expire=300
repo_gpgcheck=0
Laisser repo_gpgcheck=0 sauf si vous avez signé repomd.xml avec une
clé que DNF peut vérifier séparément. Le gpgcheck=1 au niveau des
paquets suffit pour la plupart des déploiements.
Étape 3 — Installer des paquets¶
# Rafraîchir les métadonnées
sudo dnf makecache --repo=repod
# Installer un paquet
sudo dnf install monpaquet
# Lister les paquets disponibles depuis Repod uniquement
sudo dnf list available --repo=repod
baseurl par distribution¶
| Distribution | baseurl |
|---|---|
| AlmaLinux 8 | http://VOTRE_HOTE:80/repos/almalinux8/x86_64/ |
| AlmaLinux 9 | http://VOTRE_HOTE:80/repos/almalinux9/x86_64/ |
| Rocky Linux 8 | http://VOTRE_HOTE:80/repos/rocky8/x86_64/ |
| Rocky Linux 9 | http://VOTRE_HOTE:80/repos/rocky9/x86_64/ |
| CentOS Stream 9 | http://VOTRE_HOTE:80/repos/centos-stream9/x86_64/ |
| Fedora 42 | http://VOTRE_HOTE:80/repos/fedora/x86_64/ |
| openSUSE Leap 15.6 | http://VOTRE_HOTE:80/repos/opensuse-leap-15.6/x86_64/ |
Rôle Ansible (DNF)¶
---
- name: Configurer le dépôt RPM Repod
hosts: all
become: true
tasks:
- name: Importer la clé GPG Repod
ansible.builtin.rpm_key:
key: "http://VOTRE_HOTE:80/repos/gpg.key"
state: present
- name: Ajouter le dépôt Repod
ansible.builtin.yum_repository:
name: repod
description: Repod Private Repository
baseurl: "http://VOTRE_HOTE:80/repos/{{ ansible_distribution | lower }}{{ ansible_distribution_major_version }}/x86_64/"
enabled: yes
gpgcheck: yes
gpgkey: "http://VOTRE_HOTE:80/repos/gpg.key"
state: present
Clients RPM — Zypper (openSUSE Leap)¶
Étape 1 — Ajouter le dépôt¶
sudo zypper addrepo \
--name "Repod Private Repository" \
--gpgcheck \
http://VOTRE_HOTE:80/repos/opensuse-leap-15.6/x86_64/ \
repod
Étape 2 — Importer la clé GPG¶
Étape 3 — Installer des paquets¶
Clients Maven (mvn / Gradle)¶
Le support Maven de Repod (V1) héberge des artefacts de release privés — il
ne fait pas office de proxy vers Maven Central. Chaque déploiement (PUT)
nécessite une authentification HTTP Basic ; les lectures (GET) sont
ouvertes, la même limitation connue déjà documentée pour les téléchargements
de paquets APT/RPM/APK. Les versions SNAPSHOT ne sont pas encore prises en
charge — ne déployez que des versions de release.
Étape 1 — Configurer les identifiants dans settings.xml¶
Le <server><id> doit correspondre à l'<id> utilisé dans le bloc
<distributionManagement>/<repository> de votre POM ci-dessous. Le mot de
passe peut être votre mot de passe de compte Repod ou, pour la CI/CD, un
token API (repod_...).
<settings>
<servers>
<server>
<id>repod-releases</id>
<username>VOTRE_NOM_UTILISATEUR</username>
<password>VOTRE_MOT_DE_PASSE_OU_TOKEN_API</password>
</server>
</servers>
</settings>
Dépôts en HTTP simple
Maven bloque par défaut les dépôts externes en http:// depuis la
version 3.8.1. Si votre instance Repod n'est pas encore derrière TLS
(voir docker-compose.tls.yml), ajoutez une surcharge de miroir pour
débloquer spécifiquement l'identifiant de votre dépôt :
Étape 2 — Publier (mvn deploy)¶
<project>
...
<distributionManagement>
<repository>
<id>repod-releases</id>
<url>http://VOTRE_HOTE:8000/api/v1/maven/releases</url>
</repository>
</distributionManagement>
</project>
releases est le nom du dépôt Maven cible — il est créé automatiquement au
premier déploiement réussi (aucun pré-enregistrement nécessaire), sur le même
modèle de dépôt dynamique que le registre OCI. Ensuite :
Les sommes de contrôle (.sha1/.md5) et maven-metadata.xml sont toujours
générées côté serveur à partir de l'artefact réellement stocké — tout ce que
le client Maven envoie pour ces fichiers est accepté mais ignoré, jamais
utilisé tel quel.
Étape 3 — Résoudre (mvn dependency:get / dépendances classiques)¶
<repositories>
<repository>
<id>repod-releases</id>
<url>http://VOTRE_HOTE:8000/api/v1/maven/releases</url>
</repository>
</repositories>
Gradle¶
repositories {
maven {
url "http://VOTRE_HOTE:8000/api/v1/maven/releases"
credentials {
username = project.findProperty("repodUser") ?: ""
password = project.findProperty("repodToken") ?: ""
}
}
}
publishing {
repositories {
maven {
url "http://VOTRE_HOTE:8000/api/v1/maven/releases"
credentials {
username = project.findProperty("repodUser") ?: ""
password = project.findProperty("repodToken") ?: ""
}
}
}
}
Contrôle d'accès¶
Par défaut, tout nom de dépôt est ouvert au mvn deploy pour les comptes
uploader/maintainer/admin. Pour restreindre un dépôt spécifique à certains
rôles ou groupes, utiliser POST /api/v1/maven/repositories/{name}/access
(admin uniquement) — le même modèle RBAC que
distribution_access/oci_repository_access : aucune ligne signifie ouvert,
l'admin passe toujours outre, et un refus en lecture renvoie 404 plutôt
que 403 pour éviter de révéler l'existence d'un dépôt restreint.
Clients PyPI (pip / twine)¶
Le support PyPI de Repod (V1) héberge des wheels/sdists privés — il ne fait
pas office de proxy vers PyPI. Il implémente l'API Simple Repository (PEP
503) en HTML pour pip install/pip download, ainsi que le protocole
d'upload « legacy » (POST .../legacy/) pour twine upload — le même
protocole utilisé par upload.pypi.org sur le vrai PyPI, donc les outils
standards fonctionnent sans modification. Contrairement à Maven, les lectures
(pages de l'API Simple et téléchargements de fichiers) sont elles aussi
soumises au RBAC lorsqu'un index de dépôt est restreint — voir « Contrôle
d'accès » ci-dessous.
Étape 1 — Installer (pip install)¶
pip install --index-url http://VOTRE_UTILISATEUR:VOTRE_MOT_DE_PASSE_OU_TOKEN@VOTRE_HOTE:8000/api/v1/pypi/private/simple/ monpaquet
Ou en le rendant persistant dans pip.conf/pip.ini :
[global]
index-url = http://VOTRE_UTILISATEUR:VOTRE_MOT_DE_PASSE_OU_TOKEN@VOTRE_HOTE:8000/api/v1/pypi/private/simple/
private est le nom de l'index PyPI cible — comme les dépôts Maven et OCI,
il est créé automatiquement au premier upload réussi (aucun pré-
enregistrement nécessaire). Si l'index n'a aucune restriction RBAC, les
identifiants dans l'URL sont optionnels — un simple pip install --index-url
http://VOTRE_HOTE:8000/api/v1/pypi/private/simple/ monpaquet fonctionne
aussi.
Combiner avec le PyPI public
Utiliser --extra-index-url au lieu de --index-url pour se rabattre
sur pypi.org pour les paquets non hébergés en privé :
Étape 2 — Publier (twine upload)¶
pip install twine
twine upload --repository-url http://VOTRE_HOTE:8000/api/v1/pypi/private/legacy/ \
-u VOTRE_NOM_UTILISATEUR -p VOTRE_MOT_DE_PASSE_OU_TOKEN_API \
dist/*
Ou via .pypirc :
[distutils]
index-servers = repod-private
[repod-private]
repository = http://VOTRE_HOTE:8000/api/v1/pypi/private/legacy/
username = VOTRE_NOM_UTILISATEUR
password = VOTRE_MOT_DE_PASSE_OU_TOKEN_API
Les sommes de contrôle sont toujours calculées côté serveur à partir du
fichier uploadé — le sha256_digest envoyé par twine est accepté mais non
utilisé tel quel.
Contrôle d'accès¶
Par défaut, tout nom d'index est ouvert en publication pour les comptes
uploader/maintainer/admin, et ouvert en lecture pour tout le monde. Pour
restreindre un index spécifique (lectures et écritures) à certains rôles
ou groupes, utiliser POST /api/v1/pypi/repositories/{name}/access (admin
uniquement) — même modèle RBAC que
distribution_access/maven_repository_access : aucune ligne signifie
ouvert, l'admin passe toujours outre, un refus renvoie 404 plutôt que 403
pour éviter de révéler l'existence d'un index restreint. Un index restreint
rejette les pip install/pip download non authentifiés — fournir les
identifiants dans --index-url comme montré ci-dessus.
Clients npm (npm / yarn)¶
Le support npm de Repod (V1) héberge des paquets privés — il ne fait pas
office de proxy vers npmjs.org. Il implémente le vrai protocole du registre
npm (packument via GET /{package}, publication via un simple PUT
/{package} avec le tarball encodé en base64 dans le corps de la requête —
la même forme que celle envoyée par npm publish à n'importe quel registre),
donc les outils standards fonctionnent sans modification. Comme pour PyPI,
les lectures (packument + téléchargement du tarball) sont elles aussi
soumises au RBAC lorsqu'un namespace est restreint.
Étape 1 — Obtenir un token¶
Générer un token API Repod (Paramètres → Tokens API, ou demander à un
admin) — le flux interactif npm login n'est pas pris en charge en V1 ;
coller directement un token pré-généré dans .npmrc à la place (l'approche
standard pour les registres privés — GitHub Packages, Artifactory et
Verdaccio avec authentification par token fonctionnent tous de la même
manière).
Étape 2 — Configurer .npmrc¶
registry=http://VOTRE_HOTE:8000/api/v1/npm/private/
//VOTRE_HOTE:8000/api/v1/npm/private/:_authToken=VOTRE_TOKEN_API
private est le namespace npm cible — comme pour Maven/PyPI, il est créé
automatiquement à la première publication réussie (aucun pré-enregistrement
nécessaire). Si le namespace n'a aucune restriction RBAC, la ligne
_authToken n'est nécessaire que pour npm publish (les lectures
fonctionnent sans elle).
Pour restreindre une organisation spécifique à un namespace privé tout en gardant le reste sur le registre npm public :
@monorg:registry=http://VOTRE_HOTE:8000/api/v1/npm/private/
//VOTRE_HOTE:8000/api/v1/npm/private/:_authToken=VOTRE_TOKEN_API
Étape 3 — Installer / publier¶
npm install monpaquet # se résout via le registre configuré
npm publish # depuis le répertoire du paquet
Contrôle d'accès¶
Par défaut, tout namespace est ouvert en publication pour les comptes
uploader/maintainer/admin, et ouvert en lecture pour tout le monde. Pour
restreindre un namespace (lectures et écritures) à certains rôles ou
groupes, utiliser POST /api/v1/npm/repositories/{name}/access (admin
uniquement) — même modèle RBAC que
maven_repository_access/pypi_repository_access : aucune ligne signifie
ouvert, l'admin passe toujours outre, un refus renvoie 404 plutôt que
403.
Limitations connues en V1¶
- Seul le dist-tag
latestest pris en charge — il pointe vers la version publiée le plus récemment (le comportement réel par défaut de npm pournpm publishsans--tag), pas nécessairement la version au semver le plus élevé. - Les champs
dependencies/scripts/engineset autres champs depackage.jsonne sont pas conservés dans le packument — suffisant pournpm install <pkg>/npm publishd'un paquet autonome, pas pour résoudre un paquet qui dépend lui-même d'autres paquets npm. npm unpublishetnpm deprecatene sont pas implémentés.
Accès authentifié (tokens API)¶
Si votre instance Repod nécessite une authentification pour télécharger des paquets (ce n'est pas le cas par défaut avec le Nginx du dépôt, mais c'est possible via des règles de reverse proxy), utiliser l'authentification HTTP Basic ou un token dans l'en-tête de requête.
Configuration CI/CD¶
- name: Configurer le dépôt Repod (APT)
run: |
curl -fsSL http://${{ secrets.REPOD_HOST }}/repos/dists/jammy/InRelease \
| gpg --dearmor \
| sudo tee /etc/apt/trusted.gpg.d/repod.gpg > /dev/null
echo "deb http://${{ secrets.REPOD_HOST }}/repos jammy main" \
| sudo tee /etc/apt/sources.list.d/repod.list
sudo apt update
sudo apt install monpaquet
install:
before_script:
- |
curl -fsSL http://${REPOD_HOST}/repos/dists/jammy/InRelease \
| gpg --dearmor \
| tee /etc/apt/trusted.gpg.d/repod.gpg > /dev/null
echo "deb http://${REPOD_HOST}/repos jammy main" \
> /etc/apt/sources.list.d/repod.list
apt-get update -qq
script:
- apt-get install -y monpaquet
Résolution de problèmes¶
| Problème | Cause probable | Solution |
|---|---|---|
NO_PUBKEY lors de apt update |
Clé GPG non importée ou expirée | Ré-exécuter la commande d'import de clé |
404 Not Found lors de apt update |
Nom de code de distribution incorrect | Vérifier le codename dans sources.list |
GPG key retrieval failed sur dnf install |
Clé non importée | Exécuter rpm --import ... |
| Version de paquet obsolète | Cache de métadonnées trop long | dnf makecache ou apt update |
HTTPS requis par la politique |
Politique interne | Ajouter un reverse proxy avec TLS ; voir le guide reverse proxy |