Structure des fichiers de configuration Nginx

10 min de lecture·Matthieu·nginxconfigurationweb-server|

Un tour complet de l'organisation des fichiers de configuration Nginx sur le disque, de l'imbrication des contextes, du fonctionnement des directives include et de l'héritage des directives.

Vous avez installé Nginx. Vous avez ouvert /etc/nginx/nginx.conf et vous avez trouvé un fichier qui inclut d'autres fichiers, qui eux-mêmes en incluent d'autres. Certaines directives se trouvent entre des accolades, d'autres flottent au niveau racine. Avant de commencer à configurer des blocs server, du SSL ou des reverse proxies, il vous faut la carte.

Cet article vous donne cette carte. Pas de recettes. Juste le modèle mental du fonctionnement de la configuration Nginx, pour que vous puissiez lire et modifier n'importe quelle config que vous rencontrez.

Où sont stockés les fichiers de configuration Nginx ?

Sur Debian 12 et Ubuntu 24.04, le paquet apt installe tout sous /etc/nginx/. Voici à quoi ressemble ce répertoire sur une installation fraîche :

/etc/nginx/
├── nginx.conf              # Main config entry point
├── mime.types              # Maps file extensions to MIME types
├── conf.d/                 # Drop-in config files (*.conf auto-included)
├── sites-available/        # All virtual host config files
│   └── default             # Default server block
├── sites-enabled/          # Symlinks to active virtual hosts
│   └── default -> ../sites-available/default
├── snippets/               # Reusable config fragments
│   └── fastcgi-php.conf
├── modules-available/      # Available dynamic module configs
├── modules-enabled/        # Symlinks to loaded modules
├── fastcgi.conf            # FastCGI directive defaults
├── fastcgi_params          # FastCGI parameter mappings
├── proxy_params            # Proxy header defaults
├── scgi_params             # SCGI parameter mappings
├── uwsgi_params            # uWSGI parameter mappings
├── koi-utf                 # Character set mapping files
├── koi-win
└── win-utf

Vous pouvez vérifier cela sur votre propre serveur :

ls -la /etc/nginx/

Le fichier que vous modifiez le plus souvent n'est pas nginx.conf lui-même. C'est généralement un fichier dans sites-available/ ou conf.d/. Le fichier principal nginx.conf définit les paramètres globaux et inclut ces fichiers via des directives include.

Comment les fichiers de configuration Nginx sont-ils organisés ?

La configuration Nginx utilise un arbre de contextes (contexts) imbriqués. Chaque contexte est une directive de bloc entre accolades. Les directives placées dans un contexte ne s'appliquent que dans cette portée.

La hiérarchie ressemble à ceci :

main (top level, outside any braces)
├── events { }
└── http { }
    └── server { }
        └── location { }

Chaque directive de la configuration se trouve à l'un de ces niveaux. Le contexte main est le fichier lui-même. Tout le reste s'imbrique à l'intérieur.

Que contrôle le contexte main ?

Le contexte main représente tout ce qui se trouve en dehors de tout bloc de directives dans nginx.conf. Il contrôle les paramètres au niveau du processus qui affectent l'ensemble de l'instance Nginx.

Directives principales à ce niveau :

Directive Fonction Valeur typique
user Utilisateur système sous lequel tournent les workers www-data
worker_processes Nombre de processus worker auto (correspond aux cœurs CPU)
pid Chemin vers le fichier PID /run/nginx.pid
error_log Chemin et niveau du log d'erreur global /var/log/nginx/error.log
include Charge les configs des modules /etc/nginx/modules-enabled/*.conf

Voici le contexte main du fichier nginx.conf par défaut sur Debian 12 :

user www-data;
worker_processes auto;
pid /run/nginx.pid;
error_log /var/log/nginx/error.log;
include /etc/nginx/modules-enabled/*.conf;

Ces cinq lignes s'exécutent avant tout le reste. Elles définissent l'utilisateur sous lequel Nginx tourne, le nombre de workers à lancer et l'emplacement des logs d'erreur.

Que contient le bloc events ?

Le bloc events configure la façon dont Nginx gère les connexions au niveau du système d'exploitation. Il se trouve à l'intérieur du contexte main.

events {
    worker_connections 768;
    # multi_accept on;
}

worker_connections définit le nombre maximum de connexions simultanées par processus worker. Avec worker_processes auto sur une machine 4 cœurs, vous obtenez 4 x 768 = 3 072 connexions concurrentes. La valeur par défaut dans le code source de Nginx est 512, mais Debian la fixe à 768.

Optimisation des performances Nginx sur un VPS

À quoi sert le contexte http ?

Le bloc http contient toute la configuration liée au traitement du trafic HTTP. Chaque bloc server se trouve à l'intérieur. Les directives placées ici s'appliquent à tous les virtual hosts, sauf si un bloc server ou location les remplace.

http {
    sendfile on;
    tcp_nopush on;
    types_hash_max_size 2048;
    server_tokens off;

    include /etc/nginx/mime.types;
    default_type application/octet-stream;

    access_log /var/log/nginx/access.log;

    gzip on;

    include /etc/nginx/conf.d/*.conf;
    include /etc/nginx/sites-enabled/*;
}

Notez server_tokens off; vers le haut. Cela masque le numéro de version de Nginx dans les en-têtes de réponse. La divulgation de la version aide les attaquants à cibler des failles connues. La config par défaut de Debian n'inclut pas cette ligne. Ajoutez-la.

Les deux lignes include en bas sont la façon dont Nginx charge vos configurations de sites. Nous verrons include en détail plus bas.

Comment fonctionnent les blocs server ?

Un bloc server définit un virtual host. Il se trouve à l'intérieur du contexte http. Chaque bloc server écoute sur une combinaison adresse/port et fait correspondre les requêtes par l'en-tête Host.

server {
    listen 80;
    listen [::]:80;
    server_name example.com www.example.com;

    root /var/www/example.com/html;
    index index.html;

    location / {
        try_files $uri $uri/ =404;
    }
}

Quand une requête arrive, Nginx sélectionne le bloc server en comparant server_name avec l'en-tête Host. Si aucun bloc ne correspond, Nginx utilise le default_server :

listen 80 default_server;

En général, vous créez un fichier par domaine dans sites-available/, chacun contenant un bloc server (ou deux, si vous avez à la fois HTTP et HTTPS).

Nginx Server Blocks : héberger plusieurs domaines sur un VPS

Comment Nginx fait-il correspondre les blocs location ?

Un bloc location définit la façon dont Nginx traite les requêtes pour des motifs d'URI spécifiques. Il se trouve à l'intérieur d'un bloc server (ou à l'intérieur d'un autre location).

Nginx évalue les blocs location dans un ordre précis :

Modificateur Type Exemple Comportement
= Correspondance exacte location = / Correspond uniquement à /. Arrête la recherche immédiatement.
^~ Préfixe prioritaire location ^~ /images/ Correspond au préfixe. Ignore les expressions régulières.
~ Regex (sensible à la casse) location ~ \.php$ La première regex correspondante gagne.
~* Regex (insensible à la casse) location ~* \.(jpg|png)$ La première regex correspondante gagne.
(aucun) Préfixe location /api/ Le préfixe le plus long gagne, mais une regex peut le supplanter.

L'algorithme de correspondance :

  1. Nginx vérifie tous les préfixes de location et mémorise le plus long.
  2. Si cette correspondance utilise = ou ^~, stop. Elle est utilisée.
  3. Sinon, Nginx vérifie les locations regex dans l'ordre où elles apparaissent dans le fichier de config.
  4. La première regex correspondante gagne. Si aucune regex ne correspond, le préfixe le plus long de l'étape 1 est utilisé.

Cela signifie que l'ordre des locations par préfixe dans votre fichier de config n'a pas d'importance. Mais l'ordre des regex, si.

Comment fonctionne la directive include ?

La directive include insère le contenu d'un autre fichier (ou des fichiers correspondant à un motif glob) à la position actuelle dans la config. Nginx la résout au chargement de la config, avant que celle-ci ne soit analysée dans son ensemble.

include /etc/nginx/mime.types;
include /etc/nginx/conf.d/*.conf;
include /etc/nginx/sites-enabled/*;

Le glob *.conf correspond à tous les fichiers se terminant par .conf dans ce répertoire. Le glob * correspond à tout. Les deux motifs sont courants.

La directive include fonctionne dans n'importe quel contexte. Vous pouvez l'utiliser dans les blocs http, server ou location :

server {
    listen 443 ssl;
    include snippets/ssl-params.conf;
}

C'est ainsi que fonctionne le répertoire snippets/. Vous écrivez un fragment réutilisable une seule fois et vous l'incluez où vous en avez besoin.

Un point à surveiller : Nginx refuse de démarrer si un include sans glob ne correspond à aucun fichier. Si vous écrivez include /etc/nginx/conf.d/*.conf; et que le répertoire est vide, Nginx démarre sans problème (les globs peuvent ne rien correspondre). Mais include /etc/nginx/ssl.conf; échouera si ce fichier n'existe pas.

Quelle est la différence entre sites-available, sites-enabled et conf.d ?

Ces trois répertoires servent des objectifs différents. Debian et Ubuntu utilisent les trois.

Répertoire Fonction Comment Nginx le lit Quand l'utiliser
sites-available/ Stocke toutes les configs de virtual hosts Pas lu directement Toujours. Un fichier par domaine.
sites-enabled/ Contient des liens symboliques vers les configs actives Inclus via include /etc/nginx/sites-enabled/*; Créez un lien symbolique ici pour activer un site.
conf.d/ Fragments de config à chargement automatique Inclus via include /etc/nginx/conf.d/*.conf; Paramètres http globaux, blocs upstream, maps.

Le modèle sites-available / sites-enabled permet de désactiver un site sans supprimer sa configuration. Pour activer un site :

ln -s /etc/nginx/sites-available/example.com /etc/nginx/sites-enabled/

Pour le désactiver :

rm /etc/nginx/sites-enabled/example.com

Puis rechargez :

sudo nginx -t && sudo systemctl reload nginx

Lancez toujours nginx -t avant de recharger. Cette commande valide la config sans affecter le trafic en cours.

Le répertoire conf.d/ est plus simple. Chaque fichier .conf qu'il contient est automatiquement chargé. Pas de liens symboliques. Certains administrateurs préfèrent conf.d/ pour sa simplicité et n'utilisent pas du tout sites-available/sites-enabled. Les deux approches fonctionnent. Choisissez-en une et restez cohérent.

Un piège : si vous utilisez à la fois conf.d/ et sites-enabled/, assurez-vous de ne pas définir de blocs server en conflit dans les deux endroits. Nginx chargera les deux, et le résultat dépend des règles de fusion des directives et de la correspondance server_name.

Comment fonctionne l'héritage des directives Nginx ?

Nginx transmet les directives des contextes parents vers les contextes enfants. C'est la partie que la plupart des gens comprennent mal, et la source de bugs subtils en production.

Il existe trois types de directives, et chacun hérite différemment.

Directives normales

Les directives normales contiennent une seule valeur. Si un contexte enfant définit la même directive, il remplace entièrement la valeur du parent. Si l'enfant ne la définit pas, la valeur du parent est héritée.

Exemple : root est une directive normale.

http {
    root /var/www/default;

    server {
        server_name example.com;
        # root is inherited: /var/www/default

        location /app {
            root /var/www/app;
            # root is overridden: /var/www/app
        }

        location /blog {
            # root is inherited: /var/www/default
        }
    }
}

Autres directives normales : index, access_log (quand utilisé une seule fois), error_log, client_max_body_size.

Directives de type tableau

Les directives de type tableau (array directives) peuvent apparaître plusieurs fois dans un même contexte pour accumuler des valeurs. Mais quand un contexte enfant en définit ne serait-ce qu'une seule instance, il remplace toutes les valeurs du parent. Il ne les fusionne pas. Il les remplace.

add_header est la directive de type tableau la plus courante. Ce comportement cause un bug bien connu en production.

Que se passe-t-il quand vous ajoutez des en-têtes dans les blocs http et location ?

Si vous définissez add_header dans le contexte http puis un autre add_header dans un bloc location, le bloc location efface tous les en-têtes du contexte http. Pas seulement celui que vous remplacez. Tous.

http {
    add_header X-Frame-Options "SAMEORIGIN";
    add_header X-Content-Type-Options "nosniff";

    server {
        server_name example.com;

        location /api/ {
            add_header X-Custom "api-response";
            # X-Frame-Options is GONE
            # X-Content-Type-Options is GONE
            # Only X-Custom is sent
        }
    }
}

Pour vérifier que cela se produit sur votre serveur :

curl -I https://example.com/api/

Vérifiez les en-têtes de réponse. Si vos en-têtes de sécurité sont absents des réponses /api/ mais présents sur les autres chemins, c'est la raison.

La solution : répéter tous les en-têtes dans le contexte enfant.

location /api/ {
    add_header X-Frame-Options "SAMEORIGIN";
    add_header X-Content-Type-Options "nosniff";
    add_header X-Custom "api-response";
}

Ou utiliser un snippet :

# /etc/nginx/snippets/security-headers.conf
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header Strict-Transport-Security "max-age=63072000" always;
location /api/ {
    include snippets/security-headers.conf;
    add_header X-Custom "api-response";
}

Note : Nginx 1.29.3+ a introduit add_header_inherit merge; qui change ce comportement. Avec merge, les contextes enfants ajoutent aux en-têtes du parent au lieu de les remplacer. Si vous utilisez Nginx 1.28.x (la version stable actuelle en mars 2026), vous n'avez pas encore cette fonctionnalité.

Le même comportement d'effacement s'applique à proxy_set_header. Si vous définissez un proxy_set_header dans un bloc location, toutes les directives proxy_set_header du contexte server ou http sont perdues. La documentation officielle le dit explicitement : « These directives are inherited from the previous configuration level if and only if there are no proxy_set_header directives defined on the current level. »

server {
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

    location /api/ {
        proxy_set_header X-Request-ID $request_id;
        # Host, X-Real-IP, X-Forwarded-For are all GONE
        proxy_pass http://backend;
    }
}

Corrigez de la même façon : répétez tous les en-têtes dans le bloc location, ou utilisez un snippet include.

Directives d'action

Les directives d'action comme rewrite et return ne sont pas héritées dans les contextes imbriqués. Elles s'exécutent uniquement dans le contexte où elles sont définies.

server {
    rewrite ^/old/(.*)$ /new/$1 permanent;

    location /app {
        # The rewrite above does NOT apply here
        # Requests matching /app are handled by this location
    }
}

La directive try_files présente un piège lié à ce fonctionnement. Quand elle est placée dans le contexte server, Nginx crée une pseudo-location implicite avec la priorité la plus basse. Si un bloc location classique correspond à la requête, le try_files au niveau du serveur ne s'exécute jamais :

server {
    try_files $uri /index.php;   # Never runs for /app/* requests
    location /app { }            # This catches them first
}

Placez toujours try_files à l'intérieur d'un bloc location spécifique.

Comment inspecter la configuration effective de Nginx ?

Deux commandes vous aident à comprendre ce que Nginx voit réellement après avoir résolu toutes les directives include.

Tester la config pour les erreurs de syntaxe :

sudo nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful

Lancez toujours cette commande avant de recharger. Si le test échoue, Nginx vous indique le fichier et le numéro de ligne.

Afficher la configuration complète fusionnée :

sudo nginx -T

Cette commande affiche la configuration effective complète avec tous les includes résolus et insérés en ligne. Envoyez la sortie vers less pour une meilleure lisibilité :

sudo nginx -T | less

Ou recherchez une directive spécifique :

sudo nginx -T | grep -n "add_header"

Cela affiche chaque directive add_header dans tous les fichiers inclus, avec les numéros de ligne dans la sortie fusionnée. Utilisez ceci pour déboguer les problèmes d'héritage. Si un en-tête apparaît dans le bloc http mais pas dans un bloc location, et que vous ne voyez aucun add_header dans cette location, l'en-tête est hérité. Si vous voyez un add_header différent dans la location, tous les en-têtes du parent sont effacés.

Utilisez nginx -T chaque fois que les modifications de config ne se comportent pas comme prévu.

Référence rapide : la vue d'ensemble

/etc/nginx/nginx.conf
│
├─ main context (process-level: user, worker_processes, pid)
│
├─ events { }  (connection handling: worker_connections)
│
└─ http { }    (all HTTP config)
   │
   ├─ include conf.d/*.conf      (global HTTP settings, upstreams, maps)
   ├─ include sites-enabled/*    (virtual host configs)
   │
   └─ server { }                 (one per domain/port)
      │
      ├─ listen, server_name     (routing)
      ├─ root, index             (defaults for this host)
      │
      └─ location { }           (URI pattern matching)
         ├─ try_files, root      (per-path behavior)
         └─ proxy_pass           (reverse proxy target)

Inheritance: parent -> child (down only)
Normal directives: child overrides parent
Array directives: child REPLACES ALL parent values
Action directives: no inheritance
Structure des fichiers de config Nginx