Installer et configurer nginx sur Debian et Ubuntu
Du paquet apt au premier bloc server avec PHP-FPM et HTTPS : quelle version de nginx livre chaque distribution, ce qui change avec le dépôt nginx.org et comment se débarrasser des erreurs classiques.
Installer nginx prend trente secondes. C'est le reste de la journée qui part en fumée, parce que le bloc server ne s'applique pas, parce que PHP renvoie une 502 ou parce qu'Apache occupe déjà le port 80. Cet article passe exactement ces points en revue, et ce séparément pour Debian 13, Debian 12, Ubuntu 24.04 et Ubuntu 22.04, car les quatre systèmes se comportent différemment sur plusieurs aspects.
Quel nginx : paquet de la distribution ou dépôt officiel
La première décision se prend avant la première commande. Chaque distribution livre une version figée qui ne reçoit plus que des correctifs de sécurité. En juillet 2026, la situation est la suivante :
| Système | nginx dans le paquet de la distribution |
| Debian 13 (trixie) | 1.26.3 |
| Debian 12 (bookworm) | 1.22.1 |
| Ubuntu 24.04 LTS (noble) | 1.24.0 |
| Ubuntu 22.04 LTS (jammy) | 1.18.0 |
Chez nginx.org, les branches 1.30.4 (stable) et 1.31.3 (mainline) sont disponibles en juillet 2026. L'écart avec Ubuntu 22.04 représente donc environ six ans de développement de fonctionnalités.
Prenez le paquet de la distribution si vous exploitez des sites web classiques ou des configurations de reverse proxy et que vous voulez laisser unattended-upgrades faire le travail. Prenez le dépôt nginx.org si vous avez besoin de HTTP/3 et de QUIC (totalement absents d'Ubuntu 22.04, et de Debian 12 également), si vous voulez des modules dynamiques prêts à l'emploi comme nginx-module-brotli ou le module ACME, ou si vous souhaitez faire tourner exactement la même version sur plusieurs distributions.
Ce que beaucoup de tutoriels passent sous silence : les deux paquets ne sont pas le même programme en versions différentes, ils sont compilés différemment et empaquetés différemment. C'est la raison la plus fréquente pour laquelle un tutoriel recopié ne fonctionne pas.
| Caractéristique | Paquet Debian/Ubuntu | Paquet nginx.org |
| Utilisateur du processus | www-data | nginx |
| Docroot par défaut | /var/www/html | /usr/share/nginx/html |
| sites-available et sites-enabled | présent | n'existe pas |
| /etc/nginx/snippets/ | présent | n'existe pas |
| Profils ufw (Nginx Full, etc.) | présent | n'existe pas |
| Modules dynamiques | libnginx-mod-* | nginx-module-* |
Installation depuis le paquet de la distribution
Identique sur les quatre systèmes :
apt update
apt install -y nginx
apt install -y curl
Le métapaquet nginx suffit. nginx-full et nginx-extras existent toujours dans Debian 12 et 13, mais ils ne font qu'ajouter des paquets de modules supplémentaires. Les modules individuels, vous les récupérez de façon ciblée, par exemple avec apt install libnginx-mod-http-headers-more-filter.
curl figure volontairement dans la même série. Ce n'est pas une dépendance de nginx et il manque sur un Debian ou un Ubuntu fraîchement installé, même une fois nginx correctement en place. Sans cette étape, la première commande de vérification ci-dessous s'arrête sur curl: command not found, et le même piège vous rattrape plus tard lors du test de l'en-tête Host et du test PHP.
Vient maintenant la partie que la plupart des tutoriels omettent : la preuve que tout tourne vraiment. Un apt install sans message d'erreur ne prouve strictement rien.
nginx -v
systemctl is-enabled nginx
systemctl is-active nginx
curl -I http://127.0.0.1/
Vous devez obtenir enabled, active et un HTTP/1.1 200 OK avec un en-tête Server qui mentionne nginx (Debian 13 répond Server: nginx, Ubuntu 24.04 Server: nginx/1.24.0). C'est seulement à ce moment que le serveur web est réellement en place. Pour savoir avec quelles options le paquet a été compilé, utilisez nginx -V (V majuscule) : la sortie indique aussi si --with-http_v3_module en fait partie.
Si ufw est actif, il manque encore la règle de pare-feu. Avant cela, un mot sur le paquet lui-même : sur Ubuntu Server, ufw est installé d'origine et simplement inactif, alors que sur Debian il est totalement absent. Le premier appel s'y solde sinon par ufw: command not found. Installez-le donc au passage, le paquet est disponible sur les quatre systèmes :
apt install -y ufw
ufw app list
ufw allow 'Nginx Full'
Les profils sont fournis par le paquet nginx-common de la distribution : Nginx Full, Nginx HTTP et Nginx HTTPS, plus Nginx QUIC sur Debian 13. Avec une installation issue du dépôt nginx.org, ils n'apparaissent tout simplement pas dans ufw app list (voir le tableau plus haut).
Ajouter le dépôt officiel nginx
nginx.org prend en charge bookworm, trixie, jammy et noble. apt-key est déprécié : la clé doit aller dans son propre trousseau et être référencée via signed-by.
apt install -y curl gnupg2 ca-certificates lsb-release debian-archive-keyring
Sur Ubuntu, le dernier paquet s'appelle ubuntu-keyring et non debian-archive-keyring. Ensuite :
mkdir -p /root/.gnupg && chmod 700 /root/.gnupg
curl https://nginx.org/keys/nginx_signing.key | gpg --dearmor | tee /usr/share/keyrings/nginx-archive-keyring.gpg >/dev/null
gpg --dry-run --quiet --no-keyring --import --import-options import-show /usr/share/keyrings/nginx-archive-keyring.gpg
Le mkdir de la première ligne n'est pas du remplissage. Sur un serveur fraîchement installé, /root/.gnupg n'existe pas encore, et le gpg 2.4.7 de Debian 13 ne crée pas ce répertoire de lui-même dans cette combinaison d'appels bien précise. La commande de vérification s'interrompt alors sur gpg: Fatal: /root/.gnupg: directory does not exist!, et ce en plein milieu de la sortie, donc avant l'apparition des empreintes. Pour les voir, il faut créer le répertoire au préalable ; un simple gpg --list-keys lancé une fois suffit également.
La dernière commande n'est pas décorative non plus, c'est le véritable contrôle. Elle affiche trois clés, c'est voulu et ce n'est pas une raison de s'arrêter : la clé de signature actuelle 8540 A6F1 8833 A80E 9C16 53A4 2FD2 1310 B49F 6B46 (signing-key-2@nginx.com), plus 573B FD6B 3D8F BC64 1079 A6AB ABF5 BD82 7BD9 BF62 et 9E9B E90E ACBC DE69 FE9B 204C BCDC D8A3 8D88 A2B3. Si d'autres empreintes s'affichent, le téléchargement a livré autre chose que ce qui était attendu, et vous vous arrêtez ici.
Passons à la source de paquets. Faites attention au segment de chemin qui suit /packages/, car nginx.org maintient deux arborescences distinctes pour Debian et pour Ubuntu. Sous /packages/debian/dists/, ni noble ni jammy n'existent : les paquets Ubuntu se trouvent exclusivement sous /packages/ubuntu/. La version ci-dessous détermine le segment elle-même et fonctionne donc telle quelle sur les deux familles :
OS=$(. /etc/os-release; echo $ID)
echo "deb [signed-by=/usr/share/keyrings/nginx-archive-keyring.gpg] http://nginx.org/packages/$OS $(lsb_release -cs) nginx" | tee /etc/apt/sources.list.d/nginx.list
$ID vaut debian sur Debian et ubuntu sur Ubuntu : le chemin s'adapte donc automatiquement à la distribution. Si vous inscrivez à la place packages/debian en dur, parce que vous suivez un tutoriel Debian sur un Ubuntu, echo écrit la ligne sans broncher et l'erreur n'apparaît qu'au prochain apt update :
Err: http://nginx.org/packages/debian noble Release
E: The repository 'http://nginx.org/packages/debian noble Release' does not have a Release file.
Sur Ubuntu 22.04, c'est jammy qui figure à cet endroit au lieu de noble, la cause est la même. Pour la branche mainline, insérez mainline/ devant le nom de la distribution. Pour qu'apt privilégie effectivement le paquet nginx.org par rapport à celui de la distribution, il faut un pinning, sinon c'est le mauvais qui l'emporte selon le numéro de version :
printf 'Package: *\nPin: origin nginx.org\nPin: release o=nginx\nPin-Priority: 900\n' | tee /etc/apt/preferences.d/99nginx
apt update
apt-cache policy nginx
apt install -y nginx
apt-cache policy nginx est le contrôle avant l'installation : la ligne Candidate doit afficher la version nginx.org (par exemple 1.30.4-1~noble) et la priorité doit être le 900 du fichier de pin. Si la version de la distribution y figure encore, le pinning ne s'applique pas et vous installez d'emblée le mauvais paquet.
Migrer depuis une installation existante de la distribution
Si le paquet de la distribution tourne déjà, la mise à niveau échoue. Le message ressemble à ceci :
dpkg: error processing archive /var/cache/apt/archives/nginx_1.30.4-1~bookworm_amd64.deb (--unpack):
trying to overwrite '/etc/nginx/mime.types', which is also in package nginx-common 1.22.1-9+deb12u9
Le paquet nginx.org ne connaît pas nginx-common, d'où la collision des fichiers. La méthode propre : sauvegarder d'abord la configuration, supprimer ensuite le paquet de la distribution, puis réinstaller.
tar czf /root/nginx-config-backup.tar.gz /etc/nginx
systemctl stop nginx
apt purge -y nginx nginx-common
apt install -y nginx
Le fait que tar affiche tar: Removing leading '/' from member names est normal et ne constitue pas une erreur. Ensuite, /etc/nginx/sites-available a disparu et vos anciens vhosts ne se trouvent plus que dans l'archive. Copiez-les vers /etc/nginx/conf.d/ et donnez-leur l'extension .conf, sans quoi ils ne seront pas chargés. Faites attention à deux points : include snippets/fastcgi-php.conf; n'existe pas dans le paquet nginx.org, et l'utilisateur du processus s'appelle désormais nginx, ce qui concerne les droits des fichiers et les sockets PHP-FPM.
Bien comprendre sites-available et sites-enabled
Le modèle à deux répertoires est une pure invention de Debian, nginx lui-même ne le connaît pas. /etc/nginx/sites-available/ contient tous les fichiers de configuration, /etc/nginx/sites-enabled/ contient les liens symboliques vers ceux qui sont actifs. Seul ce qui figure dans nginx.conf via include est réellement chargé. En cas de doute, vérifiez-le vous-même :
grep include /etc/nginx/nginx.conf
Dans le paquet Debian et Ubuntu, on y trouve deux lignes, include /etc/nginx/conf.d/*.conf; et include /etc/nginx/sites-enabled/*;. Dans le paquet nginx.org, seule la première est présente. C'est exactement de là que vient le grand classique : quelqu'un suit un tutoriel Ubuntu sur un paquet nginx.org, crée /etc/nginx/sites-available/mon-site, pose le lien symbolique, obtient un syntax is ok impeccable avec nginx -t, et pourtant rien ne se passe. Il n'y a aucun message d'erreur, parce que ce répertoire n'intéresse tout simplement personne.
Le contre-test qui dit toujours la vérité, c'est nginx -T avec un T majuscule. Il affiche la configuration complète, entièrement résolue, c'est-à-dire exactement ce que nginx voit réellement :
nginx -T | grep -n "server_name\|listen\|root"
Si votre server_name n'y apparaît pas, le fichier n'est pas lu. Point final. Continuer à déboguer la configuration elle-même est alors une perte de temps.
La deuxième erreur fréquente est un lien symbolique qui pointe dans le vide, par exemple après une faute de frappe ou parce que le fichier cible a été renommé :
nginx: [emerg] open() "/etc/nginx/sites-enabled/mon-site" failed (2: No such file or directory) in /etc/nginx/nginx.conf:62
Vous trouvez les liens symboliques cassés avec find /etc/nginx/sites-enabled/ -xtype l. Un site ne se désactive d'ailleurs jamais en supprimant le fichier dans sites-available, mais en retirant le lien symbolique avec unlink /etc/nginx/sites-enabled/mon-site.
Votre premier bloc server
Nous créons un site statique. D'abord le répertoire et un fichier de test :
mkdir -p /var/www/exemple/html
echo '<h1>Page de test KernelHost</h1>' > /var/www/exemple/html/index.html
chown -R www-data:www-data /var/www/exemple
Avec le paquet nginx.org, le propriétaire est nginx:nginx. Passons à la configuration, et vraiment comme une étape à part entière : le fichier doit exister avant que le lien symbolique ne pointe dessus. Créez-le avec votre éditeur ou écrivez-le directement via un heredoc ; avec le paquet nginx.org, il va à la place dans /etc/nginx/conf.d/exemple.conf :
cat > /etc/nginx/sites-available/exemple <<'EOF'
server {
listen 80;
listen [::]:80;
server_name exemple.fr www.exemple.fr;
root /var/www/exemple/html;
index index.html;
access_log /var/log/nginx/exemple.access.log;
error_log /var/log/nginx/exemple.error.log;
location / {
try_files $uri $uri/ =404;
}
}
EOF
Les guillemets simples autour de 'EOF' sont importants : sans eux, le shell remplace $uri par une chaîne vide et le bloc est déjà cassé au moment de l'enregistrement. Ensuite seulement, activez, testez et rechargez :
ln -s /etc/nginx/sites-available/exemple /etc/nginx/sites-enabled/
nginx -t
systemctl reload nginx
L'ordre n'est pas arbitraire. ln crée le lien symbolique même lorsque le fichier cible n'existe pas du tout, et sans dire un mot. Cela ne se voit qu'au moment du test :
nginx: [emerg] open() "/etc/nginx/sites-enabled/exemple" failed (2: No such file or directory) in /etc/nginx/nginx.conf:61
Le numéro de ligne varie selon le système (61 sur Debian 13, 60 sur Debian 12 et sur les deux Ubuntu), le message est identique. Dans cet état, un reload serait refusé : la configuration en cours d'exécution reste donc intacte. C'est précisément ce cas que détecte aussi find /etc/nginx/sites-enabled/ -xtype l.
Trois autres erreurs reviennent sans cesse à cet endroit.
Serveur par défaut en double. Si vous recopiez default_server depuis un tutoriel alors que le site par défaut de Debian est encore actif, vous obtenez :
nginx: [emerg] a duplicate default server for 0.0.0.0:80 in /etc/nginx/sites-enabled/exemple:2
Soit vous omettez le mot-clé, soit vous désactivez le site par défaut avec unlink /etc/nginx/sites-enabled/default.
Nom de serveur en double. Si le même nom figure dans deux blocs, c'est celui chargé en premier qui l'emporte sans commentaire, il n'y a qu'un avertissement :
nginx: [warn] conflicting server name "exemple.fr" on 0.0.0.0:80, ignored
Nom de serveur trop long. Avec des domaines longs ou de nombreux sous-domaines :
nginx: [emerg] could not build server_names_hash, you should increase server_names_hash_bucket_size: 32
Le remède est server_names_hash_bucket_size 64; dans le bloc http de nginx.conf.
La preuve de fonctionnement se fait sans DNS, via l'en-tête Host :
curl -H 'Host: exemple.fr' -sS http://127.0.0.1/
Si c'est la page par défaut de Debian qui s'affiche au lieu de votre page de test, votre bloc ne s'applique pas et vous atterrissez sur le serveur par défaut. Si c'est bien votre page, tout est en ordre.
Intégrer PHP-FPM
C'est ici que se cache le piège le plus désagréable de tout ce guide, et il coûte une heure à quantité de gens. Le métapaquet php dépend, via php8.x, de l'alternative libapache2-mod-php8.x | php8.x-fpm | php8.x-cgi. apt choisit toujours la première : apt install php installe donc immanquablement Apache au passage, et Apache occupe ensuite le port 80. Installez par conséquent de façon ciblée :
apt install -y php-fpm php-mysql php-xml php-curl php-mbstring php-zip
La version de PHP que vous obtenez et le nom du socket dépendent de la distribution :
| Système | PHP | Socket | Service |
| Debian 13 | 8.4 | /run/php/php8.4-fpm.sock | php8.4-fpm |
| Debian 12 | 8.2 | /run/php/php8.2-fpm.sock | php8.2-fpm |
| Ubuntu 24.04 | 8.3 | /run/php/php8.3-fpm.sock | php8.3-fpm |
| Ubuntu 22.04 | 8.1 | /run/php/php8.1-fpm.sock | php8.1-fpm |
Ne devinez pas le chemin, lisez-le :
ls -l /run/php/
Le bloc PHP dans le serveur (exemple pour Debian 12, adaptez le chemin) :
index index.php index.html;
location ~ \.php$ {
try_files $uri =404;
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_pass unix:/run/php/php8.2-fpm.sock;
fastcgi_index index.php;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param PATH_INFO $fastcgi_path_info;
}
location ~ /\.(?!well-known).* {
deny all;
}
Sur Debian et Ubuntu, vous pouvez remplacer les premières lignes par include snippets/fastcgi-php.conf;. Dans le paquet nginx.org, ce snippet n'existe pas : il vous faut alors la version écrite en entier. Le try_files $uri =404; n'est pas un effet de style, il empêche que des fichiers téléversés soient exécutés lorsque .php est accolé dans le chemin.
Il manque toutefois encore une étape, et elle est presque toujours sautée. L'appel de test qui suit passe par le vhost par défaut livré avec le paquet, et dans /etc/nginx/sites-available/default, la section location ~ \.php$ est intégralement commentée d'origine. Tant que cela reste ainsi, nginx transmet les fichiers .php tels quels : vous recevez un 200 OK avec Content-Type: application/octet-stream et le code source PHP en clair. Ce n'est pas un détail cosmétique. Dans un vrai fichier, on trouve à cet endroit des identifiants de base de données ou des clés d'API, et tous ceux qui connaissent l'URL les lisent alors en même temps que vous.
Commencez donc par activer ce bloc. Dans /etc/nginx/sites-available/default, retirez les caractères de commentaire qui le précèdent ou saisissez-le en entier :
location ~ \.php$ {
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/run/php/php8.4-fpm.sock;
}
Le nom du socket dépend de la distribution, le tableau plus haut l'indique : php8.4 sur Debian 13, php8.3 sur Ubuntu 24.04, php8.2 sur Debian 12, php8.1 sur Ubuntu 22.04. Testez ensuite, puis rechargez :
nginx -t
systemctl reload nginx
Ce n'est que maintenant que la vérification prend toute sa valeur : elle prouve que PHP tourne réellement via FPM et que le fichier n'est pas simplement proposé au téléchargement :
printf '<?php echo "PHP ", PHP_VERSION, " via ", php_sapi_name(), "\n";' > /var/www/html/kh-check.php
curl -s http://127.0.0.1/kh-check.php
rm /var/www/html/kh-check.php
Une sortie du type PHP 8.4.23 via fpm-fcgi est correcte, et sur Ubuntu 24.04 ce sera PHP 8.3.6 via fpm-fcgi. Si c'est le code source qui revient, location ~ \.php$ ne s'applique pas encore dans le vhost actif : il est donc toujours commenté ou il pointe vers le mauvais socket. N'oubliez pas de supprimer le fichier, et n'utilisez pas phpinfo() sur un serveur accessible depuis l'extérieur.
Lire correctement une 502 Bad Gateway
Une 502 n'est pas un diagnostic, le diagnostic se trouve dans /var/log/nginx/error.log. Trois lignes typiques reviennent :
connect() to unix:/run/php/php8.2-fpm.sock failed (2: No such file or directory) while connecting to upstream
Mauvais chemin, ou FPM ne tourne pas. Vérifiez avec systemctl status php8.2-fpm et ls /run/php/. Un déclencheur fréquent est une montée de version de la distribution : après le passage de Debian 12 à 13, l'ancienne configuration pointe encore vers php8.2-fpm.sock alors que la version installée est la 8.4.
connect() to unix:/run/php/php8.2-fpm.sock failed (13: Permission denied) while connecting to upstream
Cela ne concerne pratiquement que les installations issues du dépôt nginx.org. Le pool FPM appartient à www-data et a le mode 0660, alors que nginx y tourne sous l'utilisateur nginx. Dans /etc/php/8.2/fpm/pool.d/www.conf, définissez listen.group = nginx et redémarrez FPM.
FastCGI sent in stderr: "Primary script unknown" while reading response header from upstream
SCRIPT_FILENAME pointe dans le vide. La plupart du temps, root se trouve dans le bloc location au lieu du bloc server, ou bien il manque complètement.
HTTPS avec Let's Encrypt
Les versions de certbot des distributions sont très éloignées les unes des autres : Debian 13 livre la 4.0.0, Ubuntu 24.04 la 2.9.0, Debian 12 la 2.1.0 et Ubuntu 22.04 seulement la 1.21.0. Toutes parlent ACMEv2, mais la 1.21 est trop ancienne pour les fonctions récentes comme les certificats à durée de vie courte. Sur Ubuntu 22.04, le détour par snap en vaut la peine.
apt install -y certbot python3-certbot-nginx
certbot --version
Trois conditions doivent être remplies avant l'émission, sinon la validation échoue sans message exploitable : l'enregistrement A (et le cas échéant AAAA) pointe vers le serveur, le port 80 est joignable depuis l'extérieur, et il existe un bloc server avec le server_name correspondant. Le dernier point est déterminant, car le plugin nginx trouve le bloc par le server_name, pas par le nom du fichier. Ensuite :
certbot --nginx -d exemple.fr -d www.exemple.fr
certbot écrit alors dans votre fichier de configuration : un second bloc server avec listen 443 ssl, les chemins vers fullchain.pem et privkey.pem, un include /etc/letsencrypt/options-ssl-nginx.conf et une redirection depuis le port 80. Le fait que le fichier soit modifié surprend régulièrement. Si vous l'écrasez ensuite à la main, vous perdez le HTTPS et vous obtenez au rechargement suivant :
nginx: [emerg] cannot load certificate "/etc/letsencrypt/live/exemple.fr/fullchain.pem": BIO_new_file() failed
Le renouvellement automatique passe par un timer systemd, pas par une tâche cron. Contrôlez les deux :
systemctl list-timers | grep certbot
certbot renew --dry-run
Cette exécution à blanc est la seule vraie preuve que le renouvellement fonctionnera dans quatre-vingt-dix jours. Si vous utilisez le dépôt nginx.org, il existe en outre depuis nginx 1.29, avec nginx-module-acme, une variante entièrement sans certbot dans laquelle nginx demande et renouvelle les certificats lui-même.
nginx -t, reload et restart
La règle est simple et pourtant enfreinte en permanence : jamais de reload sans un nginx -t préalable. En cas d'erreur de syntaxe, nginx refuse certes de reprendre la configuration cassée, mais lors d'un restart l'ancien processus est déjà terminé et le site est hors ligne.
nginx -t
Voici exactement ce qui est attendu :
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
reload démarre de nouveaux workers avec la nouvelle configuration et laisse les anciens terminer de servir leurs connexions ouvertes. Pas une seule requête n'est perdue. Vous n'avez besoin de restart que lorsque quelque chose change dans le processus lui-même, par exemple après une mise à jour de paquet, en cas de modification de user ou lors du chargement de directives load_module.
Si le démarrage échoue, la sortie de systemd est quasiment inutile :
Job for nginx.service failed because the control process exited with error code.
See "systemctl status nginx.service" and "journalctl -xeu nginx.service" for details.
Le texte exploitable se trouve un niveau plus bas :
journalctl -xeu nginx.service --no-pager -n 30
Résoudre le conflit de port avec Apache sur le port 80
L'erreur nginx la plus connue de toutes :
nginx: [emerg] bind() to 0.0.0.0:80 failed (98: Address already in use)
Notez que nginx -t ne détecte pas cette erreur, car le test n'ouvre aucun port. Seul le démarrage échoue. Commencez par déterminer qui occupe le port au lieu de deviner :
apt install -y iproute2
ss -tlnp | grep ':80'
La sortie nomme le processus en clair, typiquement users:(("apache2",pid=612,fd=4)). Dans neuf cas sur dix, Apache est arrivé sur le système via apt install php ou via un panneau de contrôle d'hébergement. Il existe trois issues propres.
Premièrement, désactiver Apache. Si vous n'en avez pas besoin, la désactivation suffit, ainsi il ne revient pas après le prochain redémarrage :
systemctl disable --now apache2
systemctl start nginx
Deuxièmement, supprimer Apache. Attention : si libapache2-mod-php en dépend, apt purge apache2 peut emporter PHP avec lui. Vérifiez la liste qu'apt affiche avant l'exécution, et réinstallez ensuite php-fpm.
Troisièmement, faire tourner les deux en parallèle. C'est pertinent lorsque des vhosts Apache existants doivent continuer à fonctionner avec .htaccess et que nginx travaille devant eux comme reverse proxy. Pour cela, placez un Listen 127.0.0.1:8080 dans /etc/apache2/ports.conf, changez <VirtualHost *:80> en <VirtualHost *:8080> dans chaque vhost et laissez nginx transmettre les requêtes :
location / {
proxy_pass http://127.0.0.1:8080;
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;
}
Pour qu'Apache ne voie plus uniquement 127.0.0.1 dans ses logs, activez-y le module remoteip. Sans cette étape, les règles Fail2ban basées sur les logs Apache sont sans valeur, puisque chaque requête semble provenir de localhost.
Deux variantes de la même erreur passent volontiers inaperçues. Si la même entrée listen figure en double dans deux de vos propres fichiers, nginx signale également Address already in use alors qu'Apache n'est absolument pas en cause. Et avec bind() to [::]:80 failed, seul IPv6 est concerné, le plus souvent parce qu'un second bloc définit lui aussi listen [::]:80 sans ipv6only=on.
La recette finale : huit vérifications plutôt que l'intuition
Avant de considérer une installation comme terminée, passez ces points en revue. Chacun d'eux a déjà évité une panne silencieuse.
nginx -tsignale test is successful.systemctl is-enabled nginxrenvoieenabled, le service revient donc après un redémarrage.ss -tlnp | grep nginxaffiche le port 80 et, s'il est configuré, le port 443.nginx -T | grep server_nameliste chaque domaine censé fonctionner.curl -I http://127.0.0.1/renvoie un code 200 ou une redirection voulue.- Le fichier de test PHP affiche
fpm-fcgiet a été supprimé ensuite. certbot renew --dry-runs'exécute sans erreur./var/log/nginx/error.logne contient aucune nouvelle entrée après un accès de test.
Sur un serveur fraîchement installé, il reste ensuite à ajouter le pare-feu, voyez pour cela notre guide sur la configuration d'ufw. Debian 10 et Ubuntu 20.04 sont sans support depuis juin 2024 et mai 2025 respectivement et ne reçoivent plus de mises à jour de sécurité pour nginx : la montée de version n'y est pas une question de confort, elle aurait déjà dû être faite.
Ce que KernelHost apporte en plus
Sur les serveurs root KVM et les serveurs dédiés de KernelHost, vous installez Debian 13, Debian 12, Ubuntu 24.04 ou Ubuntu 22.04 directement depuis l'espace client et vous disposez ensuite d'un accès root complet, les étapes décrites plus haut fonctionnent sans la moindre modification. Les systèmes se trouvent dans le datacenter maincubes à Frankfurt am Main, certifié TÜV TIER3+, raccordé via notre propre réseau. La protection DDoS agit en amont du serveur et pas seulement dans nginx : 3,2 Tbps de filtrage Arbor en temps réel directement sur le site, et jusqu'à 17 Tbps de capacité de filtrage globale en supplément dans les offres Professional. Tout fonctionne sur une base PrePaid, donc sans durée minimale, sans préavis de résiliation et sans frais de mise en service.
Questions fréquentes
Faut-il installer nginx depuis le paquet de la distribution ou depuis le dépôt officiel nginx.org ?
Pourquoi mon bloc server dans sites-available est-il totalement ignoré alors que nginx -t réussit ?
nginx ne démarre pas et signale bind() to 0.0.0.0:80 failed (98: Address already in use). Que faire ?
Quelle version de PHP et quel socket FPM me faut-il sur ma distribution ?
Comment savoir de façon fiable que nginx tourne vraiment correctement et pas seulement que la commande est passée ?
2026 KernelHost GmbH. Tous droits réservés. Ce guide est protégé par le droit d'auteur. Sa republication sur d'autres sites web, même partielle ou sous une forme modifiée, n'est pas autorisée sans notre accord écrit. Les citations accompagnées de la source et d'un lien sont expressément les bienvenues.

