Tutoriel

Harbor Registry self-hosted sur VPS : guide complet

Déploiement8 min de lecture7 étapes

Depuis la CVE-2026-21589 qui a secoué la supply chain Atlassian, les équipes DevOps cherchent à reprendre le contrôle de chaque artefact qui circule dans leur pipeline. Docker Hub impose un rate-limit à 100 pulls/6 h sur les comptes gratuits, GHCR lie vos images à la politique de rétention de GitHub, et aucun des deux ne signe ni ne scanne vos images par défaut. Harbor, le registre open source de la CNCF, règle ces trois problèmes d'un seul déploiement : scan de vulnérabilités Trivy intégré, signature Cosign, RBAC granulaire et audit logs complets. Ce guide vous accompagne de l'installation Docker Compose jusqu'à la politique d'admission en production, sur un VPS de 4 vCPU / 8 Go RAM.

Sommaire· Pourquoi un registre Docker privé avec Harbor1/9
  1. 01Pourquoi un registre Docker privé avec Harbor
  2. 02Bénéfices clés de Harbor
  3. 03Prérequis chiffrés
  4. 04Installation Harbor v2.15 avec Docker Compose
  5. 05Configuration : projets, utilisateurs et OIDC (ZITADEL)
  6. 06Scanner les images avec Trivy
  7. 07Conseil sécurité : politiques d'admission Kubernetes
  8. 08Dépannage : 5 erreurs réelles avec leurs causes
  9. 09Harbor vs Docker Hub vs GHCR vs Gitea Registry

Pourquoi un registre Docker privé avec Harbor

Docker Hub et GHCR sont des services publics pratiques, mais ils posent trois problèmes concrets dès que votre organisation grandit ou doit répondre à une exigence NIS2 (art. 21 § 2 f – sécurité de la chaîne d'approvisionnement) ou GDPR (données d'infrastructure hébergées hors UE). Harbor répond point par point.

Bénéfices clés de Harbor

  • Scan Trivy intégré — chaque push déclenche une analyse CVE ; les politiques d'admission bloquent le déploiement d'une image dont la criticité dépasse le seuil configuré.
  • Signature Cosign / Notary — la chaîne de confiance va du build CI jusqu'au cluster Kubernetes ; seules les images signées par votre clé passent.
  • RBAC multi-projet — isolation par équipe, par environnement (dev/staging/prod) ou par client, avec des rôles Guest, Developer, Maintainer et ProjectAdmin.
  • Réplication inter-registres — synchronisez vers un second VPS, vers AWS ECR ou vers Docker Hub pour la distribution CDN.
  • Audit logs immuables — chaque pull, push, suppression et connexion est tracé avec l'IP source ; conformité NIS2 article 21 § 2 d.
  • Pas de rate limit — vos runners CI tirent autant d'images que nécessaire sans délai ni quota.
  • OIDC natif — connectez Harbor à ZITADEL ou tout fournisseur OpenID Connect ; zéro compte local à gérer.

Prérequis chiffrés

Harbor tourne confortablement sur un VPS à partir de la configuration suivante :

- CPU : 4 vCPU (minimum 2 vCPU, mais Trivy consomme 1–2 cœurs au scan)
- RAM : 8 Go (4 Go minimum ; prévoir 2 Go pour la base PostgreSQL, 1 Go pour Redis, 2 Go pour le core Harbor, 1 Go de marge)
- Disque : 100 Go SSD (les layers Docker s'accumulent vite ; prévoir 40 Go pour le registre, 20 Go pour les logs Trivy, 20 Go pour le système)
- OS : Debian 12 ou Ubuntu 22.04 LTS
- Docker : ≥ 24.0, Docker Compose : ≥ 2.20
- DNS : un sous-domaine pointant vers votre VPS (registry.exemple.com), déjà résolu
- TLS : certificat valide — Let's Encrypt via Certbot ou Traefik ACME

Installation Harbor v2.15 avec Docker Compose

  1. Télécharger le programme d'installation offline

    Connectez-vous en SSH sur votre VPS. Récupérez le package offline Harbor v2.15.4 (le plus stable au 2026-10-13) depuis GitHub :

    export HARBOR_VERSION=v2.15.4
    wget https://github.com/goharbor/harbor/releases/download/${HARBOR_VERSION}/harbor-offline-installer-${HARBOR_VERSION}.tgz
    wget https://github.com/goharbor/harbor/releases/download/${HARBOR_VERSION}/harbor-offline-installer-${HARBOR_VERSION}.tgz.asc
    # Vérifier la signature GPG
    gpg --keyserver keyserver.ubuntu.com --recv-keys 7722D168DAEC457894C2988818B80B4B2D318C8A
    gpg --verify harbor-offline-installer-${HARBOR_VERSION}.tgz.asc
    tar xvf harbor-offline-installer-${HARBOR_VERSION}.tgz
    cd harbor
  2. Préparer les certificats TLS

    Harbor exige TLS. Si vous utilisez Certbot :

    apt install -y certbot
    certbot certonly --standalone -d registry.exemple.com
    # Les certificats sont dans /etc/letsencrypt/live/registry.exemple.com/
    mkdir -p /data/cert
    cp /etc/letsencrypt/live/registry.exemple.com/fullchain.pem /data/cert/registry.exemple.com.crt
    cp /etc/letsencrypt/live/registry.exemple.com/privkey.pem  /data/cert/registry.exemple.com.key

    Si vous utilisez Traefik comme reverse proxy (voir l'article sur Traefik v3), déléguez la terminaison TLS à Traefik et configurez Harbor en HTTP interne sur le port 8080.

  3. Configurer harbor.yml

    Copiez le template et adaptez les valeurs essentielles :

    cp harbor.yml.tmpl harbor.yml

    Éditez harbor.yml :

    hostname: registry.exemple.com
    
    https:
      port: 443
      certificate: /data/cert/registry.exemple.com.crt
      private_key: /data/cert/registry.exemple.com.key
    
    harbor_admin_password: ChangezCeMotDePasse!
    
    database:
      password: ChangezAussiCeci!
    
    data_volume: /data
    
    trivy:
      ignore_unfixed: false
      skip_update: false
      offline_scan: false
      security_check: vuln
      insecure: false
  4. Lancer l'installateur

    Harbor propose plusieurs composants optionnels. Activez Trivy (scanner) et Notary (signatures) :

    ./install.sh --with-trivy --with-notary

    L'installateur génère un docker-compose.yml et démarre tous les conteneurs. Vérifiez qu'ils sont tous healthy :

    docker compose ps
    # STATUS attendu pour chaque service : healthy
  5. Première connexion et changement du mot de passe

    Ouvrez https://registry.exemple.com dans votre navigateur. Connectez-vous avec admin / le mot de passe de harbor.yml. Rendez-vous dans Administration → Users → admin et changez immédiatement le mot de passe.

    Depuis votre poste de travail ou votre runner CI :

    docker login registry.exemple.com
    # Entrez votre identifiant admin ou un compte de service
  6. Créer un projet et pousser une première image

    Dans l'interface Harbor, créez un projet mon-projet (privé). Puis depuis votre machine de build :

    docker pull nginx:alpine
    docker tag nginx:alpine registry.exemple.com/mon-projet/nginx:1.27-alpine
    docker push registry.exemple.com/mon-projet/nginx:1.27-alpine
    # Dans Harbor → mon-projet → Repositories : l'image apparaît avec son statut Trivy
  7. Activer le renouvellement TLS automatique

    Créez un hook post-renouvellement Certbot pour recharger Harbor :

    cat > /etc/letsencrypt/renewal-hooks/post/harbor-reload.sh << 'EOF'
    #!/bin/bash
    cp /etc/letsencrypt/live/registry.exemple.com/fullchain.pem /data/cert/registry.exemple.com.crt
    cp /etc/letsencrypt/live/registry.exemple.com/privkey.pem  /data/cert/registry.exemple.com.key
    cd /opt/harbor && docker compose restart proxy
    EOF
    chmod +x /etc/letsencrypt/renewal-hooks/post/harbor-reload.sh

Configuration : projets, utilisateurs et OIDC (ZITADEL)

Projets et RBAC

Harbor organise les images par projets. Chaque projet peut être public ou privé, avec une politique de rétention indépendante. Créez un projet par équipe ou par environnement : frontend, backend, infra. Assignez des membres avec des rôles granulaires :

- Guest : pull uniquement
- Developer : push + pull
- Maintainer : gestion des tags, des webhooks et des politiques de rétention
- ProjectAdmin : gestion des membres

Intégration OIDC avec ZITADEL

Si vous avez déjà déployé ZITADEL (voir l'article dédié), connectez Harbor en quelques clics. Dans ZITADEL, créez une application harbor de type *Web*, notez le Client ID et le Client Secret. Dans Harbor → Administration → Configuration → Authentication :

- Auth Mode : OIDC
- OIDC Provider Name : ZITADEL
- OIDC Endpoint : https://sso.exemple.com
- OIDC Client ID / Secret : ceux de ZITADEL
- OIDC Scope : openid profile email groups
- Cochez Verify Certificate

Au premier login OIDC, Harbor crée automatiquement le compte utilisateur. Désactivez ensuite la création de comptes locaux (Administration → Configuration → Allow Self-Registration → Off).

Scanner les images avec Trivy

Harbor embarque Trivy directement dans le pipeline push. Dès qu'une image est poussée, Harbor déclenche un scan asynchrone qui interroge la base CVE de Trivy (mise à jour quotidienne). Le résultat apparaît dans l'interface : nombre de vulnérabilités par criticité (CRITICAL, HIGH, MEDIUM, LOW, UNKNOWN).

Activer le scan automatique au push : dans Harbor → Administration → Configuration → Vulnerability → cochez *Automatically scan images on push*.

Consulter un rapport : ouvrez un dépôt, cliquez sur un tag → onglet *Vulnerabilities*. Chaque CVE liste le package affecté, la version fixée et un lien vers la NVD.

Version de Trivy dans Harbor v2.15 : Harbor v2.15.4 embarque trivy-adapter aligné sur Trivy v0.55.x, avec support des bases OS (Alpine, Debian, RHEL, Ubuntu), des gestionnaires de paquets applicatifs (npm, pip, cargo, go.mod) et des fichiers de lock.

Politiques de conformité par projet : dans Harbor → *Votre projet* → Policy → *Deployment Security* → choisissez le niveau de criticité qui bloque le pull. Par exemple, bloquer tout pull d'une image ayant au moins une CVE CRITICAL non corrigée.

Conseil sécurité : politiques d'admission Kubernetes

Combinez Harbor avec le contrôleur d'admission Cosign (via Kyverno ou Connaisseur) pour qu'aucune image non signée ou ayant une CVE CRITICAL ne puisse entrer dans votre cluster. Dans votre pipeline CI :

# Signer l'image avec Cosign après le build
cosign sign --key cosign.key registry.exemple.com/mon-projet/nginx:1.27-alpine
# Vérifier en CI avant le déploiement
cosign verify --key cosign.pub registry.exemple.com/mon-projet/nginx:1.27-alpine

Configurer une politique Kyverno qui exige la signature Harbor : chaque pod dont l'image n'est pas signée par votre clé est rejeté à l'admission. Cela ferme la brèche la plus exploitée dans les supply chain attacks post-CVE-2026-21589.

Dépannage : 5 erreurs réelles avec leurs causes

1. Error response from daemon: Get https://registry.exemple.com/v2/: x509: certificate signed by unknown authority
Cause : le certificat Let's Encrypt n'est pas encore propagé ou vous utilisez un certificat auto-signé.
Correction : sur chaque nœud Docker client, copiez fullchain.pem dans /etc/docker/certs.d/registry.exemple.com/ca.crt puis systemctl restart docker.

2. harbor-core redémarre en boucle avec Error 1045 (28000): Access denied for user 'root'@'localhost'
Cause : le volume PostgreSQL contient des données d'une installation précédente avec un autre mot de passe.
Correction : docker compose down -v (⚠️ supprime les données), modifiez le mot de passe dans harbor.yml, relancez ./prepare && docker compose up -d.

3. Scan Trivy bloqué sur Fetching vulnerability DB depuis 10 minutes
Cause : le VPS n'a pas accès à ghcr.io (pare-feu sortant restrictif) pour télécharger la base Trivy.
Correction : autorisez les sorties HTTPS vers ghcr.io et pkg.dev, ou activez le mode offline_scan: true après avoir pré-chargé la base avec trivy image --download-db-only.

4. unauthorized: unauthorized to access repository en CI malgré un docker login réussi
Cause : le compte de service n'a pas le rôle Developer sur le projet ciblé.
Correction : dans Harbor → *Votre projet* → Members → ajoutez le compte robot ou utilisateur avec le rôle Developer ou supérieur.

5. Interface Harbor inaccessible après renouvellement du certificat Let's Encrypt
Cause : le conteneur proxy (nginx) continue à servir l'ancien certificat chargé en mémoire.
Correction : docker compose restart proxy depuis le dossier d'installation Harbor. Idéalement, automatisez-le via le hook post-renouvellement décrit à l'étape 7.

Harbor vs Docker Hub vs GHCR vs Gitea Registry

Faites défiler le tableau

CritèreHarbor self-hostedDocker HubGHCRGitea Registry
HébergementVotre VPS (données UE)Serveurs Docker Inc. (USA)Serveurs GitHub/Microsoft (USA/UE opt.)Votre VPS
Scan de vulnérabilitésTrivy intégré, auto au pushDocker Scout (payant)Aucun natifAucun natif
Signature d'imagesCosign + Notary v2DCT (deprecated)Cosign externeAucun natif
RBAC granulaire5 rôles par projetRôles d'organisation limitésRôles GitHub (coarse)Rôles Gitea basiques
Rate limit (pulls)Aucun100/6h (gratuit), 5000/jour (Pro)Lié aux limites GitHubAucun
OIDC/SSO natifOui (LDAP, OIDC, SAML)Non (SSO entreprise payant)SSO GitHub uniquementOIDC partiel
Audit logs completsOui (IP, user, action, tag)LimitéPartiel via GitHub auditLimité
Conformité NIS2/GDPRTotale (données on-premise)Contractuelle seulementDPA Microsoft disponibleTotale (on-premise)
CoûtVPS (~15-30 €/mois)Gratuit / Pro ~5$/moisInclus GitHub Free/ProVPS partagé avec Gitea

Déployez votre registre Harbor sur un VPS ServOrbit

Un VPS 4 vCPU / 8 Go RAM suffit pour faire tourner Harbor en production pour une équipe de 10 développeurs. ServOrbit livre la VM en moins de 90 secondes, avec accès root SSH et snapshots automatiques inclus.

Besoin d'aide ?

Parcourez notre centre d'aide et notre FAQ, ou contactez notre équipe — rappel, WhatsApp ou e-mail. Support en français, anglais et arabe.

Écrire sur WhatsApps'ouvre dans un nouvel onglet