Serveur dédié : installer NginX avec support HTTP2 et certificat SSL, PHP, MariaDB sous Debian

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.

Serveur dédié : installer NginX avec support HTTP2 et certificat SSL, PHP, MariaDB sous Debian photo

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.listCode 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 mainCode 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-devCode 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 alreadyCode 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.comCode 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-backportsCode 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 = 4096Code 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 certsCode 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

  1. Serveur dédié : installation d’Apache, PHP, MySQL et Webmin
  2. Serveur dédié : créer la base de données MySQL et importer WordPress
  3. Serveur dédié : créer et activer un Virtual Host sous Apache
  4. Serveur dédié : changer les DNS du nom de domaine et le faire pointer vers le serveur
  5. Serveur dédié : sécurisation des services avec iptables et fail2ban
  6. Serveur dédié : sécurisation de la couche TCP/IP
  7. 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
  8. Serveur dédié : sécuriser Apache 2 avec ModSecurity
  9. Serveur dédié : CHMOD récursif sur des fichiers ou répertoires en ligne de commande
  10. Serveur dédié : installer APC comme système de cache et configurer Varnish comme reverse-proxy pour Apache pour améliorer les performances
  11. Serveur dédié : afficher la véritable IP derrière un reverse-proxy comme Varnish
  12. Serveur dédié : intégrer SSH à WordPress pour mettre à jour le core, les plugins et les thèmes
  13. Serveur dédié : installer la dernière version d’APC par SVN
  14. Serveur dédié : analyse des performances du serveur
  15. Serveur dédié : mettre à jour le noyau Debian de la Kimsufi
  16. Serveur dédié : sauvegarde automatique des fichiers avec Backup Manager sur le serveur de sauvegarde OVH
  17. Serveur dédié : configurer la limite mémoire pour PHP et Suhosin
  18. Bash : supprimer tous les fichiers et sous-répertoires d’un répertoire
  19. Serveur dédié : impossible de se connecter à un port distant
  20. Rsync: rapatrier les fichiers du serveur à la maison
  21. Bash : réparer les tables MySQL en cas de crash
  22. Serveur dédié : création d’une seedbox avec Transmission
  23. Serveur dédié : des paquets LAMP à jour sous Debian
  24. Serveur dédié : mise à jour vers Debian 7 Wheezy
  25. Serveur dédié : activer X11 forwarding pour SSH
  26. Serveur dédié : optimiser toutes les images JPG et PNG avec OptiPNG et JpegOptim
  27. Postfix : résoudre l’erreur “fatal: www-data(33): message file too big”
  28. Serveur dédié : mise en place de l’IPv6
  29. WordPress : accorder les bonnes permissions aux fichiers et dossiers avec chown et chmod
  30. WordPress : héberger les images sur un sous-domaine
  31. Serveur dédié : ajouter l’authentification SPF, Sender-ID et DKIM à Postfix et Bind9 avec opendkim
  32. Apache : lorsque le domaine seul (sans WWW) renvoie une erreur 403
  33. Serveur dédié : sécuriser Apache avec HTTPS (HTTP avec la couche TLS/SSL) en Perfect Forward Secrecy
  34. Serveur dédié : passer WordPress en HTTPS (TLS/SSL)
  35. Serveur dédié : configurer Webmin en TLS avec un certificat SSL
  36. Serveur dédié : configurer Transmission pour accéder au WebUI via TLS-SSL
  37. Serveur dédié : installer et configurer Varnish 4
  38. Serveur dédié : passage au mod FastCGI et PHP-FPM avec Apache MPM Worker
  39. Récupérer un serveur Kimsufi après un plantage de kernel avec le mode rescue OVH
  40. Serveur dédié : configurer Postfix et Courier pour utiliser TLS-SSL en Perfect Forward Secrecy
  41. Serveur dédié : retirer Varnish, devenu inutile avec HTTPS
  42. Serveur dédié : installer la dernière version d’OpenSSL sous Debian
  43. Serveur dédié : activer l’IP canonique du serveur sous Apache
  44. Serveur dédié : mise à jour vers PHP 5.6
  45. MySQL : convertir les tables MyISAM au format InnoDB
  46. Serveur dédié : optimiser toutes les images GIF avec GIFsicle
  47. Serveur dédié : migration de MySQL vers MariaDB
  48. BASH : lister, bloquer et débloquer des adresses IP avec iptables
  49. Serveur dédié : produire une meilleure réserve d’entropie avec haveged
  50. Serveur dédié : mettre en place DNSSEC pour sécuriser les DNS du domaine
  51. Serveur dédié : mise en place du protocole DANE
  52. 8 règles d’or pour bien déployer DNSSEC et DANE
  53. Serveur dédié : installer PHP7 FPM avec FastCGI sous Debian
  54. Serveur dédié : optimiser la couche TCP
  55. Fail2Ban: protéger Postfix contre les attaques DoS de types AUTH, UNKNOWN et EHLO
  56. Serveur dédié : mettre à jour Apache pour HTTP/2
  57. Serveur dédié : ajouter le domaine à la liste HSTS preload
  58. Serveur dédié : ajouter l’authentification DMARC à Postfix et BIND
  59. Serveur dédié : à la recherche de l’inode perdue ou comment résoudre le problème “no space left on device”
  60. 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.

Parlons de votre projet dès aujourd'hui »

Articles conseillés :

Matt

Matt Biscay est développeur WordPress et WooCommerce certifié chez Codeable, ainsi que sysadmin qualifié et enseignant-chercheur. Passionné par le code performant et les solutions sécurisées, je m'efforce d'offrir une expérience utilisateur exceptionnelle sur chaque projet.

Vous avez aimé cet article ? Vous avez un projet en tête et vous pensez que je pourrais vous aider à le concrétiser ? N'hésitez pas à me contacter, je serais ravi de discuter avec vous de votre projet !

1 pensée sur “Serveur dédié : installer NginX avec support HTTP2 et certificat SSL, PHP, MariaDB sous Debian”

Opinions