---
title: "Roadmap : Webhook Git → rebuild Hugo automatique"
description: "Plan d'implémentation du webhook GitHub → Hugo rebuild. HMAC-SHA256, rate limiting 1/min, IPAddressAllow GitHub ranges. ETA juin 2026 après sprint sécu MCP."
url: "https://www.arleo.eu/posts/roadmap-webhook-git-rebuild/"
language: "fr"
datePublished: "2026-05-09T12:47:17+02:00"
dateModified: "2026-05-15T23:51:25+02:00"
tags: ["roadmap","hugo","webhook","github","ci-cd","mcp"]
categories: ["roadmap"]
contentSignal: "ai-train=no, search=yes, ai-input=yes"
---

# Roadmap : Webhook Git → rebuild Hugo automatique
Plan d'implémentation du webhook GitHub → Hugo rebuild. HMAC-SHA256, rate limiting 1/min, IPAddressAllow GitHub ranges. ETA juin 2026 après sprint sécu MCP.



## Statut : 🗂️ BACKLOG — pas encore implémenté

Cette page documente une intention d'architecture qui sera implémentée dans une prochaine itération. Le code n'est pas encore en prod.

## Contexte

Dans la [Stratégie 4 (séparation MCP / Git)](/posts/strategie-4-mcp-vs-git/), j'ai expliqué pourquoi `content/` est dans `.gitignore` côté repo arleo.eu : pour qu'aucun conflit ne soit possible entre l'écriture MCP et l'écriture Git.

Concrètement, ça veut dire que quand je push depuis VS Code une nouvelle version de `layouts/`, `themes/`, `static/`, `hugo.toml`, ou `deploy.sh`, **rien ne se passe automatiquement** côté serveur. Je dois SSH dans la VM Hugo et faire `git pull && hugo --minify && rsync` à la main.

C'est pas critique (push de structure = ~1× par semaine), mais c'est de la friction inutile. Donc : webhook GitHub → rebuild auto.

## Architecture cible

<!--more-->
<!-- mermaid-source:c2VxdWVuY2VEaWFncmFtCiAgICBwYXJ0aWNpcGFudCBHSCBhcyBHaXRIdWIKICAgIHBhcnRpY2lwYW50IENGIGFzIENsb3VkZmxhcmUKICAgIHBhcnRpY2lwYW50IFAgYXMgbWNwLW9hdXRoLXByb3h5CiAgICBwYXJ0aWNpcGFudCBWTSBhcyBodWdvLW1jcCBWTQoKICAgIEdILT4+Q0Y6IFBPU1QgL3dlYmhvb2svZ2l0PGJyLz5YLUh1Yi1TaWduYXR1cmUtMjU2OiBzaGEyNTY94oCmCiAgICBDRi0+PkNGOiBJUCB3aGl0ZWxpc3QgMTQwLjgyLjExMi4wLzIwIOKckwogICAgQ0YtPj5QOiBGb3J3YXJkIChCb3QgTWdtdCBza2lwcGVkKQogICAgUC0+PlZNOiBQcm94eSAvd2ViaG9vay9naXQKICAgIFZNLT4+Vk06IDEuIEhNQUMtU0hBMjU2IOKckwogICAgVk0tPj5WTTogMi4gcmVmcy9oZWFkcy9tYWluIOKckwogICAgVk0tPj5WTTogMy4gUmF0ZSBsaW1pdCAxL21pbiDinJMKICAgIFZNLT4+Vk06IDQuIGdpdCByZXNldCAtLWhhcmQgKyBodWdvIC0tbWluaWZ5CiAgICBWTS0+PlZNOiA1LiBBdWRpdCBsb2cgSlNPTgogICAgVk0tLT4+R0g6IDIwMCBPSw== -->
{{< mermaid-svg hash="3007aa7f" >}}

```
GitHub push
    │
    │ POST https://mcp-hugo.arleo.eu/webhook/git
    │ Header: X-Hub-Signature-256: sha256=<hmac>
    │ Body: {"ref": "refs/heads/main", "head_commit": ...}
    │
    ▼
[Cloudflare]
    │ Custom rule: skip Bot Mgmt si IP in GitHub ranges
    │
    ▼
[mcp-oauth-proxy] (NUC, port 443)
    │ Routing /webhook/git → forward to MCP server VM
    │
    ▼
[hugo-mcp] (VM Hugo, port 8000)
    │ 1. Validate HMAC-SHA256
    │ 2. Validate refs/heads/main only
    │ 3. Rate limit : 1 rebuild / minute
    │ 4. Trigger : git fetch && git reset --hard origin/main && hugo --minify
    │ 5. Audit log JSON : commit SHA, author, duration
    │
    ▼
[Site rebuilded] ~3 secondes
```

## Choix techniques

### HMAC-SHA256 (pas IP whitelist seule)

GitHub publie ses ranges (`140.82.112.0/20` et autres). On pourrait juste filter par IP. Mais HMAC est plus robuste :

- **IP spoofing** est théoriquement possible (très rare, mais)
- **HMAC signature** repose sur un secret partagé. Si l'attaquant ne l'a pas, il ne peut rien forger.

Concrètement on fait les **deux** : Cloudflare fait l'IP filter (élimine 99% du noise), et le HMAC valide cryptographiquement.

### Rate limiting : 1 / minute

Pourquoi ? Si un attaquant arrive à signer un payload (ex: vol du `WEBHOOK_SECRET` via une fuite), il pourrait spam le serveur de rebuilds. Hugo build = ~3s + Cloudflare API call = ~400ms. À 100 rebuilds/minute, le serveur est saturé et l'API Cloudflare râle.

1 rebuild / minute couvre largement le cas légitime (je ne push pas plus que ça) et limite le blast radius en cas de compromise.

### Validation `refs/heads/main` uniquement

Si quelqu'un push une branche feature, on ne rebuild PAS. Seul `main` triggers le déploiement. Évite de déployer des trucs en cours.

### Audit log JSON

Chaque rebuild trigger log :

```json
{
  "ts": "2026-05-09T14:23:11Z",
  "event": "webhook_rebuild_triggered",
  "commit_sha": "a1b2c3d4...",
  "commit_author": "jmrGrav <276982731+jmrGrav@users.noreply.github.com>",
  "commit_message": "fix: typo dans le footer",
  "build_duration_ms": 2853,
  "deploy_success": true,
  "cf_purge_success": true
}
```

Ingéré par Vector → BetterStack pour timeline + alerting.

## Sécurité layer par layer

| Layer | Protection |
|-------|-----------|
| Cloudflare | IP whitelist GitHub (`140.82.112.0/20`) |
| Cloudflare | Rule "skip Bot Mgmt sur webhook path" scopée triple |
| nginx | TLS 1.3 obligatoire |
| systemd | IPAddressAllow GitHub ranges (rebuild git fetch) |
| MCP | HMAC-SHA256 validation (secret 32 bytes random) |
| MCP | Validation `refs/heads/main` strict |
| MCP | Rate limiting 1/min (slowapi) |
| MCP | Audit log JSON ingéré BetterStack |

Defense-in-depth. Si un layer est compromis, les autres tiennent.

## Ce qui fonctionne déjà

- Stratégie 4 (`.gitignore content/`) en place côté repo
- `mcp-oauth-proxy` peut déjà router vers de nouveaux endpoints sans redéploiement OAuth
- Cloudflare Bot Management bypass scopé déjà créé (cf. [post-mortem CF blocking](/posts/postmortem-cf-bot-blocking-mcp/))
- Audit log structuré JSON pas encore en place côté MCP — c'est un prérequis du sprint sécu

## Ce qui reste à faire

1. Implémenter `/webhook/git` endpoint dans `hugo-mcp` (~2h)
2. Configurer GitHub webhook avec secret HMAC (5 min)
3. Tests reproductibles : push réel → rebuild auto en moins de 10s (~30 min)
4. Rollback procedure : si le rebuild casse le site, revert auto au dernier commit valide (~1h)

Total estimé : **~4h**. Effort raisonnable, mais non prioritaire vs le sprint sécurité MCP en cours.

## Décision

Le webhook Git Strategy 4 sera implémenté **après** le sprint sécurité MCP (rate limiting + audit logs JSON + Pydantic v2). Plusieurs des couches de sécu de ce webhook (rate limiting, audit logs) sont des chantiers du sprint — pas la peine de les ré-implémenter ici, elles seront disponibles globalement après.

ETA : courant juin 2026.

## Référence

Brief technique complet archivé dans le repo `hugo-mcp` : `docs/backlogs/webhook-git-rebuild-2026-05-08.md`. Inclut le code Python détaillé, les snippets nginx, la config Cloudflare exacte, et le runbook de rollback.



## Tags

- roadmap
- hugo
- webhook
- github
- ci-cd
- mcp

## Categories

- roadmap
