| HOMELAB Infrastructure auto-hébergée |
PROCÉDURE TECHNIQUE
Raccordement des connecteurs de supervision et passerelles à WatchTower
Configuration des accès d’API de service (Guacamole, NPM, Technitium, Gitea, CrowdSec, Wazuh, Proxmox VE), contournement 2FA et sécurisation du coffre de clés.
| Référence HL-PRC-020 | Version 0.1 | Date d’édition 02/11/2026 |
| Auteur Administrateur système et réseaux | Classification Interne | Statut Brouillon |
Sommaire
Raccordement des connecteurs de supervision et passerelles à WatchTower — HL-PRC-020
1 Objet
Cette procédure détaille l’intégration et le raccordement technique des connecteurs d’infrastructure au sein de la plateforme WatchTower (hébergée dans le conteneur LXC 2013). Elle décrit la création des comptes de service dédiés, la génération des jetons d’authentification pour chaque composant supervisé (passerelle d’accès distant Apache Guacamole, reverse proxy Nginx Proxy Manager, serveur DNS Technitium, forge logicielle Gitea, moteur de sécurité CrowdSec LAPI, pile SIEM Wazuh Indexer et Manager, grappe Proxmox VE et agent Hermes), ainsi que leur enregistrement dans le coffre chiffré de WatchTower. À l’issue de la procédure, l’ensemble des connecteurs doit présenter le statut joignable (« OK »), permettant à WatchTower d’assurer la découverte automatique, la télémétrie unifiée et le pilotage opérationnel, les identifiants étant protégés par le coffre chiffré de WatchTower.
La difficulté principale réside dans la disparité des mécanismes d’authentification des composants tiers et les exigences de fonctionnement « headless » de WatchTower : Apache Guacamole impose par défaut un enrôlement 2FA/TOTP bloquant les connexions automatisées (nécessitant une dérogation au niveau de la base de données PostgreSQL), l’API locale de CrowdSec écoute nativement sur l’interface de boucle locale (127.0.0.1) interdisant les requêtes distantes, la sonde interne WatchTower pour Gitea exige une authentification explicite sur les instances privées (erreur 403 Forbidden corrigée dans le code du catalogue), et la pile Wazuh sépare l’API de gestion (port 55000) du moteur d’indexation (port 9200). Le non-respect de ces particularités provoque des échecs d’authentification silencieux ou des interruptions de service.
2 Périmètre et prérequis
Périmètre
Couvert : création des comptes et jetons de service sur Apache Guacamole, Nginx Proxy Manager, Technitium DNS, Gitea, CrowdSec et Wazuh ; modification de la configuration d’écoute LAPI de CrowdSec ; désactivation ciblée de la contrainte TOTP sur Guacamole pour le compte de service API ; correction de la sonde d’authentification du catalogue WatchTower pour Gitea ; déclaration des identifiants et des URL dans l’interface d’administration WatchTower ; persistance et chiffrement des clés dans le coffre local (/opt/watchtower/donnees/).
Hors périmètre : déploiement initial du conteneur WatchTower et de son API REST (déjà opérationnels) ; configuration des règles de filtrage pare-feu transverses du Juniper SRX300 (traitées dans HL-PRC-001) ; déploiement des services tiers sous-jacents (Gitea, Wazuh, Guacamole, Technitium) ; intégration des assistants conversationnels externes (OpenAI/Anthropic).
Prérequis
• Conteneur WatchTower opérationnel : CT 2013 actif sur pve1, API watchtower-api.service en écoute sur le port 8000, frontend accessible via le reverse proxy NPM (https://watchtower.srv.dozylab.lan).
• Passerelle Apache Guacamole accessible : instance opérationnelle sur 10.10.10.20:8080, base PostgreSQL guacamole_db accessible en local ou via terminal d’administration.
• Reverse Proxy Nginx Proxy Manager fonctionnel : instance active sur 10.10.20.12, port d’administration web 81 joignable en HTTP depuis le VLAN serveurs.
• Serveur Technitium DNS joignable : conteneur 2011 actif sur 10.10.20.11, interface web et API REST opérationnelles sur le port 5380.
• Instance Gitea disponible : conteneur 2014 opérationnel sur 10.10.20.15:3000 avec instance configurée en mode privé (REQUIRE_SIGNIN_VIEW).
• Moteur CrowdSec déployé : serveur opérationnel sur 10.10.20.22, utilitaire cscli accessible en ligne de commande root.
• Pile Wazuh opérationnelle : Wazuh Indexer accessible sur 10.10.20.20:9200 et Wazuh Manager accessible sur 10.10.20.20:55000.
• Grappe Proxmox VE active : nœuds pve1 (10.10.10.10), pve2 (10.10.10.11), pve3 (10.10.10.12) avec API REST active sur le port 8006.
• Agent Hermes déployé : instance active sur 10.10.80.10 avec API server opérationnelle sur le port 8642.
Note Versions validées sur le terrain. Procédure validée le 26/10/2026 sur l’infrastructure DozyLab avec WatchTower v1.0 (branche surcouche/reconciliation-auth-collecteurs), Apache Guacamole v1.5.x, Nginx Proxy Manager v2.11, Technitium DNS Server v13, Gitea v1.22, CrowdSec v1.6, Wazuh v4.9, Proxmox VE 9.x et Debian 12 (bookworm).
3 Rôles et responsabilités
| Rôle | Responsabilité |
| Administrateur système et réseaux | Configure les comptes de service tiers, applique les correctifs de configuration (CrowdSec, WatchTower catalogue), génère les jetons d’accès et valide les sondes de connectivité. |
| Détenteur des secrets | Génère et consigne les mots de passe de service et jetons API dans le coffre-fort centralisé (Vaultwarden), initialise et sauvegarde la clé de chiffrement du coffre WatchTower (coffre.cle ou variable WT_COFFRE_CLE). |
| Exploitant | Surveille la disponibilité des connecteurs dans l’interface WatchTower, consulte les métriques collectées et signale toute perte d’authentification ou expiration de jeton. |
Note Homelab individuel. Les trois rôles sont assumés par la même personne. La distinction est maintenue pour assurer la rigueur opérationnelle, le cloisonnement des privilèges et la traçabilité des accès.
4 Procédure de raccordement des connecteurs
Paramètres de la procédure
Les paramètres ci-dessous fixent les valeurs du lab pour les services supervisés, leurs interfaces d’API et les comptes de service associés.
| Paramètre | Description | Valeur de référence | Contrainte |
| URL_WATCHTOWER | URL frontale d’accès à WatchTower | https://watchtower.srv.dozylab.lan | Résolution DNS vers NPM |
| IP_WATCHTOWER | IP du conteneur WatchTower (CT 2013) | 10.10.20.13 | VLAN 20 (zone srv) |
| DIR_WATCHTOWER | Répertoire d’installation de WatchTower | /opt/watchtower | Système de fichiers CT 2013 |
| URL_GUACAMOLE | URL d’accès à l’API Guacamole | http://10.10.10.20:8080/guacamole | VLAN 10 (chemin /guacamole requis) |
| USER_GUACAMOLE | Compte de service Guacamole | watchtower | Rôle dédié sans 2FA TOTP |
| MDP_GUACAMOLE | Mot de passe du compte Guacamole | [SECRET — NON DOCUMENTÉ] | Stocké dans Vaultwarden |
| URL_NPM | URL d’administration de NPM | http://10.10.20.12:81 | HTTP obligatoire (port 81) |
| USER_NPM | Compte de service NPM | watchtower@dozylab.lan | Permissions All Items |
| MDP_NPM | Mot de passe du compte NPM | [SECRET — NON DOCUMENTÉ] | Stocké dans Vaultwarden |
| URL_TECHNITIUM | URL de l’API Technitium DNS | http://10.10.20.11:5380 | VLAN 20 (zone srv) |
| TOKEN_TECHNITIUM | Jeton d’API Technitium DNS | [SECRET — NON DOCUMENTÉ] | Jeton sans date d’expiration |
| URL_GITEA | URL d’accès à l’API Gitea | http://10.10.20.15:3000 | Port 3000 ou 443 via reverse proxy |
| TOKEN_GITEA | Jeton d’accès personnel Gitea | [SECRET — NON DOCUMENTÉ] | Portées read:repository, read:user |
| URL_CROWDSEC | URL de la LAPI CrowdSec | http://10.10.20.22:8080 | Port TCP 8080 (0.0.0.0) |
| KEY_CROWDSEC | Clé de bouncer CrowdSec | [SECRET — NON DOCUMENTÉ] | Générée par cscli bouncers add |
| URL_WAZUH_INDEXER | URL de l’Indexer Wazuh | https://10.10.20.20:9200 | Port TCP 9200 (TLS sans vérif.) |
| USER_WAZUH_INDEXER | Utilisateur Wazuh Indexer | readall | Compte lecture de sécurité |
| MDP_WAZUH_INDEXER | Mot de passe Wazuh Indexer | [SECRET — NON DOCUMENTÉ] | Stocké dans Vaultwarden |
| URL_WAZUH_API | URL du Manager Wazuh API | https://10.10.20.20:55000 | Port TCP 55000 (TLS sans vérif.) |
| USER_WAZUH_API | Utilisateur API Wazuh Manager | wazuh | Utilisateur interne Wazuh |
| MDP_WAZUH_API | Mot de passe API Wazuh Manager | [SECRET — NON DOCUMENTÉ] | Extrait de la config dashboard |
| NODES_PROXMOX | Adresses des hyperviseurs PVE | 10.10.10.10, .11, .12 | Port 8006 (zone adm) |
| TOKEN_ID_PROXMOX | Identifiant du jeton PVE | watchtower@pve!lecture | Rôle PVEAuditor, privsep 0 |
| URL_HERMES | URL de l’API server Hermes | http://10.10.80.10:8642 | Port 8642 (zone lab) |
| KEY_HERMES | Clé secrète API Hermes | [SECRET — NON DOCUMENTÉ] | Variable API_SERVER_KEY |
Attention Substitution des paramètres. Les blocs de commandes ci-après contiennent les valeurs de référence réelles de l’infrastructure DozyLab. Lors d’une réplication sur un autre environnement, les adresses IP et secrets doivent être substitués avant exécution. Aucun jeton secret ne doit être consigné en clair dans un script non sécurisé.
Inventaire des connecteurs et interfaces cibles
Le tableau ci-dessous récapitule l’ensemble des connecteurs intégrés à WatchTower, leur méthode d’authentification et leurs exigences de communication.
| Service | Type de connecteur | URL / Point de terminaison | Protocole | Mécanisme d’accès |
| Apache Guacamole | Passerelle d’accès | http://10.10.10.20:8080/guacamole | HTTP / REST | User / Password (2FA désactivé) |
| Nginx Proxy Manager | Reverse Proxy | http://10.10.20.12:81 | HTTP / REST | User / Password (Portée All Items) |
| Technitium DNS | Serveur DNS | http://10.10.20.11:5380 | HTTP / REST | API Token permanent (Never expires) |
| Gitea | Forge Git | http://10.10.20.15:3000 | HTTP / REST | Access Token (read:repo, read:user) |
| CrowdSec | Sécurité / LAPI | http://10.10.20.22:8080 | HTTP / LAPI | Bouncer API Key (cscli) |
| Wazuh Indexer | Moteur de recherche | https://10.10.20.20:9200 | HTTPS / REST | Basic Auth (readall, TLS OFF) |
| Wazuh Manager | Gestionnaire SIEM | https://10.10.20.20:55000 | HTTPS / REST | Basic Auth (wazuh / wazuh-wui) |
| Proxmox VE | Virtualisation | https://10.10.10.10:8006 (x3) | HTTPS / REST | API Token (watchtower@pve!lecture) |
| Hermes Agent | Assistant autonome | http://10.10.80.10:8642 | HTTP / REST | API Key (API_SERVER_KEY) |
Étapes de réalisation
1. Raccordement et contournement 2FA de la passerelle Apache Guacamole
Principe et contrainte d’authentification headless : L’extension TOTP de Guacamole force par défaut l’inscription d’un second facteur pour tous les comptes. Lors d’une connexion via l’API REST (POST /api/tokens), Guacamole renvoie une erreur HTTP 403 « TOTP enrollment must be completed before authentication can continue », ce qui empêche tout raccordement automatisé. La création d’une dérogation s’effectue en injectant l’attribut guac-totp-disabled positionné à true dans la base de données PostgreSQL guacamole_db.
1. Se connecter à l’interface web de Guacamole (https://guacamole.adm.dozylab.lan/guacamole) avec le compte administrateur.2. Dans Paramètres > Utilisateurs, cliquer sur Nouvel utilisateur et créer le compte watchtower avec un mot de passe robuste.3. Ne cocher aucun privilège d’administration. Dans la section Connexions, attribuer les droits de lecture aux connexions destinées à être visualisées dans WatchTower.4. Ouvrir une session SSH sur le serveur hébergeant la base PostgreSQL de Guacamole (10.10.10.20) et injecter la dérogation TOTP pour le compte watchtower :
Connexion à PostgreSQL et application de la dérogation 2FA
su – postgres -c "psql -d guacamole_db" << 'EOF'
INSERT INTO guacamole_user_attribute (user_id, attribute_name, attribute_value)
SELECT u.user_id, 'guac-totp-disabled', 'true'
FROM guacamole_user u
JOIN guacamole_entity e ON u.entity_id = e.entity_id
WHERE e.name = 'watchtower'
ON CONFLICT (user_id, attribute_name)
DO UPDATE SET attribute_value = 'true';
EOF
Validation du jeton API sans 2FA : Tester immédiatement la génération d’un jeton d’authentification via l’API REST depuis la console :
curl -s -X POST "http://10.10.10.20:8080/guacamole/api/tokens" \
-d "username=watchtower&password=MOT_DE_PASSE_GUACAMOLE"
Sortie attendue : Un objet JSON contenant "authToken":"…","username":"watchtower","dataSource":"postgresql". Aucune demande d’enrôlement TOTP ne doit être renvoyée.
5. Dans WatchTower > Paramètres > Connecteurs > Guacamole > Configurer : – Adresse : http://10.10.10.20:8080/guacamole (ou https://guacamole.adm.dozylab.lan/guacamole) – Utilisateur : watchtower – Mot de passe : le mot de passe attribué – Vérifier le certificat TLS : désactivé si appel en HTTP direct ou certificat auto-signé.6. Cliquer sur Tester la connexion puis Enregistrer.
2. Configuration du connecteur Nginx Proxy Manager
Protocole d’administration et autorisations : L’interface d’administration de Nginx Proxy Manager écoute nativement sur le port TCP 81 en HTTP simple. Tenter une connexion en HTTPS sur ce port provoque une interruption brutale du handshake SSL. Le compte de service doit disposer des droits de consultation sur l’ensemble des hôtes proxy et des certificats pour que WatchTower puisse inventorier les règles de publication.
1. Se connecter à l’interface d’administration de NPM (http://10.10.20.12:81) avec le compte administrateur.2. Dans le menu Users, cliquer sur Add User et renseigner les informations : – First Name : WatchTower, Last Name : Service – Email : watchtower@dozylab.lan – Roles : cocher Permissions sur All Items (Proxy Hosts, Redirection Hosts, SSL Certificates en mode View). Ne pas attribuer le rôle Administrator.3. Dans l’onglet Permissions, s’assurer que les accès en lecture seule sont validés et enregistrer.4. Dans WatchTower > Paramètres > Connecteurs > Nginx Proxy Manager > Configurer : – Adresse : http://10.10.20.12:81 (impérativement en http:// et non https://) – Adresse de connexion : watchtower@dozylab.lan – Mot de passe : mot de passe du compte de service5. Cliquer sur Tester la connexion puis Enregistrer.
3. Génération du jeton d’API Technitium DNS
Persistance de la session de supervision : L’interrogation des zones et enregistrements Technitium DNS sur le port 5380 s’effectue au moyen d’un jeton d’API (API Token). Pour éviter toute interruption de supervision lors de l’expiration des sessions web, le jeton doit être configuré avec une durée de validité illimitée.
1. Se connecter à l’interface Technitium DNS (http://10.10.20.11:5380).2. Accéder à Administration > Sessions.3. Cliquer sur Create API Token : – Name / Description : watchtower-probe – Validity : Never expires (validité permanente)4. Valider et copier immédiatement le jeton affiché dans le presse-papier.5. Tester la validité du jeton en ligne de commande depuis le conteneur WatchTower :
curl -s "http://10.10.20.11:5380/api/zones/list?token=TOKEN_SECRET" | grep -o '"status":"ok"'
Sortie attendue : "status":"ok".6. Dans WatchTower > Paramètres > Connecteurs > Technitium DNS > Configurer : – Adresse : http://10.10.20.11:5380 – Jeton d’API : coller le jeton généré7. Cliquer sur Tester la connexion puis Enregistrer.
4. Raccordement Gitea et correction de la sonde du catalogue WatchTower
Contradiction doc/terrain et correction logicielle : Sur une instance Gitea configurée en mode privé (directive REQUIRE_SIGNIN_VIEW = true dans app.ini), toute consultation anonyme d’une route d’API — y compris la vérification de version logicielle /api/v1/version — est rejetée avec le code HTTP 403 Forbidden. La sonde interne _sonde_gitea de WatchTower effectuait initialement un appel GET sans en-tête d’autorisation, provoquant l’échec systématique du test de connectivité. Il est impératif d’injecter le jeton d’authentification dans la sonde et de redémarrer le service d’API.
1. Sur l’instance Gitea (http://10.10.20.15:3000), se connecter avec le compte de service ou l’administrateur.2. Accéder à Paramètres > Applications > Gestion des jetons d’accès personnels.3. Générer un nouveau jeton : – Nom du jeton : watchtower-connector – Portées cochées : read:repository, read:organization, read:user4. Copier la chaîne de jeton (visible une seule fois).5. Ouvrir une session sur le conteneur WatchTower (CT 2013) et éditer le fichier du catalogue de connecteurs :
Sauvegarde du fichier de catalogue original
cp /opt/watchtower/apps/api/watchtower_api/connecteurs/catalogue.py \
/opt/watchtower/apps/api/watchtower_api/connecteurs/catalogue.py.bak
6. Dans la fonction _sonde_gitea, remplacer l’appel sans en-tête par l’appel authentifié transmettant le header Authorization: token <jeton> :
Extrait corrigé dans /opt/watchtower/apps/api/watchtower_api/connecteurs/catalogue.py
async def _sonde_gitea(client: httpx.AsyncClient, valeurs: dict[str, Any]) -> tuple[bool, str]:
adresse = valeurs.get("adresse", "").rstrip("/")
jeton = valeurs.get("jeton", "")
headers = {"Authorization": f"token {jeton}"} if jeton else {}
try:
r = await client.get(f"{adresse}/api/v1/version", headers=headers, timeout=5.0)
if r.status_code == 200:
v = r.json().get("version", "inconnue")
return True, f"Gitea {v}"
return False, f"Code HTTP {r.status_code}"
except Exception as e:
return False, str(e)
7. Redémarrer le service API WatchTower pour charger le correctif :
systemctl restart watchtower-api
systemctl status watchtower-api --no-pager
Validation du jeton Gitea en ligne de commande : Vérifier que le jeton permet bien d’interroger l’API avec succès :
curl -i -H "Authorization: token e2800bb86bb78c881998a10cd400daeaf05c145c" \
"http://10.10.20.15:3000/api/v1/user"
Sortie attendue : HTTP/1.1 200 OK avec le corps JSON contenant l’identifiant, le statut is_admin et les paramètres du profil.8. Dans WatchTower > Paramètres > Connecteurs > Gitea > Configurer : – Adresse : http://10.10.20.15:3000 – Jeton d’accès : coller le jeton généré9. Cliquer sur Tester la connexion puis Enregistrer.
5. Déclaration du bouncer CrowdSec et ouverture d’écoute LAPI
Liaison réseau de la LAPI et contrôle d’accès : Par défaut, le démon CrowdSec lie son API locale (LAPI) à l’adresse de bouclage 127.0.0.1:8080. Les requêtes en provenance d’autres conteneurs ou machines du VLAN serveurs sont systématiquement rejetées par le noyau. L’écoute doit être étendue à 0.0.0.0:8080 dans la directive api.server.listen_uri, et une clé de bouncer dédiée doit être enregistrée dans la base CrowdSec.
1. Se connecter en console root sur le serveur CrowdSec (10.10.20.22).2. Enregistrer un bouncer nommé watchtower :
cscli bouncers add watchtower
Sortie attendue : Génération et affichage de la clé d’API du bouncer (chaîne de 32 caractères alphanumériques). Consigner cette clé dans Vaultwarden.3. Éditer le fichier de configuration principal /etc/crowdsec/config.yaml :
Modification de l'écoute LAPI dans /etc/crowdsec/config.yaml
sed -i 's/listen_uri: 127.0.0.1:8080/listen_uri: 0.0.0.0:8080/' /etc/crowdsec/config.yaml
systemctl restart crowdsec
4. Vérifier que le démon écoute bien sur toutes les interfaces réseau :
ss -tlpn | grep 8080
Sortie attendue : LISTEN 0 4096 0.0.0.0:8080 0.0.0.0:* users:(("crowdsec",pid=…,fd=…)).5. Valider la joignabilité de l’API depuis le conteneur WatchTower :
curl -s -H "X-Api-Key: CLE_BOUNCER_CROWDSEC" \
http://10.10.20.22:8080/v1/decisions
Sortie attendue : Réponse JSON (tableau vide [] ou null si aucune décision de bannissement active, prouvant que la clé est acceptée).6. Dans WatchTower > Paramètres > Connecteurs > CrowdSec > Configurer : – Adresse : http://10.10.20.22:8080 – Clé de bouncer : coller la clé générée par cscli7. Cliquer sur Tester la connexion puis Enregistrer.
6. Raccordement des composants Wazuh (Indexer et Manager)
Dissociation de l’indexation et de la gestion : La solution Wazuh all-in-one héberge deux points d’accès distincts : l’Indexer (moteur OpenSearch sur le port TCP 9200) et le Manager (API de pilotage sur le port TCP 55000). Renseigner le port 55000 pour l’Indexer provoque une erreur HTTP 404. De même, les comptes d’authentification diffèrent : l’Indexer utilise un compte de sécurité interne (readall), tandis que le Manager s’appuie sur les utilisateurs de l’API Wazuh.
1. Raccordement du connecteur Wazuh Indexer : – Adresse : https://10.10.20.20:9200 – Utilisateur : readall (compte stocké dans Vaultwarden avec privilèges de lecture sur les index wazuh-alerts-*) – Mot de passe : mot de passe du compte readall – Vérifier le certificat TLS : Décoché (certificat auto-signé natif)2. Vérifier la réponse de l’Indexer en console :
curl -k -u readall:MOT_DE_PASSE https://10.10.20.20:9200/
Sortie attendue : JSON avec "cluster_name":"wazuh-cluster" et "version":{"number":"2.x.x"…}.3. Raccordement du connecteur Wazuh Manager API : – Adresse : https://10.10.20.20:55000 – Utilisateur : wazuh (ou wazuh-wui) – Mot de passe : mot de passe extrait du fichier de configuration du dashboard (/usr/share/wazuh-dashboard/data/wazuh/config/wazuh.yml) – Vérifier le certificat TLS : Décoché4. Tester les deux connecteurs et enregistrer.
7. Raccordement de la grappe Proxmox VE et de l’agent Hermes
Haute disponibilité et privilèges sans séparation : Un jeton d’API unique partagé au niveau de la grappe Proxmox permet de surveiller les trois hyperviseurs (pve1, pve2, pve3). L’option –privsep 0 est rigoureusement obligatoire : avec la séparation de privilèges par défaut (–privsep 1), le jeton s’authentifie avec succès mais n’hérite d’aucun droit d’inventaire sur les nœuds et les conteneurs.
1. Sur le nœud pve1 (la configuration étant répliquée sur toute la grappe via corosync) :
Création du compte d'audit et du jeton sans séparation de privilèges
pveum user add watchtower@pve --comment "Compte de supervision WatchTower"
pveum acl modify / --users watchtower@pve --roles PVEAuditor
pveum user token add watchtower@pve lecture --privsep 0
Sortie attendue : Affichage du Token ID (watchtower@pve!lecture) et de la valeur secrète (value). Copier le secret immédiatement.2. Dans WatchTower > Paramètres > Connecteurs > Proxmox VE > Configurer : – Créer un nœud pour pve1 (https://10.10.10.10:8006), pve2 (https://10.10.10.11:8006) et pve3 (https://10.10.10.12:8006) – Identifiant du jeton : watchtower@pve!lecture – Secret du jeton : valeur secrète générée – Vérifier le certificat TLS : Décoché3. Raccordement de l’agent Hermes : – Récupérer la clé API sur la machine Hermes (10.10.80.10) : grep API_SERVER_KEY ~/.hermes/.env – Dans WatchTower > Connecteurs > Hermes : Adresse http://10.10.80.10:8642, clé API_SERVER_KEY – Adresse tableau de bord : http://10.10.80.10:9119 avec identifiants admin.4. Valider l’ensemble des tests de connexion.
8. Initialisation du coffre de clés et vérification globale des sondes
Chiffrement local et intégrité de session : Au premier enregistrement d’un connecteur, WatchTower initialise automatiquement sa clé de chiffrement symétrique dans le fichier /opt/watchtower/donnees/coffre.cle. Les requêtes de test exécutées depuis l’interface web s’appuient sur un jeton JWT dont la validité est de 15 minutes. Si la session expire, l’interface renvoie une erreur 401 Unauthorized « Refusé : Session requise », imposant une réauthentification avant de poursuivre les tests.
1. Se connecter à l’interface WatchTower (https://watchtower.srv.dozylab.lan).2. Dans Paramètres > Connecteurs, cliquer sur le bouton Tout tester.3. Vérifier que le compteur en en-tête affiche l’ensemble des connecteurs au vert (« Joignable »).4. Ouvrir une session SSH sur le conteneur WatchTower et contrôler la création et les permissions du coffre chiffré :
ls -la /opt/watchtower/donnees/
file /opt/watchtower/donnees/coffre.cle
Sortie attendue : Le fichier coffre.cle est présent avec les droits stricts 600 (-rw——-) appartenant au propriétaire du service api.5. Sauvegarder la clé du coffre dans Vaultwarden (élément WatchTower – Coffre Clé) pour faciliter la recouvrabilité en cas de restauration du conteneur sans volume persistant.
Retour arrière
En cas de dysfonctionnement bloquant lors de la configuration des connecteurs ou de l’application des correctifs, exécuter les actions ci-dessous :
| Situation | Cause / Constat | Action de retour arrière |
| Régression de service sur l’API WatchTower | Erreur de syntaxe ou régression suite au patch de catalogue.py | Restaurer la sauvegarde : cp /opt/watchtower/…/catalogue.py.bak /opt/watchtower/…/catalogue.py puis systemctl restart watchtower-api. |
| Échec d’écoute CrowdSec après modification | Erreur d’indentation YAML dans config.yaml empêchant le démarrage | Rétablir listen_uri: 127.0.0.1:8080 dans /etc/crowdsec/config.yaml et exécuter systemctl restart crowdsec. |
| Blocage de compte sur Apache Guacamole | Erreur lors de l’injection SQL ou corruption de la table des attributs | Exécuter DELETE FROM guacamole_user_attribute WHERE attribute_name = 'guac-totp-disabled' AND user_id = (SELECT user_id FROM guacamole_user u JOIN guacamole_entity e ON u.entity_id = e.entity_id WHERE e.name = 'watchtower');. |
| Perte de la clé du coffre WatchTower | Fichier coffre.cle accidentellement supprimé ou corrompu (erreur HTTP 503) | Restaurer le fichier coffre.cle depuis la sauvegarde Vaultwarden ou définir la variable d’environnement WT_COFFRE_CLE dans /opt/watchtower/.env. |
Pièges connus
Les anomalies ci-après ont été réellement constatées lors des opérations de raccordement et de qualification des connecteurs dans l’infrastructure DozyLab.
| Symptôme rencontré | Cause identifiée | Résolution appliquée |
| HTTP 403: TOTP enrollment must be completed before authentication can continue | Guacamole force l’enrôlement 2FA pour tous les comptes. L’API REST rejette le compte de service headless. | Insérer l’attribut guac-totp-disabled = 'true' dans la table PostgreSQL guacamole_user_attribute pour l’entité watchtower. |
| curl: (7) Failed to connect to localhost port 8080 sur Guacamole | La JVM Tomcat écoute sur l’IP physique (10.10.10.20) et non sur la boucle locale 127.0.0.1. | Spécifier impérativement l’adresse IP réelle 10.10.10.20 ou le FQDN dans la configuration du connecteur WatchTower. |
| SSL / TLS Certificate Error sur Nginx Proxy Manager port 81 | Le connecteur a été configuré avec le schéma https:// alors que l’interface NPM écoute en HTTP simple sur le port 81. | Remplacer l’URL du connecteur par http://10.10.20.12:81 dans WatchTower. |
| HTTP 403 Forbidden sur /api/v1/version lors du test Gitea | Instance Gitea privée interdisant la consultation anonyme de version ; la sonde WatchTower n’envoyait aucun jeton. | Patcher la fonction _sonde_gitea dans catalogue.py pour transmettre le header Authorization: token <jeton> et redémarrer l’API. |
| HTTP 404 Not Found lors de la validation Wazuh | Inversion des ports d’écoute : port 55000 utilisé pour l’Indexer au lieu du port 9200. | Configurer l’Indexer sur le port 9200 (https://10.10.20.20:9200) et le Manager sur le port 55000. |
| Connection refused sur la LAPI CrowdSec port 8080 | Par défaut, CrowdSec lie la LAPI sur 127.0.0.1:8080, rejetant les paquets du VLAN serveurs. | Remplacer listen_uri: 127.0.0.1:8080 par listen_uri: 0.0.0.0:8080 dans /etc/crowdsec/config.yaml et redémarrer. |
| HTTP 401: Refusé : Session requise dans l’interface web | Expiration du jeton de session JWT administrateur de WatchTower après 15 minutes d’inactivité. | Se reconnecter sur le portail web de WatchTower pour renouveler le cookie de session avant de relancer les tests. |
| Jeton Proxmox validé mais aucun nœud n’apparaît | Le jeton d’API a été généré avec la séparation de privilèges par défaut (–privsep 1). | Recréer le jeton avec l’option –privsep 0 pour hériter de l’intégralité des privilèges du rôle PVEAuditor. |
5 Intégration réseau
Identité des instances
Le tableau ci-dessous recense l’ensemble des composants intervenant dans l’architecture de supervision et leur localisation dans les zones de sécurité.
| Composant | Rôle fonctionnel | Adresse IP / FQDN | Zone pare-feu SRX |
| WatchTower (CT 2013) | Plateforme centrale de supervision | 10.10.20.13 / watchtower.srv.dozylab.lan | srv (VLAN 20) |
| NPM (VM 2012) | Reverse Proxy frontal et terminaison TLS | 10.10.20.12 / srv01.adm.dozylab.lan | srv (VLAN 20) |
| Technitium (CT 2011) | Serveur DNS autoritaire et récursif | 10.10.20.11 / dns.srv.dozylab.lan | srv (VLAN 20) |
| Gitea (CT 2014) | Forge logicielle et gestion de code | 10.10.20.15 / git.srv.dozylab.lan | srv (VLAN 20) |
| CrowdSec | Moteur de détection et LAPI | 10.10.20.22 / crowdsec.srv.dozylab.lan | srv (VLAN 20) |
| Wazuh SIEM | Indexer (9200) et Manager (55000) | 10.10.20.20 / wazuh.srv.dozylab.lan | srv (VLAN 20) |
| Apache Guacamole | Passerelle d’accès HTML5 | 10.10.10.20 / guacamole.adm.dozylab.lan | adm (VLAN 10) |
| Grappe Proxmox VE | Hyperviseurs pve1, pve2, pve3 | 10.10.10.10, .11, .12 / pve*.adm.dozylab.lan | adm (VLAN 10) |
| Agent Hermes | Agent conversationnel d’administration | 10.10.80.10 / hermes.lab.dozylab.lan | lab (VLAN 80) |
| Juniper SRX300 | Passerelle de routage et pare-feu | 10.10.10.254 / fw01.adm.dozylab.lan | Passerelle inter-zones |
Plan d’adressage et interfaces
| VLAN | Nom de zone | Sous-réseau | Passerelle SRX300 / Interface |
| VLAN 10 | adm (Administration) | 10.10.10.0/24 | 10.10.10.254 (ge-0/0/1.10) |
| VLAN 20 | srv (Serveurs) | 10.10.20.0/24 | 10.10.20.254 (ge-0/0/1.20) |
| VLAN 80 | lab (Expérimentation) | 10.10.80.0/24 | 10.10.80.254 (ge-0/0/1.80) |
Matrice des flux réseau
| Source | Destination | Port | Protocole | Application Junos | Statut |
| Postes clients | NPM (10.10.20.12) | 443 | TCP | junos-https | Autorisé |
| NPM (10.10.20.12) | WatchTower (10.10.20.13) | 8000 | TCP | p-intra-srv | Autorisé |
| WatchTower (10.10.20.13) | Guacamole (10.10.10.20) | 8080 | TCP | p-srv-to-adm-guac | Autorisé |
| WatchTower (10.10.20.13) | Proxmox (10.10.10.10-12) | 8006 | TCP | PVE-8006 | Autorisé |
| WatchTower (10.10.20.13) | NPM (10.10.20.12) | 81 | TCP | p-intra-srv | Autorisé |
| WatchTower (10.10.20.13) | Technitium (10.10.20.11) | 5380 | TCP | p-intra-srv | Autorisé |
| WatchTower (10.10.20.13) | Gitea (10.10.20.15) | 3000 | TCP | p-intra-srv | Autorisé |
| WatchTower (10.10.20.13) | CrowdSec (10.10.20.22) | 8080 | TCP | p-intra-srv | Autorisé |
| WatchTower (10.10.20.13) | Wazuh Indexer (10.10.20.20) | 9200 | TCP | p-intra-srv | Autorisé |
| WatchTower (10.10.20.13) | Wazuh Manager (10.10.20.20) | 55000 | TCP | p-intra-srv | Autorisé |
| WatchTower (10.10.20.13) | Hermes (10.10.80.10) | 8642, 9119 | TCP | p-srv-to-lab-hermes | Autorisé |
Dépendances et points de défaillance
| Composant d’infrastructure | Impact opérationnel en cas d’indisponibilité |
| Conteneur WatchTower (CT 2013) | Interruption du tableau de bord de supervision unifié ; les services supervisés continuent de fonctionner de manière autonome. |
| Nginx Proxy Manager (10.10.20.12) | Perte de l’accès HTTPS public au tableau de bord WatchTower. L’accès direct sur http://10.10.20.13:8000 demeure accessible en intra-VLAN. |
| Pare-feu Juniper SRX300 | Coupure des flux inter-zones (VLAN 20 vers VLAN 10 et VLAN 80). Perte de télémétrie sur Proxmox VE, Guacamole et Hermes. |
| Technitium DNS (10.10.20.11) | Échec de résolution des FQDN internes (*.dozylab.lan). Les connecteurs configurés par adresse IP restent joignables. |
6 Durcissement et sécurité
• Principe de moindre privilège sur les comptes de service : Aucun connecteur n’utilise de compte administrateur racine (root, admin global). Chaque composant est configuré avec un compte d’audit dédié restreint à la seule lecture (PVEAuditor sur Proxmox, rôle Viewer sur NPM, compte readall sur Wazuh Indexer).
• Chiffrement symétrique des secrets au repos : L’intégralité des identifiants et jetons enregistrés dans WatchTower est chiffrée de manière symétrique dans /opt/watchtower/donnees/ au moyen d’une clé locale (coffre.cle). Les secrets ne figurent jamais en clair dans la base de données applicative.
• Cloisonnement strict par zones pare-feu : Le conteneur WatchTower réside dans le VLAN serveurs (zone srv). Ses communications vers les hyperviseurs de gestion (zone adm) et l’agent Hermes (zone lab) sont strictement filtrées par port sur le pare-feu Juniper SRX300.
• Exclusion des secrets de la gestion de versions : Le dossier /opt/watchtower/donnees/ et le fichier .env sont exclus de l’arbre Git via le fichier .gitignore, garantissant qu’aucune clé ou jeton ne soit poussé sur les forges publiques ou privées.
• Contrôle d’accès aux fichiers sensibles du système : Le fichier /opt/watchtower/donnees/coffre.cle est protégé par les droits stricts 600 (-rw——-), interdisant sa lecture par tout autre utilisateur que le service système watchtower-api.
Dettes techniques
| Point technique identifié | Impact potentiel sur la sécurité | État / Arbitrage retenu |
| Désactivation de la vérification TLS sur les connecteurs | Risque théorique d’interception (MitM) sur le segment réseau local en cas de compromission du commutateur. | Toléré en homelab ; raccordement planifié à l’autorité de certification interne step-ca. |
| Dérogation 2FA TOTP sur le compte Guacamole | Le compte watchtower ne bénéficie pas de la double authentification en cas de fuite du mot de passe. | Mitigé : mot de passe fort (>20 caractères) consigné dans Vaultwarden et droits restreints à la consultation. |
| Écoute CrowdSec LAPI sur 0.0.0.0 au lieu d’une IP liée | L’API locale écoute sur toutes les interfaces réseau du serveur CrowdSec. | Accepté : accès protégé par clé de bouncer de 32 caractères et filtrage pare-feu inter-VLAN. |
| Clé du coffre WatchTower stockée sur le système local | La compromission complète du conteneur CT 2013 permettrait à un attaquant de lire coffre.cle et de déchiffrer les connecteurs. | Évolution prévue : injection de la clé via la variable WT_COFFRE_CLE alimentée dynamiquement par Vaultwarden. |
7 Vérifications finales
Exécuter les contrôles ci-dessous pour prononcer la recette fonctionnelle et la qualification des connecteurs de WatchTower.
| Point de contrôle | Critère d’acceptation mesurable | Statut |
| Authentification API Guacamole | curl -s -X POST http://10.10.10.20:8080/guacamole/api/tokens -d "username=watchtower&…" retourne un JSON avec authToken valide sans prompt 2FA | ☐ |
| Sonde API Nginx Proxy Manager | Le connecteur NPM affiche le statut vert (« Joignable ») dans WatchTower et retourne les métriques d’hôtes proxy | ☐ |
| Interrogation API Technitium DNS | curl -s "http://10.10.20.11:5380/api/zones/list?token=…" retourne "status":"ok" | ☐ |
| Sonde Gitea authentifiée | La sonde WatchTower /api/v1/version avec en-tête d’autorisation retourne le statut joignable (« Gitea 1.22 ») au lieu de l’erreur 403 | ☐ |
| Écoute et décision CrowdSec LAPI | curl -s -H "X-Api-Key: …" http://10.10.20.22:8080/v1/decisions répond HTTP 200 (JSON vide ou liste) | ☐ |
| Joignabilité Wazuh Indexer (port 9200) | curl -k -u readall:… https://10.10.20.20:9200/ retourne le nom du cluster wazuh-cluster en HTTP 200 | ☐ |
| Joignabilité Wazuh Manager (port 55000) | Le connecteur Wazuh Manager affiche le statut joignable dans l’interface WatchTower | ☐ |
| Découverte de la grappe Proxmox VE | Les trois nœuds pve1, pve2 et pve3 affichent le statut en ligne avec leurs métriques de charge CPU/RAM | ☐ |
| Intégrité du coffre chiffré | Le fichier /opt/watchtower/donnees/coffre.cle existe avec les droits 600 et le coffre conserve les clés après redémarrage | ☐ |
8 Références et historique des révisions
Documentation éditeur
• Apache Guacamole Project : Guacamole Manual — REST API Authentication and TOTP Extension Configuration (2026). Établit la structure des requêtes API tokens et la table des attributs utilisateurs.
• CrowdSec : CrowdSec Documentation — Local API (LAPI) and Bouncers Configuration (2026). Établit les paramètres de liaison réseau (listen_uri) et l’enregistrement de bouncers.
• Gitea Project : Gitea Documentation — API Authentication and Private Instance Scopes (2026). Établit l’obligation d’en-tête d’autorisation sur instance privée.
• Nginx Proxy Manager : Official Documentation — Host Configuration, Custom SSL and Admin API (2026). Établit les prérequis de droits sur le port 81.
• Technitium : Technitium DNS Server HTTP API Documentation (2026). Établit la syntaxe des jetons d’authentification permanents.
• Wazuh Server Solutions : Wazuh User Manual — RESTful API Reference and Indexer Authentication (2026). Établit la distinction entre les ports 55000 et 9200.
• Proxmox Server Solutions : Proxmox VE Administration Guide — API Tokens and Privileges Separation (2026). Établit le rôle PVEAuditor et l’option –privsep 0.
Documents associés
• HL-PRC-001 : Mise en service du pare-feu Juniper SRX300.
• HL-PRC-003 : Mise en service de la grappe Proxmox à trois nœuds.
• HL-PRC-004 : Technitium DNS.
• HL-PRC-006 : Wazuh all-in-one.
• HL-PRC-007 : Hermes Agent.
• HL-PRC-010 : Guacamole — Connexion SSH par clé.
• HL-PRC-012 : Publication de ProxPanel via Nginx Proxy Manager.
Historique des révisions
| Version | Date | Auteur | Modifications |
| 0.1 | 02/11/2026 | Administrateur système et réseaux | Création du document à partir de l’intervention réelle. |