Guide complet pour déployer un site statique sécurisé avec Nginx, HTTPS auto-signé, headers de sécurité et rate limiting.
Assure-toi d'avoir tout ça :
Structure de fichiers à créer dans /var/www/secure_web :
Crée le dossier :
sudo mkdir -p /var/www/secure_web/css
Deux pages à créer : accueil et mesures de sécurité.
Crée le fichier /var/www/secure_web/index.html :
sudo nano /var/www/secure_web/index.html
Exemple minimal :
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Secure Web</title>
<link rel="stylesheet" href="css/style.css">
</head>
<body>
<h1>Bienvenue sur Secure Web</h1>
<p>Site sécurisé avec Nginx, HTTPS et headers de sécurité.</p>
<a href="about.html">Voir les mesures de sécurité</a>
</body>
</html>
Crée le fichier /var/www/secure_web/about.html :
sudo nano /var/www/secure_web/about.html
Exemple minimal :
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Sécurité</title>
<link rel="stylesheet" href="css/style.css">
</head>
<body>
<h1>Mesures de sécurité</h1>
<ul>
<li>HTTPS avec certificat SSL</li>
<li>Headers : HSTS, CSP, X-Frame-Options</li>
<li>Rate limiting activé</li>
<li>Version Nginx masquée</li>
</ul>
<a href="index.html">Retour</a>
</body>
</html>
Crée le fichier /var/www/secure_web/css/style.css avec un design moderne.
sudo nano /var/www/secure_web/css/style.css
Exemple minimal :
* { margin: 0; padding: 0; box-sizing: border-box; }
body {
font-family: sans-serif;
background: #0a0a0a;
color: #e0e0e0;
max-width: 700px;
margin: 0 auto;
padding: 40px 20px;
}
h1 { color: #00d2ff; margin-bottom: 16px; }
a { color: #00d2ff; }
ul { margin: 16px 0 16px 20px; }
li { margin-bottom: 8px; }
Installe et vérifie que Nginx tourne.
sudo apt update && sudo apt install nginx -y
sudo systemctl status nginx
Crée le fichier de config et applique les premières mesures.
sudo nano /etc/nginx/sites-available/secure_web.conf
Dans le fichier /etc/nginx/nginx.conf, ajoute dans le bloc http { } :
server_tokens off;
Pourquoi ? Masquer la version empêche un attaquant de cibler des failles spécifiques à ta version de Nginx.
Dans le fichier /etc/nginx/sites-available/secure_web.conf, bloc server { } :
autoindex off;
Autorise uniquement GET, HEAD et POST. Toujours dans /etc/nginx/sites-available/secure_web.conf :
if ($request_method !~ ^(GET|HEAD|POST)$) {
return 405;
}
Installe Certbot et génère un certificat SSL gratuit via Let's Encrypt.
sudo apt install certbot python3-certbot-nginx -y
Certbot va automatiquement modifier ta config Nginx pour activer HTTPS :
sudo certbot --nginx -d secure_web.local
En local ? Certbot ne fonctionne qu'avec un vrai nom de domaine. Pour un environnement local, utilise un certificat auto-signé à la place :
sudo mkdir -p /etc/nginx/ssl
sudo openssl req -x509 -nodes \
-days 365 \
-newkey rsa:2048 \
-keyout /etc/nginx/ssl/secure_web.key \
-out /etc/nginx/ssl/secure_web.crt \
-subj "/CN=secure_web.local"
Résultat : les fichiers sont créés dans /etc/nginx/ssl/ — secure_web.crt (certificat) et secure_web.key (clé privée).
Ajoute ces lignes dans le bloc server { } du fichier /etc/nginx/sites-available/secure_web.conf :
# Écouter sur le port 443 (HTTPS) listen 443 ssl; server_name secure_web.local; # Certificat et clé ssl_certificate /etc/nginx/ssl/secure_web.crt; ssl_certificate_key /etc/nginx/ssl/secure_web.key; # Protocoles TLS autorisés (1.2 et 1.3 uniquement) ssl_protocols TLSv1.2 TLSv1.3; # Cache de session SSL (performance) ssl_session_cache shared:SSL:10m; ssl_session_timeout 10m;
Un bloc server séparé redirige tout le trafic HTTP vers HTTPS. Toujours dans le fichier /etc/nginx/sites-available/secure_web.conf, mais en dehors du bloc serveur 443.
# Bloc de redirection HTTP → HTTPS
server {
listen 80;
server_name secure_web.local;
return 301 https://$host$request_uri;
}
Attention : ce bloc est séparé du bloc server 443. Les deux blocs coexistent dans le même fichier.
Chaque header protège contre un type d'attaque. Ajoute-les dans le bloc server 443 du fichier /etc/nginx/sites-available/secure_web.conf :
# Force HTTPS (avec sous-domaines) add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always; # Anti-clickjacking add_header X-Frame-Options "DENY" always; # Anti MIME-sniffing add_header X-Content-Type-Options "nosniff" always; # Protection XSS add_header X-XSS-Protection "1; mode=block" always; # Politique de contenu (CSP) add_header Content-Security-Policy "default-src 'self';" always; # Contrôle du Referer add_header Referrer-Policy "strict-origin-when-cross-origin" always; # Désactive APIs sensibles add_header Permissions-Policy "geolocation=(), microphone=(), camera=()" always;
| Header | Protection |
|---|---|
Strict-Transport-Security | Force HTTPS, même si l'utilisateur tape http:// |
X-Frame-Options | Bloque le clickjacking via iframe |
X-Content-Type-Options | Empêche le MIME sniffing |
X-XSS-Protection | Bloque les attaques XSS réfléchies |
Content-Security-Policy | Contrôle les sources de contenu autorisées |
Referrer-Policy | Limite les données de referrer |
Permissions-Policy | Désactive caméra, micro, géoloc |
Protège contre le brute force et le DDoS avec deux zones distinctes.
Dans le fichier /etc/nginx/nginx.conf, bloc http { } :
# 10 requêtes/seconde par IP pour index.html limit_req_zone $binary_remote_addr zone=index_limit:10m rate=10r/s; # 5 requêtes/minute par IP pour about.html limit_req_zone $binary_remote_addr zone=about_limit:10m rate=5r/m;
Dans le fichier /etc/nginx/sites-available/secure_web.conf, bloc server 443 :
location = /index.html {
limit_req zone=index_limit burst=20 nodelay;
}
location = /about.html {
limit_req zone=about_limit burst=5 nodelay;
}
burst = requêtes excédentaires en tampon. nodelay = traitées immédiatement sans file d'attente.
Le fichier /etc/nginx/sites-available/secure_web.conf final, prêt à copier-coller :
# ============================================
# Redirection HTTP → HTTPS
# ============================================
server {
listen 80;
server_name secure_web.local;
return 301 https://$host$request_uri;
}
# ============================================
# Serveur HTTPS principal
# ============================================
server {
listen 443 ssl;
server_name secure_web.local;
# --- Document Root ---
root /var/www/secure_web;
index index.html;
# --- SSL / TLS ---
ssl_certificate /etc/nginx/ssl/secure_web.crt;
ssl_certificate_key /etc/nginx/ssl/secure_web.key;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
# --- Sécurité de base ---
autoindex off;
# --- Méthodes HTTP autorisées ---
if ($request_method !~ ^(GET|HEAD|POST)$) {
return 405;
}
# --- Logs séparés ---
access_log /var/log/nginx/secure_web_access.log;
error_log /var/log/nginx/secure_web_error.log;
# --- Headers de sécurité ---
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
add_header X-Frame-Options "DENY" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header Content-Security-Policy "default-src 'self';" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
add_header Permissions-Policy "geolocation=(), microphone=(), camera=()" always;
# --- Rate Limiting ---
location = /index.html {
limit_req zone=index_limit burst=20 nodelay;
}
location = /about.html {
limit_req zone=about_limit burst=5 nodelay;
}
# --- Fallback ---
location / {
try_files $uri $uri/ =404;
}
}
Dernières étapes pour tout mettre en ligne.
Active le site dans sites-enabled.
sudo ln -s /etc/nginx/sites-available/secure_web.conf /etc/nginx/sites-enabled/
Vérifie qu'il n'y a aucune erreur de syntaxe.
sudo nginx -t
Attendu : syntax is ok et test is successful
Applique la nouvelle config.
sudo systemctl restart nginx
Pour que secure_web.local pointe vers ta machine.
echo "127.0.0.1 secure_web.local" | sudo tee -a /etc/hosts
Teste les headers et le certificat SSL.
# -I = headers only | -k = ignore certificat auto-signé curl -Ik https://secure_web.local/
Tu devrais voir : tous les headers de sécurité et aucune version Nginx affichée.
Checklist de tout ce qu'il faut fournir :
nginx -v et nginx -Vsecure_web.confcurl -Ik https://secure_web.local//var/www/secure_web# Version courte nginx -v # Version détaillée avec modules nginx -V # Headers HTTPS curl -Ik https://secure_web.local/ # Arborescence du site tree /var/www/secure_web # Contenu de la config cat /etc/nginx/sites-available/secure_web.conf # Détails du certificat SSL openssl x509 -in /etc/nginx/ssl/secure_web.crt -text -noout
Si tree n'est pas installé : sudo apt install tree