Projet · Phase 4.3

Phase 4 (3/3) — Harbor & Jenkins en HTTPS (ACME + HAProxy)

En HTTP, Docker refuse de pousser vers Harbor et le navigateur crie à l'insécurité. On met en place de vrais certificats (ACME/Let's Encrypt) et un reverse proxy (HAProxy) sur OPNsense — puis on valide avec un compte robot Harbor.

⏱ ~2 h 30Niveau avancéPrérequis : Phase 4 (2/3)Pratique · TP
L’idée reçue

« Sur mon réseau privé, le HTTP suffit pour Harbor et Jenkins. »

Dès que tu essaies un vrai docker push, Docker refuse : il exige HTTPS. Et le navigateur affiche « non sécurisé » sur Jenkins. Le TLS n’est pas un luxe : c’est ce qui rend ces services opérationnels. On va leur donner de vrais certificats, automatiquement renouvelés, et un point d’entrée unique et sûr.

Architecture cible : le pare-feu OPNsense devient le point d’entrée HTTPS. Il obtient des certificats via ACME (Let’s Encrypt, défi DNS-01 avec l’API OVH), puis un reverse proxy HAProxy (plugin OPNsense) termine le TLS et route vers Harbor et Jenkins selon le nom de domaine demandé. Aucune VM supplémentaire : tout tient sur OPNsense.

!
Hypothèse. Le DNS de ton domaine est géré chez OVH (pour automatiser le défi DNS-01 via l’API OVH). Si ton DNS est ailleurs, choisis le fournisseur correspondant dans l’ACME client. Remplace partout mondomaine.fr par ton domaine.

À la fin de ce module, tu sauras…

  • Créer les enregistrements DNS pointant vers ton IP publique
  • Émettre des certificats Let’s Encrypt via ACME et le défi DNS-01 (API OVH)
  • Configurer HAProxy (real server, backend, condition, public service) en suivant la doc officielle
  • Rendre Harbor et Jenkins accessibles en HTTPS, et valider avec un compte robot Harbor

01Le DNS : faire pointer les noms

Expérience 1

Des enregistrements A vers ton IP publique

Dans l’espace OVH (zone DNS de ton domaine), crée deux enregistrements A pointant vers l’IP publique du WAN d’OPNsense (celle portée par la MAC virtuelle, Phase 2) :

TypeNomCible
Aharbor.mondomaine.frIP publique WAN OPNsense
Ajenkins.mondomaine.frIP publique WAN OPNsense
Manipule
dig +short harbor.mondomaine.fr
dig +short jenkins.mondomaine.fr
Les deux noms renvoient ton IP publique. Le DNS peut prendre quelques minutes à se propager.
Comprends pourquoi tout pointe au même endroit

Les deux sous-domaines pointent vers la même IP : celle d’OPNsense. C’est le reverse proxy qui, ensuite, distinguera harbor.* de jenkins.* et enverra vers le bon service. Un seul point d’entrée public, plusieurs services derrière.

02Préparer l’accès à l’API OVH

Expérience 2

Des clés pour que l’automate crée les enregistrements de validation

Le défi DNS-01 prouve que tu possèdes le domaine en créant un enregistrement TXT temporaire. Pour l’automatiser, ACME a besoin d’accéder à l’API OVH. Génère un jeu de clés sur le créateur de tokens OVH (eu.api.ovh.com/createToken) avec les droits sur les enregistrements DNS de ta zone :

CléRôle
Application Keyidentifie l’application
Application Secretsecret associé
Consumer Keyautorise l’accès à ta zone DNS
Donne les droits GET/POST/DELETE sur /domain/zone/mondomaine.fr/*. Conserve ces trois clés : l’ACME client les utilisera.
Comprends pourquoi le DNS-01, et pas le HTTP-01

Le défi HTTP-01 exige d’ouvrir le port 80 depuis Internet vers un service — moins pratique et plus exposé. Le DNS-01 prouve la possession du domaine via un enregistrement TXT, sans rien ouvrir. Bonus : il permet des certificats wildcard (*.mondomaine.fr), pratiques quand on a plusieurs sous-domaines.

03L’ACME client : émettre le certificat

Expérience 3

Installer et configurer os-acme-client

Sur OPNsense : System → Firmware → Plugins, installe os-acme-client. Le menu Services → ACME Client apparaît. Configure dans l’ordre :

  1. Accounts : crée un compte Let’s Encrypt (ton e-mail).
  2. Challenge Types : ajoute un défi DNS-01, choisis le service DNS OVH, et colle tes trois clés API (endpoint ovh-eu).
  3. Certificates : ajoute un certificat pour harbor.mondomaine.fr et jenkins.mondomaine.fr (ou un wildcard *.mondomaine.fr), en liant le compte et le défi DNS-01.

Lance l’émission (bouton issue/renew) et surveille le journal.

Observe
AcmeClient: using challenge type: dns01 (OVH)
AcmeClient: certificate issued: harbor.mondomaine.fr ...
Le certificat est émis et stocké dans OPNsense (System → Trust → Certificates). Le renouvellement sera automatique.
Comprends ce que fait l’ACME client, sous le capot

Le plugin s’appuie sur acme.sh. Pour OVH, il appelle l’API pour créer le TXT _acme-challenge.*, laisse Let’s Encrypt le vérifier, récupère le certificat, puis nettoie le TXT — le tout automatiquement, et à chaque renouvellement. Tu obtiens un certificat de confiance publique, sans intervention manuelle.

04HAProxy : le reverse proxy

Expérience 4

Router vers Harbor et Jenkins selon le nom demandé

Installe le plugin os-haproxy. La configuration suit une chaîne logique — les termes sont ceux de la documentation officielle HAProxy/OPNsense :

Élément HAProxyCe qu’on y met
Real Serversharbor → 192.168.10.20:80 · jenkins → IP:8080
Backend Poolsun backend par service, contenant son real server
Conditions« SNI/Host TLS commence par harbor.mondomaine.fr » (et idem jenkins)
Rulessi condition harbor → utiliser backend harbor ; si jenkins → backend jenkins
Public Service (frontend)écoute sur le WAN :443, type HTTP/SSL offloading, certificat = celui d’ACME, applique les rules

Active HAProxy (Settings → enable) et applique. Ouvre le port 443 du WAN vers OPNsense si nécessaire (règle pare-feu).

Observe
Depuis debian-gui, ouvre https://jenkins.mondomaine.fr : le cadenas est vert, le certificat est valide. HAProxy a terminé le TLS et routé vers Jenkins.
Comprends la chaîne real server → backend → condition → rule → frontend

Un real server est la cible réelle (IP:port). Un backend regroupe des real servers. Une condition teste la requête (ici le nom demandé, via SNI). Une rule associe « si condition alors backend ». Le public service (frontend) écoute sur 443, présente le certificat, et applique les rules. C’est le schéma standard d’un reverse proxy — vérifie chaque champ dans la doc officielle, qui fait autorité.

05Adapter Harbor & Jenkins au HTTPS

Expérience 5

Dire aux services leur nouvelle adresse publique

Le TLS est terminé par HAProxy, mais les services doivent connaître leur URL publique. Sur la VM Harbor, édite harbor.yml :

Manipule
external_url: https://harbor.mondomaine.fr

Puis régénère la configuration et redémarre Harbor :

Manipule
cd /opt/harbor
sudo ./prepare
sudo docker compose down
sudo docker compose up -d
Côté Jenkins, va dans Administer Jenkins → System et fixe l’URL sur https://jenkins.mondomaine.fr. Les deux services se savent désormais publiés en HTTPS.
Comprends pourquoi external_url est crucial

Harbor renvoie des URLs (tokens, liens de couches) basées sur son external_url. S’il croit être en HTTP alors qu’on l’atteint en HTTPS, docker push/pull échoue avec des erreurs déroutantes. Aligner external_url sur l’adresse réelle (HTTPS) est la clé pour que le registre fonctionne derrière le proxy.

06Le test qui valide tout : un compte robot

Expérience 6

push & pull en HTTPS, avec un compte robot Harbor

Dans Harbor : projet soriaRobot Accounts → crée un robot avec droits push/pull. Note son nom (robot$soria+ci) et son secret.

Depuis la VM mgmt (notre point de déploiement), connecte-toi en HTTPS et fais l’aller-retour :

Manipule
docker login harbor.mondomaine.fr -u 'robot$soria+ci'
docker pull nginx:1.27-alpine
docker tag nginx:1.27-alpine harbor.mondomaine.fr/soria/test-https:1.0
docker push harbor.mondomaine.fr/soria/test-https:1.0
docker rmi harbor.mondomaine.fr/soria/test-https:1.0
docker pull harbor.mondomaine.fr/soria/test-https:1.0
Observe
Le push et le pull réussissent, sans aucune option « insecure registry » : la chaîne TLS est reconnue. Harbor et Jenkins sont désormais pleinement opérationnels.
Comprends pourquoi un compte robot, et pas admin

Un compte robot est une identité machine, avec des droits limités et un secret révocable — parfait pour l’automatisation (bientôt : Jenkins). On n’utilise jamais le compte admin pour ça. C’est le même principe de moindre privilège que pour l’utilisateur d’un service Linux : chaque automate a sa propre identité, restreinte.

Ce que tu retiens

Rendre un service opérationnel = lui donner du HTTPS. On a fait pointer le DNS vers l’IP publique, émis des certificats via ACME (défi DNS-01, API OVH) sur OPNsense, puis routé le trafic avec HAProxy (real server → backend → condition → rule → public service). Harbor et Jenkins sont en ligne, validés par un compte robot. L’infrastructure de base est prête pour l’orchestration.

Mini-projet — clôture de la Phase 4

Deux services opérationnels en HTTPS

À faire

  1. Crée les enregistrements A pour harbor et jenkins vers ton IP publique.
  2. Émets les certificats via ACME (DNS-01 / OVH) sur OPNsense.
  3. Configure HAProxy : real servers, backends, conditions, rules, public service (443 + certificat).
  4. Aligne external_url de Harbor et l’URL de Jenkins sur le HTTPS.
  5. Crée un compte robot et prouve un push/pull en HTTPS depuis mgmt.
  6. Snapshots : OPNsense et Harbor, nommés phase4-https-ok.
  7. Documente dans BookStack le chemin d’une requête : navigateur → HAProxy (TLS) → backend.
Fil rouge — Ton registre et ton serveur d’automatisation sont opérationnels et sécurisés. Tu as tout : code (GitHub), images (Harbor en HTTPS), réseau propre. À la Phase 5, on déploie enfin à l’échelle avec Kubernetes — manuellement d’abord, pour tout comprendre.

?Auto-évaluation

1. Pourquoi le défi DNS-01 plutôt que HTTP-01 ici ?

Il prouve la possession du domaine sans ouvrir de port, et permet les certificats wildcard. Il s’automatise via l’API OVH.

2. Dans HAProxy, quel élément décide vers quel service router ?

La condition (sur le nom demandé / SNI) combinée à une rule, qui pointe vers le backend correspondant. Le public service écoute sur 443 et présente le certificat.

3. Pourquoi aligner external_url de Harbor sur le HTTPS ?

Harbor construit ses URLs à partir de external_url ; s’il se croit en HTTP derrière un proxy HTTPS, push/pull échouent. L’aligner corrige ces erreurs.

4. Pourquoi utiliser un compte robot pour push/pull ?

C’est une identité machine à droits limités et secret révocable, adaptée à l’automatisation — sans exposer le compte admin.

Connecte-toi pour enregistrer ta progression.

Suite → Phase 5 — L'orchestration (Kubernetes)