---
title: "Nginx, VPS, proxy et CDN : déployer Éclair"
description: "Déployer Éclair sur un VPS : configuration Nginx commentée, PHP-FPM, HTTPS avec Certbot, proxy inverse, IP réelle, Cloudflare et exemple Docker php:8.3-apache."
url: "https://eclair.academy/parcours/expert/nginx-vps"
lang: "fr"
author: "Thierry Gustin"
published: "2026-11-02"
updated: "2026-11-02"
---

# Nginx, VPS, proxy et CDN : déployer Éclair

> **L’essentiel** — Pour déployer Éclair hors d'un mutualisé, reproduis dans Nginx les règles du .htaccess, envoie le reste à index.php via PHP-FPM avec fastcgi_buffering off, active HTTPS avec Certbot, puis indique dans Réglages › Avancé si le site est derrière un proxy ou un CDN. Un conteneur php:8.3-apache avec mod_rewrite et AllowOverride All fonctionne aussi.

Déployer Éclair sur un VPS, derrière un proxy ou un CDN, revient à reproduire ce que le `.htaccess` fait sur un mutualisé : protéger les dossiers internes, tout envoyer à `index.php`, compresser et mettre en cache les fichiers statiques. Cette leçon donne une configuration Nginx commentée, les réglages HTTPS, proxy et Cloudflare, un exemple Docker et les vérifications finales.

> **Avant de commencer** — Durée : 1 heure. Prérequis : un VPS Debian ou Ubuntu avec un accès root, Nginx et PHP-FPM 8.3 installés, un domaine qui pointe vers le serveur, et la leçon [L'architecture d'Éclair](https://eclair.academy/parcours/expert/architecture). Sur un mutualisé, rien de tout cela n'est nécessaire : vois [Choisir son hébergement](https://eclair.academy/hebergement).

## Ce que tu sauras faire

### 🔧 Configurer Nginx

Les règles du .htaccess, PHP-FPM et le flux de l'assistant.

### 🔒 Passer en HTTPS

Certbot, Forcer HTTPS, adresse officielle et HSTS.

### 🌍 Placer un proxy ou un CDN

Vraie adresse IP, Cloudflare et conteneur Docker.

## Ce que Nginx doit reproduire du .htaccess

Nginx ignore les fichiers `.htaccess`. Sa configuration doit donc garantir les mêmes protections :

| Règle du .htaccess | Pourquoi |
| --- | --- |
| `app/`, `data/` et `cache/` répondent 404 | code, données et pages générées restent privés |
| fichiers cachés en 404, sauf `.well-known` | `.git` ou `.env` invisibles, découverte OAuth du MCP joignable |
| aucun `.php` exécutable hors `index.php` | un script déposé ailleurs ne s'exécute jamais |
| `media/` sans scripts ni pages | une image piégée ne devient pas une page |
| tout le reste vers `index.php` | le routeur d'Éclair répond, adresses propres comprises |
| compression, cache navigateur d'un an | pages légères, fichiers statiques réutilisés |

L'en-tête `Authorization`, que le `.htaccess` doit recopier pour le connecteur MCP, est transmis d'office par Nginx à PHP-FPM.

## La configuration Nginx commentée

Les règles reprennent la section Nginx du guide officiel d'Éclair ; les lignes marquées « ajout » complètent l'exemple pour un vrai serveur. `root` désigne le dossier qui reçoit le contenu du dossier `eclair` de l'archive.

```nginx
server {
    listen 80;
    listen [::]:80;
    server_name exemple.fr www.exemple.fr;
    root /var/www/eclair;
    index index.php;

    client_max_body_size 24m;            # ajout : images jusqu'à 20 Mo (Nginx : 1 Mo par défaut)
    gzip on;                             # ajout : compression, comme le .htaccess
    gzip_types text/plain text/css text/xml text/markdown application/javascript
               application/json application/xml application/rss+xml image/svg+xml;

    # Dossiers internes et fichiers cachés, sauf .well-known (découverte OAuth)
    location ~ ^/(app|data|cache)(/|$) { return 404; }
    location ~ /\.(?!well-known/) { return 404; }

    # Médias : images et polices seulement
    location ^~ /media/ {
        location ~* \.(php\d?|phtml|phar|s?html?|svgz?|xml|js)$ { return 404; }
        add_header X-Content-Type-Options nosniff;
        add_header Content-Security-Policy "default-src 'none'; img-src 'self'; sandbox";  # ajout, comme media/.htaccess
        expires 1y;
    }

    # Fichiers statiques versionnés : cache navigateur d'un an
    location ~* \.(webp|avif|jpe?g|png|gif|ico|css|js|woff2)$ { expires 1y; add_header Cache-Control "public, immutable"; }

    # Tout le reste passe par le contrôleur frontal
    location / { try_files $uri /index.php$is_args$args; }

    location = /index.php {
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root/index.php;
        fastcgi_pass unix:/run/php/php-fpm.sock;   # à adapter, par exemple /run/php/php8.3-fpm.sock
        fastcgi_buffering off;                     # conseillé par le guide : assistant IA au fil de l'eau
        fastcgi_read_timeout 300s;                 # ajout : demandes à l'IA longues (60 s par défaut)
    }

    # Aucun autre script PHP
    location ~ \.php$ { return 404; }
}
```

Trois réglages méritent une explication :

- **`client_max_body_size`** : Nginx refuse par défaut les requêtes de plus de 1 Mo (erreur 413), alors qu'Éclair accepte des images de 20 Mo. Règle aussi `upload_max_filesize` et `post_max_size` dans le `php.ini` de PHP-FPM.
- **`fastcgi_buffering off`** : l'assistant IA répond en flux. Éclair envoie déjà `X-Accel-Buffering: no`, que Nginx respecte par défaut ; la directive couvre les configurations qui l'ignorent.
- **`fastcgi_read_timeout`** : « Créer avec l'IA » répond d'un bloc après 20 à 60 secondes, et Éclair s'accorde jusqu'à 300 secondes, quand Nginx coupe après 60 secondes de silence.

```bash
sudo nginx -t && sudo systemctl reload nginx
# Éclair n'écrit que dans data/, cache/ et media/
sudo chown -R www-data:www-data /var/www/eclair/data /var/www/eclair/cache /var/www/eclair/media
```

## HTTPS avec Certbot, puis les réglages d'Éclair

```bash
sudo certbot --nginx -d exemple.fr -d www.exemple.fr
```

Certbot obtient un certificat Let's Encrypt, ajoute l'écoute sur le port 443 au bloc `server` et peut rediriger le HTTP vers le HTTPS. Installe ensuite Éclair en ouvrant `https://exemple.fr` : l'assistant enregistre l'adresse telle que tu l'as ouverte, et coche déjà **Forcer HTTPS**. Puis, dans l'administration :

1. Ouvre **Sécurité** : l'adresse du site doit être vérifiée. Sinon, clique sur **Vérifier l'adresse du site**.
2. Dans **Réglages › Avancé**, vérifie que **Forcer HTTPS** est coché. Éclair refuse de l'activer tant que tu n'es pas connecté en https.
3. Laisse coché **Rediriger vers l'adresse officielle** : une seule version du site, avec ou sans www, dès que l'adresse est vérifiée.
4. Une fois tout stable, coche **HSTS**. Éclair envoie alors `Strict-Transport-Security: max-age=31536000`, soit un an, sans les sous-domaines. Les navigateurs refuseront ensuite le http:// pour ton domaine : ne l'active donc jamais pendant des essais.

N'ajoute pas HSTS dans Nginx en plus : l'en-tête partirait deux fois. Pour le gérer dans Nginx, décoche l'option d'Éclair, et retiens qu'un `add_header` placé dans un bloc `location` masque ceux du bloc `server`.

## Comment déployer Éclair derrière un proxy inverse ?

Quand un autre serveur termine le HTTPS (Nginx devant un conteneur, Caddy, Traefik…), PHP reçoit du HTTP. Éclair tient la connexion pour sécurisée si la variable `HTTPS` est active, si le port vaut 443, ou si la requête porte `X-Forwarded-Proto: https` ou `X-Forwarded-SSL: on`. Le proxy doit donc envoyer `X-Forwarded-Proto` et conserver l'en-tête `Host`, qu'Éclair compare à son adresse officielle.

```nginx
# Nginx en proxy inverse devant Éclair (conteneur publié sur 127.0.0.1:8080)
location / {
    proxy_pass http://127.0.0.1:8080;
    proxy_set_header Host $host;                  # hôte d'origine, comparé à l'adresse du site
    proxy_set_header X-Forwarded-Proto $scheme;   # https, tel que le visiteur le voit
    proxy_set_header X-Real-IP $remote_addr;      # vraie adresse IP du visiteur
    proxy_buffering off;                          # flux de l'assistant IA
    proxy_read_timeout 300s;
    client_max_body_size 24m;
}
```

> **Ne publie pas le port interne** — Éclair croit `X-Forwarded-Proto` d'où qu'il vienne. Publie le port d'Éclair sur `127.0.0.1` uniquement, pour que seul ton proxy puisse lui parler.

Derrière un proxy, PHP voit l'adresse IP du proxy : les limites anti-bruteforce et celles du formulaire frapperaient tous les visiteurs à la fois. Dans **Réglages › Avancé › Site derrière un proxy / CDN**, choisis l'en-tête qui porte la vraie adresse. Éclair ne le lit que si tu l'as choisi, et ne garde de `X-Forwarded-For` que la dernière adresse, celle ajoutée par le proxy le plus proche.

| Situation | Choix dans Éclair |
| --- | --- |
| pas de proxy, ou adresse déjà corrigée par le module realip de Nginx | Non (recommandé) |
| Nginx en proxy inverse avec `proxy_set_header X-Real-IP` | X-Real-IP |
| proxy qui complète `X-Forwarded-For` | X-Forwarded-For |
| Cloudflare devant le site, avec ou sans proxy derrière | Cloudflare |

Ne choisis un en-tête que si le site est vraiment derrière ce service : sinon, un visiteur pourrait l'écrire lui-même et contourner les limites. Derrière Cloudflare, n'accepte que les connexions venant des [adresses publiées par Cloudflare](https://www.cloudflare.com/ips/).

## Cloudflare : ce qu'il faut régler

- **Chiffrement** : mode SSL/TLS « Full (strict) », avec un vrai certificat sur ton serveur, celui de Certbot par exemple.
- **Pare-feu et anti-robots** : laisse passer `/_eclair/` et `/.well-known/`, sinon Claude et ChatGPT ne joignent ni le connecteur MCP ni son autorisation.
- **Cache** : les fichiers statiques sont déjà marqués pour un an. Ne mets pas le HTML en cache chez Cloudflare : Éclair vide son propre cache à chaque publication, pas celui de Cloudflare, et l'administration comme `/_eclair/` ne doivent jamais y finir.
- **Options qui injectent des scripts** : selon [la documentation de Cloudflare](https://developers.cloudflare.com/fundamentals/reference/policies-compliances/content-security-policies/), Rocket Loader exige `ajax.cloudflare.com` dans `script-src`, et Web Analytics `static.cloudflareinsights.com`. La CSP d'Éclair n'autorise que les scripts du domaine : laisse ces options désactivées.
- **Adresse IP** : choisis « Cloudflare » dans **Réglages › Avancé › Site derrière un proxy / CDN**.

## Comment déployer Éclair avec Docker ?

Voici un exemple de départ, à adapter, fondé sur l'image officielle `php:8.3-apache`. Il garde Apache pour que le `.htaccess` d'Éclair s'applique tel quel. Place ce `Dockerfile` à côté du dossier `eclair` décompressé.

```dockerfile
# Exemple de départ, à adapter : Éclair 1.8 sur l'image officielle PHP 8.3 + Apache
FROM php:8.3-apache

# Déjà présentes dans l'image : mbstring, json, dom, session, zlib, curl, openssl, sodium, Argon2id.
# À ajouter : gd avec JPEG et WebP (images), zip (sauvegardes), exif (photos de téléphone redressées).
RUN apt-get update \
 && apt-get install -y --no-install-recommends libjpeg62-turbo-dev libpng-dev libwebp-dev libzip-dev \
 && docker-php-ext-configure gd --with-jpeg --with-webp \
 && docker-php-ext-install -j"$(nproc)" gd zip exif \
 && rm -rf /var/lib/apt/lists/*

# Modules utilisés par le .htaccess : réécriture, en-têtes, compression (sans effet si déjà actif)
RUN a2enmod rewrite headers deflate

# .htaccess autorisés : l'image le fait déjà pour /var/www/ (docker-php.conf), on le rend explicite
RUN printf '%s\n' '<Directory /var/www/html>' '    AllowOverride All' '</Directory>' \
      > /etc/apache2/conf-available/eclair.conf \
 && a2enconf eclair

# Réglages PHP de production, envois d'images jusqu'à 20 Mo
RUN mv "$PHP_INI_DIR/php.ini-production" "$PHP_INI_DIR/php.ini" \
 && printf '%s\n' 'upload_max_filesize = 20M' 'post_max_size = 24M' > "$PHP_INI_DIR/conf.d/eclair.ini"

# Le contenu du dossier eclair de l'archive, fichiers cachés compris
COPY --chown=www-data:www-data eclair/ /var/www/html/
```

```yaml
# compose.yaml : données et médias persistants, port réservé au proxy HTTPS de la machine
services:
  eclair:
    build: .
    restart: unless-stopped
    ports:
      - "127.0.0.1:8080:80"
    volumes:
      - eclair-data:/var/www/html/data
      - eclair-media:/var/www/html/media
volumes:
  eclair-data:
  eclair-media:
```

`docker compose up -d --build` lance le site sur le port 8080 de la machine, derrière le proxy HTTPS de la section précédente. Les volumes nommés gardent `data/` et `media/` d'une version à l'autre : pour mettre à jour, remplace le dossier `eclair` par celui de la nouvelle archive et reconstruis l'image. L'image officielle active aussi OPcache par défaut (Dockerfile consulté le 1er novembre 2026).

```bash
docker compose exec eclair php -r 'var_dump(function_exists("imagewebp"));'   # bool(true)
docker compose exec eclair apache2ctl -M | grep -E 'rewrite|headers|deflate'
```

## Vérifications après le déploiement

```bash
SITE=https://exemple.fr
# 1. Fichiers internes inaccessibles : 404 attendu pour chacun
for f in /data/site.php /data/users.php /app/bootstrap.php /cache/runtime.php /data/.htaccess; do
  printf '%s %s\n' "$(curl -s -o /dev/null -w '%{http_code}' "$SITE$f")" "$f"
done
# 2. Réécriture d'URL : le contrôleur répond « ok »
curl -s "$SITE/__eclair/ping"; echo
# 3. Cache statique : X-Cache: HIT au deuxième appel
curl -sI "$SITE/" > /dev/null; curl -sI "$SITE/" | grep -i x-cache
# 4. Connecteur MCP activé : 401 et en-tête WWW-Authenticate
curl -si -X POST "$SITE/_eclair/mcp" | grep -i -E '^HTTP|www-authenticate'
```

Termine dans l'administration : la page **Sécurité** doit montrer un test de protection au vert et une adresse vérifiée, ce qui suppose que le serveur puisse s'appeler lui-même par son adresse publique, même depuis un conteneur. Envoie enfin une image de plus de 1 Mo dans **Médias** et, si l'assistant IA est activé, vérifie que sa réponse s'affiche au fil de l'eau.

## À retenir

- Nginx ignore le `.htaccess` : recopie ses règles en gardant `.well-known` joignable pour le connecteur MCP.
- Pour déployer Éclair proprement, autorise des envois de 20 Mo et coupe le tampon FastCGI pour l'assistant IA.
- Derrière un proxy, envoie `X-Forwarded-Proto` et `Host`, et ne choisis un en-tête d'adresse IP que s'il existe vraiment.
- Avec Cloudflare : mode Full (strict), `/_eclair/` et `/.well-known/` ouverts, HTML hors cache, Rocket Loader coupé.
- L'exemple Docker garde Apache et le `.htaccess` d'origine, avec `data/` et `media/` dans des volumes.

## Pour aller plus loin

- [L'architecture d'Éclair](https://eclair.academy/parcours/expert/architecture) : pourquoi chaque règle du `.htaccess` existe.
- [Performance : garder 100 sur 100](https://eclair.academy/parcours/expert/performance) : mesurer le site une fois déployé.
- [Sécurité avancée et maintenance](https://eclair.academy/parcours/expert/securite-avancee) : droits des fichiers, sauvegardes et mises à jour.
- [Connecter Claude à ton site](https://eclair.academy/parcours/ia-mcp/connecter-claude) : le connecteur MCP, qui exige HTTPS.
- Nginx : [module FastCGI](https://nginx.org/en/docs/http/ngx_http_fastcgi_module.html), pour `fastcgi_buffering` et `fastcgi_read_timeout`.
- Docker Hub : [image officielle php](https://hub.docker.com/_/php), ses extensions et son `php.ini`.

## Questions fréquentes

### Faut-il garder les fichiers .htaccess sous Nginx ?

Ils ne servent à rien sous Nginx, mais ne gênent pas et resserviront si tu reviens à Apache. C'est ta configuration Nginx qui protège le site.

### Pourquoi l'assistant IA répond-il d'un bloc derrière Nginx ?

Un tampon retient le flux : vérifie `fastcgi_buffering off;` dans le bloc PHP, ou `proxy_buffering off;` si Nginx sert de proxy inverse. Le reste du site n'est pas concerné.

### Cloudflare peut-il mettre mes pages HTML en cache ?

Il le peut, mais Éclair ne pourra plus vider ce cache à chaque publication : tes visiteurs verraient d'anciennes versions. Le cache statique d'Éclair sert déjà les pages en quelques millisecondes depuis ton serveur.

### Faut-il Docker pour héberger Éclair ?

Non. Un mutualisé avec Apache ou LiteSpeed suffit, et un VPS avec Nginx aussi. Docker sert surtout à standardiser des déploiements ou à isoler plusieurs sites sur une même machine.
