Aujourd’hui, nous sautons le pas et passons du serveur Apache au serveur NginX (à prononcer “engine X”) pour booster les performances générales du site.
Cela fait quelques serveurs que je monte pour d’autres en utilisant nginx et force est de constater que c’est beaucoup plus réactif qu’Apache et cela prend moins de temps à configurer pour optimiser les réglages.
Je pars du principe que c’est une nouvelle installation mais si vous aviez déjà votre site qui tournait sous Apache, certaines étapes seront juste optionnelles.
Ce tutoriel vise un serveur Debian mais est adaptable sans problème à ses dérivés comme Ubuntu ou Mint.
Etape 1 : NginX
Nous allons installer la dernière version du serveur nginx, avec le support pour HTTP2, depuis les dépôts Sury :
nano /etc/apt/sources.list
Code language: PHP (php)
et nous ajoutons :
# SURY, post-Dotdeb
deb https://packages.sury.org/php/ stretch main
deb https://packages.sury.org/nginx-mainline/ stretch main
deb https://packages.sury.org/mariadb/ stretch main
Code language: PHP (php)
On rafraîchit les dépôts :
apt update
et on installe nginx et openssl :
apt install nginx openssl libssl1.0.2 libssl1.0.1 libssl-dev
Code language: CSS (css)
Etape 2 : MariaDB
Si vous ne l’avez pas déjà – cela remplace MySQL sans que vous n’ayez rien à changer au niveau du code ou de la configuration du serveur :
apt install mariadb-server
Etape 3 : PHP
Je vous conseille de suivre mon dernier guide pour installer PHP 7.1.
Etape 4 : configurer NginX
Nous allons d’abord configurer toutes les options qui nous sont primordiales : compression des fichiers statiques, implémentation SSL, types mime… afin de gagner du temps (et éviter les erreurs) dans l’étape suivante.
1. Nous voulons un site rapide donc nous allons compresser tout ce qui peut l’être. On crée un nouveau fichier :
nano /etc/nginx/snippets/gzip-config.conf
et on y met :
# MATT : add more mime-types to compress
types {
application/x-font-ttf ttf;
font/opentype ott;
}
# MATT : gzip all the things!
gzip on;
gzip_disable "msie6";
gzip_vary on;
gzip_proxied any;
gzip_comp_level 6;
gzip_min_length 256;
gzip_buffers 16 8k;
gzip_http_version 1.1;
#gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;
# Compress all output labeled with one of the following MIME-types.
gzip_types
application/atom+xml
application/javascript
application/json
application/ld+json
application/manifest+json
application/rss+xml
application/vnd.geo+json
application/vnd.ms-fontobject
application/x-font-ttf
application/x-web-app-manifest+json
application/xhtml+xml
application/xml
font/opentype
image/bmp
image/svg+xml
image/x-icon
text/cache-manifest
text/css
text/plain
text/vcard
text/vnd.rim.location.xloc
text/vtt
text/x-component
text/x-cross-domain-policy;
# text/html is always compressed by gzip module
# don't compress woff/woff2 as they're compressed already
Code language: PHP (php)
J’ai ajouté deux types mime qui ne sont pas dans la configuration de base d’NginX et étendu la liste des types de fichiers à compresser. Certains types le sont déjà donc c’est inutile de gaspiller des ressources en essayant de les compresser.
2. Nous allons booster la sécurité de nos certificats. Tout d’abord, nous allons créer un fichier Diffie-Hellman de 4096 bits pour chiffrer les échanges de clés.
mkdir -p /etc/nginx/ssl
openssl dhparam -out /etc/nginx/ssl/dhparam4096.pem 4096
Là, vous pouvez aller prendre un café parce que cela va prendre un bon bout de temps suivant votre processeur. Comptez 15-20 minutes.
3. Nous mettons toute notre configuration SSL dans un nouveau fichier :
nano /etc/nginx/snippets/ssl-config.conf
et on y ajoute:
# MATT : badass TLS config
ssl_protocols TLSv1.1 TLSv1.2; # Dropping SSL and TLSv1
ssl_prefer_server_ciphers on;
ssl_ciphers "ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!3DES:!MD5:!PSK";
ssl_ecdh_curve secp384r1;
ssl_dhparam /etc/nginx/ssl/dhparam4096.pem;
ssl_session_cache shared:SSL:10m;
ssl_session_tickets off;
# Cache credentials
ssl_session_timeout 1h;
# Stapling
ssl_stapling on;
ssl_stapling_verify on;
resolver 8.8.8.8 8.8.4.4 valid=300s;
resolver_timeout 5s;
Code language: PHP (php)
En créant ces deux nouveaux fichiers (ainsi que le fichier Diffie-Hellman), on s’assure de pouvoir réutiliser certaines déclarations pour un autre site qui pourrait être installé sur le serveur. Mine de rien, cela peut vous faire gagner pas mal de temps et on gagne en lisibilité.
Etape 5 : nginx.conf
C’est maintenant que l’on gagne du temps – on édite le fichier nginx.conf :
nano /etc/nginx/nginx.conf
et on y met :
user www-data;
worker_processes auto;
pid /run/nginx.pid;
include /etc/nginx/modules-enabled/*.conf;
events {
worker_connections 768;
# multi_accept on;
}
http {
##
# Basic Settings
##
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
types_hash_max_size 2048;
server_tokens off;
# useful if several server blocks are used on the server!
server_names_hash_bucket_size 64;
# server_name_in_redirect off;
include /etc/nginx/mime.types;
default_type application/octet-stream;
# Update charset_types to match updated mime.types.
# text/html is always included by charset module.
charset_types text/css text/plain text/vnd.wap.wml application/javascript application/json application/rss+xml application/xml;
# Include $http_x_forwarded_for within default format used in log files
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
##
# SSL Settings
##
## MATT : ssl-config.conf
include /etc/nginx/snippets/ssl-config.conf;
##
##
# Logging Settings
##
access_log /var/log/nginx/access.log;
error_log /var/log/nginx/error.log;
##
# Gzip Settings
##
## MATT : gzip-config.conf
include /etc/nginx/snippets/gzip-config.conf;
##
##
# nginx-naxsi config
##
# Uncomment it if you installed nginx-naxsi
##
#include /etc/nginx/naxsi_core.rules;
##
# Virtual Host Configs
##
include /etc/nginx/conf.d/*.conf;
include /etc/nginx/sites-enabled/*;
}
Code language: PHP (php)
J’ai modifié le bloc http en ajoutant la configuration SSL et Gzip. J’ai aussi retiré la configuration email qui était désactivée par défaut par souci de lisibilité pour ce tutoriel.
Etape 6 : ajout d’un server block sous nginx
Nous avons donc nginx, mariaDB et PHP installés sur le serveur. Il nous faut maintenant définir un “server block” sous nginx, l’équivalent du VirtualHost sous Apache, qui va contenir toutes les définitions utiles pour servir notre site.
1. Le “server block” par défaut s’appelle… default. Nous allons le copier vers le fichier de configuration de notre domaine, example :
cp /etc/nginx/sites-available/default /etc/nginx/sites-available/example.com
Code language: JavaScript (javascript)
2. On édite notre fichier :
nano /etc/nginx/sites-available/example.com
et on y met :
# NginX customized server block for performance
# Author : Matt
# Author URL : https://www.skyminds.net
# Expires map
map $sent_http_content_type $expires {
default off;
text/html epoch;
text/css max;
application/javascript max;
~image/ max;
}
# Cache directives : the keys_zone is important, change it to reflect your domain
fastcgi_cache_path /var/nginx-cache levels=1:2 keys_zone=skyminds:100m inactive=60m max_size=256m;
fastcgi_cache_key "$scheme$request_method$host$request_uri";
fastcgi_cache_use_stale error timeout invalid_header http_500;
fastcgi_ignore_headers Cache-Control Expires Set-Cookie;
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name example.com www.example.com;
root /home/example/public_html;
index index.php index.html;
#ssl_certificate /etc/nginx/ssl/example.com-crt-ca.pem;
#ssl_certificate_key /etc/nginx/ssl/example.com.key;
expires $expires;
location / {
include snippets/cors_support;
# include the "?$args" part so non-default permalinks doesn't break when using query string
try_files $uri $uri/ /index.php?$args;
}
location ~ \.php$ {
fastcgi_cache_bypass $skip_cache;
fastcgi_no_cache $skip_cache;
fastcgi_cache skyminds;
fastcgi_cache_valid 60m;
fastcgi_pass unix:/run/php/php7.1-fpm.sock;
include snippets/fastcgi-php.conf;
include fastcgi_params;
}
location ~ /purge(/.*) {
fastcgi_cache_purge skyminds "$scheme$request_method$host$1";
}
location ~ /\.ht {
deny all;
}
location = /favicon.ico { log_not_found off; access_log off; }
location = /robots.txt { log_not_found off; access_log off; allow all; }
## All static files will be served directly.
location ~* ^.+\.(?:css|cur|js|jpe?g|gif|htc|ico|png|otf|ttf|eot|woff|woff2|svg)$ {
log_not_found off;
access_log off;
expires max;
add_header Cache-Control "public, no-transform";
## No need to bleed constant updates.
## Send the all shebang in one fell swoop.
tcp_nodelay off;
## Set the OS file cache.
open_file_cache max=3000 inactive=120s;
open_file_cache_valid 45s;
open_file_cache_min_uses 2;
open_file_cache_errors off;
add_header 'Access-Control-Allow-Origin' '*';
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
add_header 'Access-Control-Allow-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type';
}
}
# Redirect all HTTP requests to HTTPS
server {
listen 80;
listen [::]:80;
server_name example.com www.example.com;
root /home/example/public_html;
#return 301 https://$server_name$request_uri;
}
Code language: PHP (php)
Les choses sérieuses commencent ici. Voici ce que sous-tend ma configuration :
1. On crée un cache de 100MB dans /var/nginx-cache, qui fera 256MB maximum.
2. On sert tout en HTTPS, via HTTP/2
3. On sert tout ce qui est PHP avec PHP7.1
4. Tous les fichiers statiques sont servis directement.
On donne les bons droits sur les répertoires du site :
chown -R www-data:www-data /home/example/
find /home/example/ -type d -exec chmod 755 {} \;
On active le site avec un lien symbolique:
ln -s /etc/nginx/sites-available/example.com /etc/nginx/sites-enabled/
On teste la configuration du site:
nginx -t
et on relance le serveur si tout va bien:
service nginx restart
Etape 7 : installation de Let’s Encrypt
Sous Debian, pour installer Let’s Encrypt, il faut installer le paquet certbot
depuis le dépôt backports :
apt-get install certbot -t jessie-backports
Code language: JavaScript (javascript)
Histoire d’avoir une clé correcte, on crée un fichier de configuration :
nano /etc/letsencrypt/cli.ini
et on y met :
# Use a 4096 bit RSA key instead of 2048
rsa-key-size = 4096
Code language: PHP (php)
Vous devez avoir à portée de main :
- le chemin local du site
- le nom de domaine et les sous-domaines couverts par le certificat
Ensuite, il sufit de lancer cette commande :
certbot certonly --webroot -w /home/example/public_html -d example.com -d www.example.com
Résultat :
Saving debug log to /var/log/letsencrypt/letsencrypt.log
Starting new HTTPS connection (1): acme-v01.api.letsencrypt.org
Obtaining a new certificate
Performing the following challenges:
http-01 challenge for example.com
http-01 challenge for www.example.com
Using the webroot path /home/example/public_html for all unmatched domains.
Waiting for verification...
Cleaning up challenges
Generating key (4096 bits): /etc/letsencrypt/keys/0000_key-certbot.pem
Creating CSR: /etc/letsencrypt/csr/0000_csr-certbot.pem
IMPORTANT NOTES:
- Congratulations! Your certificate and chain have been saved at
/etc/letsencrypt/live/example.com/fullchain.pem. Your cert will
expire on 2017-08-03. To obtain a new or tweaked version of this
certificate in the future, simply run certbot again. To
non-interactively renew *all* of your certificates, run "certbot
renew"
Code language: PHP (php)
Comme le certificat expire tous les 90 jours, il suffit de mettre en place un crontab :
crontab -e
avec :
01 6 * * 1 certbot renew --pre-hook "service nginx stop" --post-hook "service nginx start" #renew certs
Code language: PHP (php)
On lance le script chaque lundi à 6:01 du matin. Je vous conseille de changer l’heure pour ne pas que tout le monde renouvelle ses certificats au même moment et surcharge les serveurs de Let’s Encrypt.
Etape 8 : configurer le server block avec le certificat SSL
Il suffit d’ajouter les lignes suivantes dans votre server block :
server{
...
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
...
}
et pour rediriger le trafic HTTP vers HTTPS :
# Redirect all HTTP requests to HTTPS
server {
listen 80;
listen [::]:80;
server_name example.com www.example.com;
root /home/example/public_html;
return 301 https://$server_name$request_uri;
}
Code language: PHP (php)
Redémarrez Nginx pour valider les changements :
service nginx restart
Voilà, je pense n’avoir rien oublié. Si vous pouvez lire cet article, c’est que cela fonctionne toujours ;).
Synopsis » Monter un serveur dédié de A à Z
- Serveur dédié : installation d’Apache, PHP, MySQL et Webmin
- Serveur dédié : créer la base de données MySQL et importer WordPress
- Serveur dédié : créer et activer un Virtual Host sous Apache
- Serveur dédié : changer les DNS du nom de domaine et le faire pointer vers le serveur
- Serveur dédié : sécurisation des services avec iptables et fail2ban
- Serveur dédié : sécurisation de la couche TCP/IP
- Serveur dédié : création d’un serveur mail Postfix (sécurisé avec Saslauthd et certificat SSL) et Courier (accès POP et IMAP) utilisant une base MySQL d’utilisateurs/domaines virtuels
- Serveur dédié : sécuriser Apache 2 avec ModSecurity
- Serveur dédié : CHMOD récursif sur des fichiers ou répertoires en ligne de commande
- Serveur dédié : installer APC comme système de cache et configurer Varnish comme reverse-proxy pour Apache pour améliorer les performances
- Serveur dédié : afficher la véritable IP derrière un reverse-proxy comme Varnish
- Serveur dédié : intégrer SSH à WordPress pour mettre à jour le core, les plugins et les thèmes
- Serveur dédié : installer la dernière version d’APC par SVN
- Serveur dédié : analyse des performances du serveur
- Serveur dédié : mettre à jour le noyau Debian de la Kimsufi
- Serveur dédié : sauvegarde automatique des fichiers avec Backup Manager sur le serveur de sauvegarde OVH
- Serveur dédié : configurer la limite mémoire pour PHP et Suhosin
- Bash : supprimer tous les fichiers et sous-répertoires d’un répertoire
- Serveur dédié : impossible de se connecter à un port distant
- Rsync: rapatrier les fichiers du serveur à la maison
- Bash : réparer les tables MySQL en cas de crash
- Serveur dédié : création d’une seedbox avec Transmission
- Serveur dédié : des paquets LAMP à jour sous Debian
- Serveur dédié : mise à jour vers Debian 7 Wheezy
- Serveur dédié : activer X11 forwarding pour SSH
- Serveur dédié : optimiser toutes les images JPG et PNG avec OptiPNG et JpegOptim
- Postfix : résoudre l’erreur “fatal: www-data(33): message file too big”
- Serveur dédié : mise en place de l’IPv6
- WordPress : accorder les bonnes permissions aux fichiers et dossiers avec chown et chmod
- WordPress : héberger les images sur un sous-domaine
- Serveur dédié : ajouter l’authentification SPF, Sender-ID et DKIM à Postfix et Bind9 avec opendkim
- Apache : lorsque le domaine seul (sans WWW) renvoie une erreur 403
- Serveur dédié : sécuriser Apache avec HTTPS (HTTP avec la couche TLS/SSL) en Perfect Forward Secrecy
- Serveur dédié : passer WordPress en HTTPS (TLS/SSL)
- Serveur dédié : configurer Webmin en TLS avec un certificat SSL
- Serveur dédié : configurer Transmission pour accéder au WebUI via TLS-SSL
- Serveur dédié : installer et configurer Varnish 4
- Serveur dédié : passage au mod FastCGI et PHP-FPM avec Apache MPM Worker
- Récupérer un serveur Kimsufi après un plantage de kernel avec le mode rescue OVH
- Serveur dédié : configurer Postfix et Courier pour utiliser TLS-SSL en Perfect Forward Secrecy
- Serveur dédié : retirer Varnish, devenu inutile avec HTTPS
- Serveur dédié : installer la dernière version d’OpenSSL sous Debian
- Serveur dédié : activer l’IP canonique du serveur sous Apache
- Serveur dédié : mise à jour vers PHP 5.6
- MySQL : convertir les tables MyISAM au format InnoDB
- Serveur dédié : optimiser toutes les images GIF avec GIFsicle
- Serveur dédié : migration de MySQL vers MariaDB
- BASH : lister, bloquer et débloquer des adresses IP avec iptables
- Serveur dédié : produire une meilleure réserve d’entropie avec haveged
- Serveur dédié : mettre en place DNSSEC pour sécuriser les DNS du domaine
- Serveur dédié : mise en place du protocole DANE
- 8 règles d’or pour bien déployer DNSSEC et DANE
- Serveur dédié : installer PHP7 FPM avec FastCGI sous Debian
- Serveur dédié : optimiser la couche TCP
- Fail2Ban: protéger Postfix contre les attaques DoS de types AUTH, UNKNOWN et EHLO
- Serveur dédié : mettre à jour Apache pour HTTP/2
- Serveur dédié : ajouter le domaine à la liste HSTS preload
- Serveur dédié : ajouter l’authentification DMARC à Postfix et BIND
- Serveur dédié : à la recherche de l’inode perdue ou comment résoudre le problème “no space left on device”
- Serveur dédié : installer NginX avec support HTTP2 et certificat SSL, PHP, MariaDB sous Debian
Vous avez un projet WordPress ou WooCommerce en tête? Transformez votre vision en réalité avec mon expertise reconnue.
Mise à jour des dépôts : passage de dotdeb à sury pour bénéficier des dernières versions.