Linux Platform

Installer et configurer Nginx comme serveur web

Guide complet pour installer, configurer et sécurisér Nginx sur Linux : server blocks, reverse proxy, SSL/TLS, optimisation et monitoring.

1 heurenginxserveur-webreverse-proxysslperformance

Introduction

Nginx (prononce "engine-x") est un serveur web haute performance, un reverse proxy et un repartiteur de charge. Cree par Igor Sysoev en 2004, il est aujourd'hui utilisé par des millions de sites dans le monde grâce à son architecture événementielle non-bloquante qui lui permet de gérer un grand nombre de connexions simultanees avec une consommation mémoire reduite.

Ce guide vous accompagne de l'installation a la mise en production sécurisée d'un serveur Nginx.

Installation

Sur Debian / Ubuntu

Mettez a jour les paquets disponibles puis installez Nginx :

sudo apt update
sudo apt install -y nginx

Verifiez que le service est actif :

sudo systemctl status nginx

Activez le démarrage automatique au boot :

sudo systemctl enable nginx

Sur Fedora / RHEL / AlmaLinux

sudo dnf install -y nginx
sudo systemctl start nginx
sudo systemctl enable nginx

Si vous utilisez firewalld, ouvrez les ports HTTP et HTTPS :

sudo firewall-cmd --permanent --add-service=http
sudo firewall-cmd --permanent --add-service=https
sudo firewall-cmd --reload

Verifiez l'installation en accedant a l'adresse IP de votre serveur dans un navigateur. Vous devriez voir la page d'accueil par défaut de Nginx.

Architecture de Nginx

Nginx repose sur une architecture maitre/travailleurs (master/workers). Comprendre ce modèle est essentiel pour bien configurer le serveur.

Processus master : il lit la configuration, ouvre les ports d'ecoute et créé les processus workers. Il ne traite jamais de requêtes lui-meme.

Processus workers : chaque worker gère les connexions entrantes de facon asynchrone grâce à une bouclé événementielle (epoll sur Linux). Un seul worker peut traiter des milliers de connexions simultanees sans créer de thread supplementaire.

Les directives clés qui contrôlent cette architecture se trouvent dans le bloc principal de la configuration :

# /etc/nginx/nginx.conf
worker_processes auto;          # Un worker par coeur CPU (recommande)
worker_rlimit_nofile 65535;     # Nombre max de fichiers ouverts par worker
 
events {
    worker_connections 4096;    # Connexions simultanees par worker
    multi_accept on;            # Accepter plusieurs connexions a la fois
    use epoll;                  # Methode d'E/S la plus performante sous Linux
}

La capacité maximale theorique de votre serveur est : worker_processes x worker_connections. Avec 4 workers et 4096 connexions chacun, vous pouvez gérer jusqu'a 16 384 connexions simultanees.

Configuration de base

Le fichier de configuration principal se trouve a /etc/nginx/nginx.conf. Sur Debian/Ubuntu, les server blocks sont dans /etc/nginx/sites-available/ avec des liens symboliques dans /etc/nginx/sites-enabled/. Sur Fedora/RHEL, ils sont dans /etc/nginx/conf.d/.

Voici la structure générale du fichier principal :

# /etc/nginx/nginx.conf
user www-data;                  # Utilisateur sous lequel tournent les workers
worker_processes auto;
pid /run/nginx.pid;
error_log /var/log/nginx/error.log warn;
 
events {
    worker_connections 2048;
}
 
http {
    include /etc/nginx/mime.types;
    default_type application/octet-stream;
 
    # Format de logs personnalisé
    log_format main '$remote_addr - $remote_user [$time_local] '
                    '"$request" $status $body_bytes_sent '
                    '"$http_referer" "$http_user_agent"';
 
    access_log /var/log/nginx/access.log main;
 
    sendfile on;
    tcp_nopush on;
    tcp_nodelay on;
    keepalive_timeout 65;
    types_hash_max_size 2048;
 
    # Inclure les server blocks
    include /etc/nginx/conf.d/*.conf;
    include /etc/nginx/sites-enabled/*;
}

Apres chaque modification, vérifiéz la syntaxe avant de recharger :

sudo nginx -t
sudo systemctl reload nginx

Server blocks (virtual hosts)

Les server blocks permettent d'hébergér plusieurs sites sur le meme serveur. Chaque bloc définit un domaine, un port d'ecoute et un répertoire racine.

Creez un fichier pour votre site :

sudo nano /etc/nginx/sites-available/monsite.example.com

Contenu du fichier :

server {
    listen 80;
    listen [::]:80;
    server_name monsite.example.com www.monsite.example.com;
 
    root /var/www/monsite.example.com/html;
    index index.html index.htm;
 
    # Page d'erreur personnalisée
    error_page 404 /404.html;
    error_page 500 502 503 504 /50x.html;
 
    location / {
        try_files $uri $uri/ =404;
    }
 
    # Desactiver l'accès aux fichiers caches
    location ~ /\. {
        deny all;
        access_log off;
        log_not_found off;
    }
}

Activez le site et rechargez Nginx :

sudo mkdir -p /var/www/monsite.example.com/html
echo "<h1>Bienvenue sur monsite</h1>" | sudo tee /var/www/monsite.example.com/html/index.html
sudo ln -s /etc/nginx/sites-available/monsite.example.com /etc/nginx/sites-enabled/
sudo nginx -t && sudo systemctl reload nginx

Servir des fichiers statiques

Nginx excelle dans la distribution de fichiers statiques. Configurez un bloc location dédié avec mise en cache navigateur :

server {
    listen 80;
    server_name static.example.com;
    root /var/www/static;
 
    # Cache long pour les ressources immutables (CSS, JS, images)
    location ~* \.(css|js|png|jpg|jpeg|gif|ico|svg|woff2|woff|ttf)$ {
        expires 30d;
        add_header Cache-Control "public, immutable";
        access_log off;
    }
 
    # Compression gzip pour le texte
    gzip on;
    gzip_types text/plain text/css application/json application/javascript text/xml;
    gzip_min_length 1000;
    gzip_comp_level 5;
 
    location / {
        try_files $uri $uri/ =404;
    }
}

Pour vérifiér que la compression fonctionne :

curl -H "Accept-Encoding: gzip" -I http://static.example.com/style.css

Vous devriez voir l'en-tete Content-Encoding: gzip dans la reponse.

Reverse proxy

L'un des usages les plus courants de Nginx est de servir de reverse proxy devant une application (Node.js, Python, Java, etc.). Nginx reçoit les requêtes des clients, les transmet a l'application backend, puis renvoie la reponse au client.

upstream backend_app {
    server 127.0.0.1:3000;     # Instance principale
    server 127.0.0.1:3001;     # Instance secondaire (load balancing)
    keepalive 32;               # Connexions persistantes vers le backend
}
 
server {
    listen 80;
    server_name app.example.com;
 
    location / {
        proxy_pass http://backend_app;
        proxy_http_version 1.1;
 
        # En-tetes pour transmettre les infos du client original
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
 
        # Support des WebSockets
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
 
        # Timeouts
        proxy_connect_timeout 60s;
        proxy_send_timeout 60s;
        proxy_read_timeout 60s;
    }
}

Testez que le proxy fonctionne correctement :

curl -v http://app.example.com/

SSL/TLS avec Let's Encrypt

Securisez votre site avec un certificat gratuit Let's Encrypt via Certbot.

Installation de Certbot

Sur Debian/Ubuntu :

sudo apt install -y certbot python3-certbot-nginx

Sur Fedora :

sudo dnf install -y certbot python3-certbot-nginx

Obtenir et installer le certificat

sudo certbot --nginx -d monsite.example.com -d www.monsite.example.com

Certbot modifié automatiquement votre server block pour ajouter la configuration SSL. Verifiez le résultat :

sudo nginx -t && sudo systemctl reload nginx

Renouvellement automatique

Les certificats Let's Encrypt expirent après 90 jours. Certbot installé un timer systemd pour le renouvellement automatique. Verifiez son fonctionnement :

sudo systemctl status certbot.timer
sudo certbot renew --dry-run

Votre server block après activation de SSL ressemblera a ceci :

server {
    listen 443 ssl http2;
    listen [::]:443 ssl http2;
    server_name monsite.example.com;
 
    ssl_certificate /etc/letsencrypt/live/monsite.example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/monsite.example.com/privkey.pem;
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers HIGH:!aNULL:!MD5;
    ssl_prefer_server_ciphers on;
    ssl_session_cache shared:SSL:10m;
    ssl_session_timeout 10m;
 
    root /var/www/monsite.example.com/html;
    index index.html;
 
    location / {
        try_files $uri $uri/ =404;
    }
}
 
# Redirection HTTP vers HTTPS
server {
    listen 80;
    server_name monsite.example.com www.monsite.example.com;
    return 301 https://$host$request_uri;
}

Optimisation des performances

Mise en cache des fichiers ouverts

open_file_cache max=10000 inactive=20s;
open_file_cache_valid 30s;
open_file_cache_min_uses 2;
open_file_cache_errors on;

Buffers et timeouts

client_body_buffer_size 16k;
client_header_buffer_size 1k;
client_max_body_size 50m;
large_client_header_buffers 4 8k;
 
client_body_timeout 12;
client_header_timeout 12;
send_timeout 10;

Cache de proxy

Si vous utilisez Nginx comme reverse proxy, activez le cache :

proxy_cache_path /var/cache/nginx levels=1:2 keys_zone=app_cache:10m
                 max_size=1g inactive=60m use_temp_path=off;
 
server {
    location / {
        proxy_pass http://backend_app;
        proxy_cache app_cache;
        proxy_cache_valid 200 302 10m;
        proxy_cache_valid 404 1m;
        add_header X-Cache-Status $upstream_cache_status;
    }
}

Verifiez les hits de cache dans les en-tetes de reponse :

curl -I http://app.example.com/page
# Cherchez : X-Cache-Status: HIT

Logging et monitoring

Logs d'accès personnalisés

log_format detailed '$remote_addr - $remote_user [$time_local] '
                    '"$request" $status $body_bytes_sent '
                    '"$http_referer" "$http_user_agent" '
                    '$request_time $upstream_response_time';
 
access_log /var/log/nginx/access.log detailed;

Analyser les logs en temps reel

# Suivre les requêtes en direct
tail -f /var/log/nginx/access.log
 
# Compter les codes de statut HTTP
awk '{print $9}' /var/log/nginx/access.log | sort | uniq -c | sort -rn
 
# Lister les 10 IPs les plus actives
awk '{print $1}' /var/log/nginx/access.log | sort | uniq -c | sort -rn | head -10
 
# Identifier les requêtes les plus lentes (si le format inclut request_time)
awk '{print $NF, $7}' /var/log/nginx/access.log | sort -rn | head -20

Page de statut Nginx

Activez le module stub_status pour surveiller le serveur :

server {
    listen 127.0.0.1:8080;
 
    location /nginx_status {
        stub_status;
        allow 127.0.0.1;
        deny all;
    }
}

Consultez les statistiques :

curl http://127.0.0.1:8080/nginx_status

Securite

Rate limiting

Protegez votre serveur contre les abus en limitant le nombre de requêtes par client :

# Definir la zone de limitation (dans le bloc http)
limit_req_zone $binary_remote_addr zone=général:10m rate=10r/s;
limit_req_zone $binary_remote_addr zone=login:10m rate=1r/s;
 
server {
    # Appliquer la limite globale
    location / {
        limit_req zone=général burst=20 nodelay;
        try_files $uri $uri/ =404;
    }
 
    # Limite stricte sur la page de connexion
    location /login {
        limit_req zone=login burst=3 nodelay;
        proxy_pass http://backend_app;
    }
}

En-tetes de sécurité

Ajoutez des en-tetes HTTP pour renforcer la sécurité côté client :

# Dans le bloc server ou http
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
add_header Content-Security-Policy "default-src 'self'; script-src 'self'" always;
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;

Masquer la version de Nginx

# Dans le bloc http
server_tokens off;

Restreindre les méthodes HTTP

location / {
    if ($request_method !~ ^(GET|HEAD|POST)$) {
        return 405;
    }
    try_files $uri $uri/ =404;
}

Verifiez la configuration de sécurité de votre site avec :

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

Vous devriez voir tous les en-tetes de sécurité dans la reponse.

Resume des commandes essentielles

# Tester la configuration
sudo nginx -t
 
# Recharger sans coupure
sudo systemctl reload nginx
 
# Redémarrer complètement
sudo systemctl restart nginx
 
# Voir les logs d'erreur
sudo tail -f /var/log/nginx/error.log
 
# Voir les logs d'acces
sudo tail -f /var/log/nginx/access.log
 
# Verifier les processus Nginx
ps aux | grep nginx