# ============================================================================
#  Vhost Apache - serveur MCP Infoparcelle (mcp.infoparcelle.fr)
# ============================================================================
#
#  ETAT CONSTATE LE 2026-08-19 : le DNS (162.19.28.220) et le certificat sont en
#  place, mais https://mcp.infoparcelle.fr repond 500 sur TOUTES les routes -
#  y compris sur un simple fichier statique. La reponse est la page d'erreur
#  Apache par defaut, SANS en-tete `x-powered-by` : le vhost est charge mais sa
#  configuration echoue avant d'atteindre le moindre backend.
#
#  ⚠ CAUSE IDENTIFIEE LE 2026-08-19 : le conteneur `rs` charge `proxy_module` et
#  `proxy_fcgi_module` (PHP-FPM) mais PAS `proxy_http_module`.
#
#  `ProxyPass` est alors une directive VALIDE - Apache demarre normalement et
#  tous les autres sites fonctionnent - mais au moment de parler HTTP au backend
#  aucun gestionnaire n'existe pour le schema `http` :
#      AH01144: No protocol handler was valid for the URL ... (scheme 'http')
#  d'ou un 500 sur TOUTE requete proxyfiee, en HTTP comme en HTTPS, alors que les
#  chemins servis directement par Apache repondent normalement (mesure : sur ce
#  vhost, /.well-known/index.php rendait 200 et /health rendait 500).
#
#  Correction :
#      docker exec docker-rs-1 a2enmod proxy_http
#      docker exec docker-rs-1 service apache2 reload
#
#  ⚠ `mods-enabled` n'est pas monte depuis l'hote : cette activation vit dans la
#  couche du conteneur et ne survivrait PAS a une recreation de `rs`. La reporter
#  dans `init/installvh.sh` ou dans l'image.
#
#  Diagnostic :
#    apache2ctl -S | grep mcp                       # le vhost est-il pris en compte ?
#    apache2ctl -t                                  # la configuration est-elle valide ?
#    tail -50 /var/log/apache2/mcp.infoparcelle.fr-error.log
#    curl -i http://127.0.0.1:3000/health           # le serveur MCP tourne-t-il ?
#
# ============================================================================

<VirtualHost *:80>
    ServerName mcp.infoparcelle.fr

    # Laisser passer les renouvellements ACME avant de rediriger.
    Alias /.well-known/acme-challenge /var/www/certbot/.well-known/acme-challenge
    <Directory /var/www/certbot/.well-known/acme-challenge>
        Require all granted
    </Directory>

    RewriteEngine On
    RewriteCond %{REQUEST_URI} !^/\.well-known/acme-challenge/
    RewriteRule ^(.*)$ https://%{HTTP_HOST}$1 [R=301,L]
</VirtualHost>

<IfModule mod_ssl.c>
<VirtualHost *:443>
    ServerName mcp.infoparcelle.fr

    SSLEngine on
    SSLCertificateFile      /etc/letsencrypt/live/mcp.infoparcelle.fr/fullchain.pem
    SSLCertificateKeyFile   /etc/letsencrypt/live/mcp.infoparcelle.fr/privkey.pem

    # ⚠ AUCUN DocumentRoot ni PHP : ce vhost ne sert QUE de proxy vers le
    # serveur MCP (Node). Un DocumentRoot pointant sur un dossier absent est
    # l'une des causes possibles du 500 constate.

    # ------------------------------------------------------------------
    #  En-tetes de transmission - INDISPENSABLES
    # ------------------------------------------------------------------
    #  Depuis le correctif du 2026-08-19, le serveur MCP derive son URL publique
    #  de l'hote par lequel on l'appelle : c'est ce qui lui permet d'annoncer
    #  `https://mcp.infoparcelle.fr` dans ses metadonnees OAuth (auparavant il
    #  annoncait `http://localhost:3000`, ce qui rendait toute connexion
    #  impossible depuis Claude ou ChatGPT).
    #
    #  Sans ces trois en-tetes, il ne peut PAS connaitre son adresse publique et
    #  la decouverte OAuth redevient fausse.
    RequestHeader set X-Forwarded-Proto "https"
    RequestHeader set X-Forwarded-Host  "mcp.infoparcelle.fr"
    RequestHeader set X-Forwarded-Port  "443"
    ProxyPreserveHost On

    # ------------------------------------------------------------------
    #  Proxy vers le serveur MCP
    # ------------------------------------------------------------------
    #  ⚠ CE VHOST TOURNE DANS LE CONTENEUR `rs`, PAS SUR L'HOTE.
    #
    #  Il faut donc viser le conteneur MCP par son **nom de service Docker**, que
    #  le DNS interne de Docker resout automatiquement entre conteneurs d'un meme
    #  reseau (verifie : `http://mcp:3000/health` repond 200 depuis `rs`).
    #
    #  ⚠ NE PAS coder une adresse IP ici. L'IP du conteneur est attribuee par
    #  Docker et change d'un environnement a l'autre (172.20.0.5 en dev,
    #  192.168.144.3 en production) comme d'une recreation a l'autre. Le nom, lui,
    #  ne change jamais - et cela evite d'avoir a figer une IP dans le compose.
    #
    #  `127.0.0.1:3000` ne repond PAS : le service est en `expose: 3000`, il n'est
    #  publie sur aucun port de l'hote.
    #
    #  Autre cas : service Node hors Docker (systemd/pm2) → http://127.0.0.1:3000/
    ProxyRequests Off

    # Le transport MCP peut repondre en flux (Server-Sent Events) : la reponse
    # doit partir au fil de l'eau, sans mise en tampon, et le delai doit couvrir
    # les requetes longues (une recherche cadastrale large depasse 60 s).
    ProxyTimeout 300
    <Proxy "http://mcp:3000/">
        ProxySet connectiontimeout=10 timeout=300 flushpackets=on
    </Proxy>

    ProxyPass        / http://mcp:3000/ retry=0
    ProxyPassReverse / http://mcp:3000/

    # ------------------------------------------------------------------
    #  Journaux dedies
    # ------------------------------------------------------------------
    ErrorLog  ${APACHE_LOG_DIR}/mcp.infoparcelle.fr-error.log
    CustomLog ${APACHE_LOG_DIR}/mcp.infoparcelle.fr-access.log combined

    Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains"
</VirtualHost>
</IfModule>
