Installer Nginx avec PHP-FPM sur Linux (Ubuntu, Debian, AlmaLinux)

Tutoriels Linux › Serveurs web

Documentation / Tutoriels Linux / Serveurs web / Installer Nginx avec PHP-FPM sur Linux (Ubuntu, Debian, AlmaLinux)
Mis à jour le 08/10/2026
567 vues
Débutant
20 minutes

Prérequis

  • Un serveur sous Ubuntu, Debian, AlmaLinux, Rocky, CentOS, Fedora, Alpine ou openSUSE : voir nos VPS au Canada
  • Une connexion SSH ouverte en root : Se connecter en SSH à votre VPS
  • Pour l'étape HTTPS seulement : un nom de domaine dont l'enregistrement A pointe sur l'adresse IP du serveur
Votre serveur :

Nginx sert les pages, PHP-FPM exécute le code PHP : à eux deux, ils font tourner WordPress, Laravel ou n'importe quel site PHP. Ce guide installe les deux, relie Nginx à PHP-FPM dans un site (monsite.exemple.ca, dossier /var/www/monsite), règle PHP pour un vrai site (taille des envois, mémoire, fuseau horaire), ouvre le pare-feu et passe en HTTPS avec Certbot. Choisissez votre système ci-dessus. Copiez la commande avec le bouton Copier, collez-la dans votre terminal, et comparez avec le résultat attendu.

1Mettre à jour le système

Mettre à jour le système
apt update && apt upgrade -y
Résultat attendu
...
212 upgraded, 8 newly installed, 0 to remove and 4 not upgraded.
(les nombres dépendent de l'âge de l'image)
Mettre à jour le système
dnf upgrade -y
Résultat attendu
...
Complete!
Mettre à jour le système
dnf upgrade -y
Résultat attendu
...
Complete!
Mettre à jour le système, puis redémarrer
apk update && apk upgrade && reboot
Résultat attendu
...
OK: 158 MiB in 209 packages
(les nombres dépendent de l'image ; la connexion SSH se coupe au redémarrage)

Alpine redémarre après la mise à jour : quand elle remplace le noyau, les modules du noyau en cours disparaissent et le pare-feu de l'étape 5 ne peut plus se charger (« Couldn't determine iptables version »). Reconnectez-vous en SSH après une minute.

Mettre à jour le système
zypper -n refresh && zypper -n update
Résultat attendu
All repositories have been refreshed.
...

2Installer Nginx et PHP-FPM

Les dépôts de chaque système fournissent une version récente de PHP. Les extensions installées ici sont celles que demandent WordPress, Laravel et la plupart des applications.

Installer Nginx, PHP-FPM et les extensions courantes
apt install -y nginx php-fpm php-mysql php-curl php-gd php-mbstring php-xml php-zip php-intl
Résultat attendu
...
Created symlink /etc/systemd/system/multi-user.target.wants/php8.3-fpm.service → ...
(php8.4-fpm sur Debian 13 ; Nginx et PHP-FPM démarrent tout seuls)
Activer PHP 8.3, installer Nginx, PHP-FPM et les extensions courantes, démarrer les deux
dnf module enable -y php:8.3 && dnf install -y nginx php-fpm php-cli php-mysqlnd php-gd php-mbstring php-xml php-pecl-zip php-intl php-opcache && systemctl enable --now nginx php-fpm
Résultat attendu
...
Complete!
Created symlink /etc/systemd/system/multi-user.target.wants/nginx.service → ...
Created symlink /etc/systemd/system/multi-user.target.wants/php-fpm.service → ...
Installer Nginx, PHP-FPM et les extensions courantes, démarrer les deux
dnf install -y nginx php-fpm php-cli php-mysqlnd php-gd php-mbstring php-xml php-pecl-zip php-intl php-opcache && systemctl enable --now nginx php-fpm
Résultat attendu
...
Complete!
Created symlink '/etc/systemd/system/multi-user.target.wants/nginx.service' → ...
Created symlink '/etc/systemd/system/multi-user.target.wants/php-fpm.service' → ...
Installer Nginx, PHP-FPM, les extensions courantes et curl, démarrer les deux
apk add nginx curl php84-fpm php84-mysqli php84-pdo_mysql php84-curl php84-gd php84-mbstring php84-xml php84-dom php84-simplexml php84-xmlwriter php84-zip php84-intl php84-exif php84-opcache php84-session php84-ctype php84-openssl php84-fileinfo php84-tokenizer php84-phar php84-iconv && rc-update add nginx default && rc-update add php-fpm84 default && rc-service nginx start && rc-service php-fpm84 start
Résultat attendu
...
 * service nginx added to runlevel default
 * service php-fpm84 added to runlevel default
 * Starting nginx ... [ ok ]
 * Starting PHP FastCGI Process Manager ... [ ok ]
Installer Nginx, PHP-FPM et les extensions courantes, démarrer les deux
zypper -n install nginx php8-fpm php8-cli php8-mysql php8-curl php8-gd php8-mbstring php8-dom php8-xmlreader php8-xmlwriter php8-zip php8-intl php8-exif php8-opcache php8-openssl php8-ctype php8-tokenizer php8-fileinfo php8-iconv php8-phar && systemctl enable --now nginx php-fpm
Résultat attendu
...
Running post-transaction scripts [...done]
Created symlink '/etc/systemd/system/multi-user.target.wants/nginx.service' → ...
Created symlink '/etc/systemd/system/multi-user.target.wants/php-fpm.service' → ...
Vérifier les versions
nginx -v && php -v
Résultat attendu
nginx version: nginx/1.24.0 (Ubuntu)
PHP 8.3.6 (cli) (built: ...) (NTS)
...
(Debian 13 : nginx/1.26.3 et PHP 8.4.24)
Vérifier les versions
nginx -v && php -v
Résultat attendu
nginx version: nginx/1.20.1
PHP 8.3.33 (cli) (built: ...) (NTS gcc x86_64)
...
(le troisième chiffre de PHP varie d'un dépôt à l'autre : 8.3.19 sur CentOS Stream)
Vérifier les versions
nginx -v && php -v
Résultat attendu
nginx version: nginx/1.30.4
PHP 8.5.10 (cli) (built: ...) (NTS gcc x86_64)
...
Vérifier les versions
nginx -v && php84 -v
Résultat attendu
nginx version: nginx/1.30.4
PHP 8.4.25 (cli) (built: ...) (NTS)
...
(sur Alpine, la commande s'appelle php84, pas php)
Vérifier les versions
nginx -v && php -v
Résultat attendu
nginx version: nginx/1.27.2
PHP 8.4.24 (cli) (built: ...) (NTS)
...

3Créer le site

Le site vit dans /var/www/monsite ; remplacez monsite.exemple.ca par votre nom de domaine. La page index.php affiche la version de PHP et trois réglages : elle sert de témoin pour la suite. Dans le fichier Nginx, le bloc location ~ \.php$ envoie les fichiers .php à PHP-FPM, et le dernier bloc refuse les fichiers cachés comme .env ou .git.

Créer le dossier du site et la page témoin
mkdir -p /var/www/monsite
cat > /var/www/monsite/index.php << 'EOF'
<?php
echo 'PHP ', PHP_VERSION, ' (', php_sapi_name(), ') upload ', ini_get('upload_max_filesize'), ' memoire ', ini_get('memory_limit'), ' fuseau ', date_default_timezone_get(), "\n";
EOF
Ubuntu / DebianCréer le site Nginx (et retirer le site par défaut)
cat > /etc/nginx/sites-available/monsite.conf << 'EOF'
server {
    listen 80 default_server;
    listen [::]:80 default_server;
    server_name monsite.exemple.ca;
    root /var/www/monsite;
    index index.php index.html;

    location / {
        try_files $uri $uri/ /index.php?$query_string;
    }

    location ~ \.php$ {
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_pass unix:/run/php/php-fpm.sock;
    }

    location ~ /\. {
        deny all;
    }
}
EOF
ln -s /etc/nginx/sites-available/monsite.conf /etc/nginx/sites-enabled/
rm -f /etc/nginx/sites-enabled/default
AlmaLinux / Rocky / CentOSCréer le site Nginx
cat > /etc/nginx/conf.d/monsite.conf << 'EOF'
server {
    listen 80 default_server;
    listen [::]:80 default_server;
    server_name monsite.exemple.ca;
    root /var/www/monsite;
    index index.php index.html;

    location / {
        try_files $uri $uri/ /index.php?$query_string;
    }

    location ~ \.php$ {
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_pass unix:/run/php-fpm/www.sock;
    }

    location ~ /\. {
        deny all;
    }
}
EOF
FedoraCréer le site Nginx
cat > /etc/nginx/conf.d/monsite.conf << 'EOF'
server {
    listen 80 default_server;
    listen [::]:80 default_server;
    server_name monsite.exemple.ca;
    root /var/www/monsite;
    index index.php index.html;

    location / {
        try_files $uri $uri/ /index.php?$query_string;
    }

    location ~ \.php$ {
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_pass unix:/run/php-fpm/www.sock;
    }

    location ~ /\. {
        deny all;
    }
}
EOF
AlpineCréer le site Nginx (et retirer le site par défaut)
cat > /etc/nginx/http.d/monsite.conf << 'EOF'
server {
    listen 80 default_server;
    listen [::]:80 default_server;
    server_name monsite.exemple.ca;
    root /var/www/monsite;
    index index.php index.html;

    location / {
        try_files $uri $uri/ /index.php?$query_string;
    }

    location ~ \.php$ {
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_pass 127.0.0.1:9000;
    }

    location ~ /\. {
        deny all;
    }
}
EOF
rm -f /etc/nginx/http.d/default.conf
openSUSECréer le site Nginx
cat > /etc/nginx/vhosts.d/monsite.conf << 'EOF'
server {
    listen 80 default_server;
    listen [::]:80 default_server;
    server_name monsite.exemple.ca;
    root /var/www/monsite;
    index index.php index.html;

    location / {
        try_files $uri $uri/ /index.php?$query_string;
    }

    location ~ \.php$ {
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_pass 127.0.0.1:9000;
    }

    location ~ /\. {
        deny all;
    }
}
EOF
Vérifier la configuration et recharger Nginx
nginx -t && systemctl reload nginx
Résultat attendu
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
Vérifier la configuration et recharger Nginx
nginx -t && systemctl reload nginx
Résultat attendu
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
Vérifier la configuration et recharger Nginx
nginx -t && systemctl reload nginx
Résultat attendu
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
Vérifier la configuration et recharger Nginx
nginx -t && rc-service nginx reload
Résultat attendu
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
 * Reloading nginx configuration ... [ ok ]
Vérifier la configuration et recharger Nginx
nginx -t && systemctl reload nginx
Résultat attendu
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
Tester la page témoin
curl http://127.0.0.1/
Résultat attendu
PHP 8.3.6 (fpm-fcgi) upload 2M memoire 128M fuseau UTC
(Debian 13 : PHP 8.4.24)
Tester la page témoin
curl http://127.0.0.1/
Résultat attendu
PHP 8.3.33 (fpm-fcgi) upload 2M memoire 128M fuseau UTC
Tester la page témoin
curl http://127.0.0.1/
Résultat attendu
PHP 8.5.10 (fpm-fcgi) upload 2M memoire 128M fuseau UTC
Tester la page témoin
curl http://127.0.0.1/
Résultat attendu
PHP 8.4.25 (fpm-fcgi) upload 2M memoire 128M fuseau UTC
Tester la page témoin
curl http://127.0.0.1/
Résultat attendu
PHP 8.4.24 (fpm-fcgi) upload 2M memoire 128M fuseau UTC

Dans le navigateur, http://ADRESSE_IP/ affiche la même ligne. Les valeurs 2M, 128M et UTC sont celles de PHP par défaut : l'étape suivante les change.

4Régler PHP pour un site

Les valeurs par défaut conviennent à une page témoin, pas à un site : 2 Mo par fichier envoyé, 128 Mo de mémoire par script, fuseau UTC. Remplacez America/Toronto par votre fuseau horaire, puis redémarrez PHP-FPM pour qu'il relise sa configuration.

Ubuntu / DebianDéposer les réglages et redémarrer PHP-FPM
PHPV=$(php -r 'echo PHP_MAJOR_VERSION.".".PHP_MINOR_VERSION;')
cat > /etc/php/$PHPV/fpm/conf.d/90-monsite.ini << 'EOF'
upload_max_filesize = 64M
post_max_size = 64M
memory_limit = 256M
date.timezone = America/Toronto
EOF
systemctl restart php$PHPV-fpm
AlmaLinux / Rocky / CentOSDéposer les réglages et redémarrer PHP-FPM
cat > /etc/php.d/90-monsite.ini << 'EOF'
upload_max_filesize = 64M
post_max_size = 64M
memory_limit = 256M
date.timezone = America/Toronto
EOF
systemctl restart php-fpm
FedoraDéposer les réglages et redémarrer PHP-FPM
cat > /etc/php.d/90-monsite.ini << 'EOF'
upload_max_filesize = 64M
post_max_size = 64M
memory_limit = 256M
date.timezone = America/Toronto
EOF
systemctl restart php-fpm
AlpineDéposer les réglages et redémarrer PHP-FPM
cat > /etc/php84/conf.d/90-monsite.ini << 'EOF'
upload_max_filesize = 64M
post_max_size = 64M
memory_limit = 256M
date.timezone = America/Toronto
EOF
rc-service php-fpm84 restart
openSUSEDéposer les réglages et redémarrer PHP-FPM
cat > /etc/php8/conf.d/90-monsite.ini << 'EOF'
upload_max_filesize = 64M
post_max_size = 64M
memory_limit = 256M
date.timezone = America/Toronto
EOF
systemctl restart php-fpm
Vérifier par la page témoin
curl http://127.0.0.1/
Résultat attendu
PHP 8.3.6 (fpm-fcgi) upload 64M memoire 256M fuseau America/Toronto
(Debian 13 : PHP 8.4.24)
Vérifier par la page témoin
curl http://127.0.0.1/
Résultat attendu
PHP 8.3.33 (fpm-fcgi) upload 64M memoire 256M fuseau America/Toronto
Vérifier par la page témoin
curl http://127.0.0.1/
Résultat attendu
PHP 8.5.10 (fpm-fcgi) upload 64M memoire 256M fuseau America/Toronto
Vérifier par la page témoin
curl http://127.0.0.1/
Résultat attendu
PHP 8.4.25 (fpm-fcgi) upload 64M memoire 256M fuseau America/Toronto
Vérifier par la page témoin
curl http://127.0.0.1/
Résultat attendu
PHP 8.4.24 (fpm-fcgi) upload 64M memoire 256M fuseau America/Toronto

5Ouvrir le pare-feu

Le pare-feu laisse passer SSH, HTTP et HTTPS, et refuse le reste. Le détail (règles réservées à votre adresse, journal, suppression) est dans le tutoriel Configurer le pare-feu.

Activer le pare-feu (SSH reste autorisé) et ouvrir HTTP et HTTPS
apt install -y ufw && ufw allow 22/tcp && ufw allow 80/tcp && ufw allow 443/tcp && ufw --force enable
Résultat attendu
...
Firewall is active and enabled on system startup
Activer le pare-feu (SSH reste autorisé) et ouvrir HTTP et HTTPS
dnf install -y firewalld && systemctl enable --now firewalld && firewall-cmd --permanent --add-service=http --add-service=https && firewall-cmd --reload
Résultat attendu
...
success
success
Activer le pare-feu (SSH reste autorisé) et ouvrir HTTP et HTTPS
dnf install -y firewalld && systemctl enable --now firewalld && firewall-cmd --permanent --add-service=http --add-service=https && firewall-cmd --reload
Résultat attendu
...
success
success
Activer le pare-feu (SSH reste autorisé) et ouvrir HTTP et HTTPS
apk add ufw && ufw allow 22/tcp && ufw allow 80/tcp && ufw allow 443/tcp && ufw --force enable && rc-update add ufw default
Résultat attendu
...
Firewall is active and enabled on system startup
 * service ufw added to runlevel default
Activer le pare-feu (SSH reste autorisé) et ouvrir HTTP et HTTPS
systemctl enable --now firewalld && firewall-cmd --permanent --add-service=http --add-service=https && firewall-cmd --reload
Résultat attendu
success
success

6Passer en HTTPS avec Certbot

À faire quand votre nom de domaine pointe sur le serveur. Certbot obtient le certificat Let's Encrypt, réécrit le site Nginx pour servir en HTTPS et le renouvelle tout seul. Il demande une adresse courriel et l'accord aux conditions d'utilisation ; le détail (vérifications, renouvellement selon le système, erreurs) est dans le tutoriel Installer un certificat Let's Encrypt avec Certbot.

Installer Certbot
apt install -y certbot python3-certbot-nginx
Installer Certbot (dépôt EPEL)
dnf install -y epel-release && dnf install -y certbot python3-certbot-nginx
Installer Certbot
dnf install -y certbot python3-certbot-nginx python3-pyparsing
Installer Certbot
apk add certbot certbot-nginx
Installer Certbot
zypper -n install python313-certbot-nginx
Demander le certificat et activer HTTPS sur le site
certbot --nginx -d monsite.exemple.ca

7Dimensionner PHP-FPM

PHP-FPM garde des processus prêts à répondre ; leur nombre maximal, pm.max_children, est bas par défaut. Trop bas, les visiteurs attendent leur tour ; trop haut, la mémoire déborde. La bonne valeur se calcule : la mémoire que vous réservez à PHP, divisée par le poids d'un processus. Mesurez ce poids après quelques visites de votre application (colonne RSS, en Ko).

Poids des processus PHP-FPM
ps -eo rss,user,comm | grep php-fpm
Résultat attendu
34188 root     php-fpm8.3
16316 www-data php-fpm8.3
17980 www-data php-fpm8.3
(le premier est le maître ; avec la page témoin, chaque processus de travail pèse 16 à 18 Mo, une application en pèse davantage)
Poids des processus PHP-FPM
ps -eo rss,user,comm | grep php-fpm
Résultat attendu
36092 root     php-fpm
18720 apache   php-fpm
20732 apache   php-fpm
19496 apache   php-fpm
20744 apache   php-fpm
15432 apache   php-fpm
(le premier est le maître ; avec la page témoin, chaque processus de travail pèse 15 à 21 Mo, une application en pèse davantage)
Poids des processus PHP-FPM
ps -eo rss,user,comm | grep php-fpm
Résultat attendu
37932 root     php-fpm
14188 apache   php-fpm
16092 apache   php-fpm
14644 apache   php-fpm
14644 apache   php-fpm
16080 apache   php-fpm
(le premier est le maître ; avec la page témoin, chaque processus de travail pèse 14 à 16 Mo, une application en pèse davantage)
Poids des processus PHP-FPM
ps -eo rss,user,comm | grep php-fpm
Résultat attendu
 30m root     php-fpm84
 12m nobody   php-fpm84
 14m nobody   php-fpm84
(le premier est le maître ; avec la page témoin, chaque processus de travail pèse 12 à 14 Mo, une application en pèse davantage)
Poids des processus PHP-FPM
ps -eo rss,user,comm | grep php-fpm
Résultat attendu
44024 root     php-fpm
17088 wwwrun   php-fpm
19540 wwwrun   php-fpm
(le premier est le maître ; avec la page témoin, chaque processus de travail pèse 17 à 20 Mo, une application en pèse davantage)

La valeur se change dans le fichier du pool www, ligne pm.max_children, puis PHP-FPM redémarre. Les lignes pm.start_servers, pm.min_spare_servers et pm.max_spare_servers du même fichier doivent rester inférieures ou égales à pm.max_children.

/etc/php/8.3/fpm/pool.d/www.conf
Ubuntu 24.04 (8.4 dans le chemin sur Debian 13)systemctl restart php8.3-fpm (php8.4-fpm sur Debian 13)
/etc/php-fpm.d/www.conf
AlmaLinux, Rocky, CentOS, Fedorasystemctl restart php-fpm
/etc/php84/php-fpm.d/www.conf
Alpinerc-service php-fpm84 restart
/etc/php8/fpm/php-fpm.d/www.conf
openSUSEsystemctl restart php-fpm

Les commandes du quotidien

Vérifier puis recharger Nginx après un changement de site
nginx -t && systemctl reload nginx
Redémarrer PHP-FPM après un réglage PHP (php8.4-fpm sur Debian 13)
systemctl restart php8.3-fpm
État des deux services (php8.4-fpm sur Debian 13)
systemctl status nginx php8.3-fpm
Dernières erreurs de Nginx
tail -n 20 /var/log/nginx/error.log
Visites en direct (Ctrl+C pour sortir)
tail -f /var/log/nginx/access.log
Extensions PHP chargées
php -m
Vérifier puis recharger Nginx après un changement de site
nginx -t && systemctl reload nginx
Redémarrer PHP-FPM après un réglage PHP
systemctl restart php-fpm
État des deux services
systemctl status nginx php-fpm
Dernières erreurs de Nginx
tail -n 20 /var/log/nginx/error.log
Visites en direct (Ctrl+C pour sortir)
tail -f /var/log/nginx/access.log
Extensions PHP chargées
php -m
Vérifier puis recharger Nginx après un changement de site
nginx -t && systemctl reload nginx
Redémarrer PHP-FPM après un réglage PHP
systemctl restart php-fpm
État des deux services
systemctl status nginx php-fpm
Dernières erreurs de Nginx
tail -n 20 /var/log/nginx/error.log
Visites en direct (Ctrl+C pour sortir)
tail -f /var/log/nginx/access.log
Extensions PHP chargées
php -m
Vérifier puis recharger Nginx après un changement de site
nginx -t && rc-service nginx reload
Redémarrer PHP-FPM après un réglage PHP
rc-service php-fpm84 restart
État des deux services
rc-service nginx status && rc-service php-fpm84 status
Dernières erreurs de Nginx
tail -n 20 /var/log/nginx/error.log
Visites en direct (Ctrl+C pour sortir)
tail -f /var/log/nginx/access.log
Extensions PHP chargées
php84 -m
Vérifier puis recharger Nginx après un changement de site
nginx -t && systemctl reload nginx
Redémarrer PHP-FPM après un réglage PHP
systemctl restart php-fpm
État des deux services
systemctl status nginx php-fpm
Dernières erreurs de Nginx
tail -n 20 /var/log/nginx/error.log
Visites en direct (Ctrl+C pour sortir)
tail -f /var/log/nginx/access.log
Extensions PHP chargées
php -m
Nginx et PHP-FPM en service

Nginx sert votre site, PHP-FPM exécute le code, le pare-feu est ouvert et HTTPS tient en une commande. Pour aller plus loin : Installer MySQL ou MariaDB, puis WordPress ou votre application dans /var/www/monsite.

Erreurs fréquentes

💬 Écrivez-nous sur Messenger !