HL-PRC-020 — WatchTower — raccordement des connecteurs de supervision

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ôleResponsabilité
Administrateur système et réseauxConfigure 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 secretsGé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).
ExploitantSurveille 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ètreDescriptionValeur de référenceContrainte
URL_WATCHTOWERURL frontale d’accès à WatchTowerhttps://watchtower.srv.dozylab.lanRésolution DNS vers NPM
IP_WATCHTOWERIP du conteneur WatchTower (CT 2013)10.10.20.13VLAN 20 (zone srv)
DIR_WATCHTOWERRépertoire d’installation de WatchTower/opt/watchtowerSystème de fichiers CT 2013
URL_GUACAMOLEURL d’accès à l’API Guacamolehttp://10.10.10.20:8080/guacamoleVLAN 10 (chemin /guacamole requis)
USER_GUACAMOLECompte de service GuacamolewatchtowerRôle dédié sans 2FA TOTP
MDP_GUACAMOLEMot de passe du compte Guacamole[SECRET — NON DOCUMENTÉ]Stocké dans Vaultwarden
URL_NPMURL d’administration de NPMhttp://10.10.20.12:81HTTP obligatoire (port 81)
USER_NPMCompte de service NPMwatchtower@dozylab.lanPermissions All Items
MDP_NPMMot de passe du compte NPM[SECRET — NON DOCUMENTÉ]Stocké dans Vaultwarden
URL_TECHNITIUMURL de l’API Technitium DNShttp://10.10.20.11:5380VLAN 20 (zone srv)
TOKEN_TECHNITIUMJeton d’API Technitium DNS[SECRET — NON DOCUMENTÉ]Jeton sans date d’expiration
URL_GITEAURL d’accès à l’API Giteahttp://10.10.20.15:3000Port 3000 ou 443 via reverse proxy
TOKEN_GITEAJeton d’accès personnel Gitea[SECRET — NON DOCUMENTÉ]Portées read:repository, read:user
URL_CROWDSECURL de la LAPI CrowdSechttp://10.10.20.22:8080Port TCP 8080 (0.0.0.0)
KEY_CROWDSECClé de bouncer CrowdSec[SECRET — NON DOCUMENTÉ]Générée par cscli bouncers add
URL_WAZUH_INDEXERURL de l’Indexer Wazuhhttps://10.10.20.20:9200Port TCP 9200 (TLS sans vérif.)
USER_WAZUH_INDEXERUtilisateur Wazuh IndexerreadallCompte lecture de sécurité
MDP_WAZUH_INDEXERMot de passe Wazuh Indexer[SECRET — NON DOCUMENTÉ]Stocké dans Vaultwarden
URL_WAZUH_APIURL du Manager Wazuh APIhttps://10.10.20.20:55000Port TCP 55000 (TLS sans vérif.)
USER_WAZUH_APIUtilisateur API Wazuh ManagerwazuhUtilisateur interne Wazuh
MDP_WAZUH_APIMot de passe API Wazuh Manager[SECRET — NON DOCUMENTÉ]Extrait de la config dashboard
NODES_PROXMOXAdresses des hyperviseurs PVE10.10.10.10, .11, .12Port 8006 (zone adm)
TOKEN_ID_PROXMOXIdentifiant du jeton PVEwatchtower@pve!lectureRôle PVEAuditor, privsep 0
URL_HERMESURL de l’API server Hermeshttp://10.10.80.10:8642Port 8642 (zone lab)
KEY_HERMESClé 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.

ServiceType de connecteurURL / Point de terminaisonProtocoleMécanisme d’accès
Apache GuacamolePasserelle d’accèshttp://10.10.10.20:8080/guacamoleHTTP / RESTUser / Password (2FA désactivé)
Nginx Proxy ManagerReverse Proxyhttp://10.10.20.12:81HTTP / RESTUser / Password (Portée All Items)
Technitium DNSServeur DNShttp://10.10.20.11:5380HTTP / RESTAPI Token permanent (Never expires)
GiteaForge Githttp://10.10.20.15:3000HTTP / RESTAccess Token (read:repo, read:user)
CrowdSecSécurité / LAPIhttp://10.10.20.22:8080HTTP / LAPIBouncer API Key (cscli)
Wazuh IndexerMoteur de recherchehttps://10.10.20.20:9200HTTPS / RESTBasic Auth (readall, TLS OFF)
Wazuh ManagerGestionnaire SIEMhttps://10.10.20.20:55000HTTPS / RESTBasic Auth (wazuh / wazuh-wui)
Proxmox VEVirtualisationhttps://10.10.10.10:8006 (x3)HTTPS / RESTAPI Token (watchtower@pve!lecture)
Hermes AgentAssistant autonomehttp://10.10.80.10:8642HTTP / RESTAPI 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 :

SituationCause / ConstatAction de retour arrière
Régression de service sur l’API WatchTowerErreur de syntaxe ou régression suite au patch de catalogue.pyRestaurer la sauvegarde : cp /opt/watchtower/…/catalogue.py.bak /opt/watchtower/…/catalogue.py puis systemctl restart watchtower-api.
Échec d’écoute CrowdSec après modificationErreur d’indentation YAML dans config.yaml empêchant le démarrageRétablir listen_uri: 127.0.0.1:8080 dans /etc/crowdsec/config.yaml et exécuter systemctl restart crowdsec.
Blocage de compte sur Apache GuacamoleErreur lors de l’injection SQL ou corruption de la table des attributsExé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 WatchTowerFichier 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éeRésolution appliquée
HTTP 403: TOTP enrollment must be completed before authentication can continueGuacamole 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 GuacamoleLa 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 81Le 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 GiteaInstance 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 WazuhInversion 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 8080Par 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 webExpiration 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îtLe 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é.

ComposantRôle fonctionnelAdresse IP / FQDNZone pare-feu SRX
WatchTower (CT 2013)Plateforme centrale de supervision10.10.20.13 / watchtower.srv.dozylab.lansrv (VLAN 20)
NPM (VM 2012)Reverse Proxy frontal et terminaison TLS10.10.20.12 / srv01.adm.dozylab.lansrv (VLAN 20)
Technitium (CT 2011)Serveur DNS autoritaire et récursif10.10.20.11 / dns.srv.dozylab.lansrv (VLAN 20)
Gitea (CT 2014)Forge logicielle et gestion de code10.10.20.15 / git.srv.dozylab.lansrv (VLAN 20)
CrowdSecMoteur de détection et LAPI10.10.20.22 / crowdsec.srv.dozylab.lansrv (VLAN 20)
Wazuh SIEMIndexer (9200) et Manager (55000)10.10.20.20 / wazuh.srv.dozylab.lansrv (VLAN 20)
Apache GuacamolePasserelle d’accès HTML510.10.10.20 / guacamole.adm.dozylab.lanadm (VLAN 10)
Grappe Proxmox VEHyperviseurs pve1, pve2, pve310.10.10.10, .11, .12 / pve*.adm.dozylab.lanadm (VLAN 10)
Agent HermesAgent conversationnel d’administration10.10.80.10 / hermes.lab.dozylab.lanlab (VLAN 80)
Juniper SRX300Passerelle de routage et pare-feu10.10.10.254 / fw01.adm.dozylab.lanPasserelle inter-zones

Plan d’adressage et interfaces

VLANNom de zoneSous-réseauPasserelle SRX300 / Interface
VLAN 10adm (Administration)10.10.10.0/2410.10.10.254 (ge-0/0/1.10)
VLAN 20srv (Serveurs)10.10.20.0/2410.10.20.254 (ge-0/0/1.20)
VLAN 80lab (Expérimentation)10.10.80.0/2410.10.80.254 (ge-0/0/1.80)

Matrice des flux réseau

SourceDestinationPortProtocoleApplication JunosStatut
Postes clientsNPM (10.10.20.12)443TCPjunos-httpsAutorisé
NPM (10.10.20.12)WatchTower (10.10.20.13)8000TCPp-intra-srvAutorisé
WatchTower (10.10.20.13)Guacamole (10.10.10.20)8080TCPp-srv-to-adm-guacAutorisé
WatchTower (10.10.20.13)Proxmox (10.10.10.10-12)8006TCPPVE-8006Autorisé
WatchTower (10.10.20.13)NPM (10.10.20.12)81TCPp-intra-srvAutorisé
WatchTower (10.10.20.13)Technitium (10.10.20.11)5380TCPp-intra-srvAutorisé
WatchTower (10.10.20.13)Gitea (10.10.20.15)3000TCPp-intra-srvAutorisé
WatchTower (10.10.20.13)CrowdSec (10.10.20.22)8080TCPp-intra-srvAutorisé
WatchTower (10.10.20.13)Wazuh Indexer (10.10.20.20)9200TCPp-intra-srvAutorisé
WatchTower (10.10.20.13)Wazuh Manager (10.10.20.20)55000TCPp-intra-srvAutorisé
WatchTower (10.10.20.13)Hermes (10.10.80.10)8642, 9119TCPp-srv-to-lab-hermesAutorisé

Dépendances et points de défaillance

Composant d’infrastructureImpact 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 SRX300Coupure 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 connecteursRisque 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 GuacamoleLe 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éeL’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 localLa 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ôleCritère d’acceptation mesurableStatut
Authentification API Guacamolecurl -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 ManagerLe connecteur NPM affiche le statut vert (« Joignable ») dans WatchTower et retourne les métriques d’hôtes proxy☐
Interrogation API Technitium DNScurl -s "http://10.10.20.11:5380/api/zones/list?token=…" retourne "status":"ok"☐
Sonde Gitea authentifiéeLa 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 LAPIcurl -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 VELes 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

VersionDateAuteurModifications
0.102/11/2026Administrateur système et réseauxCréation du document à partir de l’intervention réelle.
Défiler vers le haut