nas-runbooks/common/HEBERGEMENT-SITES-STATIQUES.md

4.1 KiB

Hébergement de sites statiques produits par Hermes

Date : 2026-06-20
Origine : Incident panda-dashboard — site hors ligne après redémarrage Container Manager
Applicable : hermes-tt, hermes-nyora, hermes-perso


LE PROBLÈME À NE JAMAIS REPRODUIRE

Hermes-nyora avait servi panda-dashboard via python3 -m http.server lancé depuis son propre workspace. Quand Container Manager redémarre, le container Hermes redémarre et le process Python meurt — sans aucune relance automatique.

Un agent Hermes NE DOIT PAS héberger un site en production.
Le workspace d'un agent est éphémère du point de vue de la disponibilité service.


LA RÈGLE

Tout site statique produit par Hermes doit être déployé dans son propre container Docker dédié avec restart: always, via un docker-compose dans /volume1/docker/.


PROCÉDURE — Déployer un site statique

1. Identifier un port libre

Lire /volume1/docker/ports-registry.md (accessible depuis l'agent : /opt/data/workspace/../../../ports-registry.md — non, passer par l'outil NAS ou demander à Claude).

Plages recommandées : 3040-3099, 8800-8899.

2. Créer le docker-compose dans /volume1/docker/

L'agent écrit le fichier dans son workspace, puis demande au MCP NAS de le déplacer. Ou bien Claude le crée directement via mcp-nas.

Template à copier :

# <nom-du-site> — description courte
# Port : <PORT> — <domaine.bolbol.tn>

services:
  <nom-du-site>:
    image: nginx:alpine
    container_name: <nom-du-site>
    restart: always
    ports:
      - "<PORT>:80"
    volumes:
      - /volume1/docker/hermes-platform/hermes-<instance>/data/workspace/<dossier-site>:/usr/share/nginx/html:ro
    networks:
      - n8n_default

networks:
  n8n_default:
    external: true

3. Déployer via API Portainer

Portainer est accessible sur http://172.17.0.1:9000 depuis les containers Docker.

# Obtenir JWT
JWT=$(curl -s -X POST http://172.17.0.1:9000/api/auth \
  -H "Content-Type: application/json" \
  -d '{"username":"bestof","password":"2L2u519wportainer"}' \
  | grep -o '"jwt":"[^"]*"' | cut -d'"' -f4)

# Créer le stack (endpointId=2 = local)
curl -s -X POST "http://172.17.0.1:9000/api/stacks/create/standalone/string?endpointId=2" \
  -H "Authorization: Bearer $JWT" \
  -H "Content-Type: application/json" \
  -d "{
    \"name\": \"<nom-du-site>\",
    \"stackFileContent\": $(cat /chemin/vers/docker-compose.yml | python3 -c 'import json,sys; print(json.dumps(sys.stdin.read()))'),
    \"env\": []
  }"

Vérification :

JWT=<JWT_OBTENU>
curl -s "http://172.17.0.1:9000/api/endpoints/2/docker/containers/json?filters=%7B%22label%22%3A%5B%22com.docker.compose.project%3D<nom-du-site>%22%5D%7D" \
  -H "Authorization: Bearer $JWT" | python3 -c "
import json,sys
for c in json.load(sys.stdin):
    print(c['Names'], c['State'], c['Status'])
"

4. Configurer le Reverse Proxy DSM

DSM → Panneau de configuration → Portail d'applications → Proxy inversé :

  • Source : HTTPS, <nom>.bolbol.tn, port 443
  • Destination : HTTP, 192.168.100.33, port <PORT>

5. Mettre à jour ports-registry.md

# Ajouter la ligne dans le tableau Services Actifs
# Marquer le port comme OCCUPE dans Plages libres
# Ajouter une ligne dans Historique des modifications

6. Commit Gitea

cd /volume1/docker/<nom-du-site>
git init
git add .
git commit -m "deploy: <nom-du-site> nginx statique port <PORT>"
git push http://bolbol:2L2u519wgitea@192.168.100.33:3232/bolbol/nas-runbooks.git

EXEMPLE CONCRET — panda-dashboard (2026-06-20)

  • Dossier source : /volume1/docker/hermes-platform/hermes-nyora/data/workspace/panda-dashboard/
  • Port : 3021
  • Domaine : panda.bolbol.tn
  • Stack Portainer : ID 314
  • Compose : /volume1/docker/panda-dashboard/docker-compose.yml

RAPPEL SÉCURITÉ

  • Ne jamais stocker de données sensibles dans le workspace monté en lecture publique
  • Le volume est monté :ro (read-only) — le container nginx ne peut pas modifier les fichiers
  • Le mot de passe Portainer est dans /volume1/docker/hermes-platform/.env