Accelérer votre serveur web avec nginx, php7, mysql et ssl

Le nombre de connexion augmentant sur mon petit site, j’ai décidé d’upgrader mon serveur web que ce soit d’un point de vue matériel que logiciel. depuis toujours sur un serveur Apache, je suis passé sur un serveur Nginx, vu la sortie récente de PHP 7 et de son amélioration de sa vélocité, j’en ai profité.Depuis que j’ai commencé ce site, j’ai toujours été sur un serveur web Apache avec PHP 5 le tout monté sur un Raspberry pi 2. Mon but initial était de me faire un pense-bête des outils que j’utilise régulièrement. Je ne pensais pas avoir un grand nombre de connexion journalière (ce n’est toujours pas le cas) mais au bout de moins d’un an d’existence, j’arrive à un nombre de connexions mensuelles supérieures à 1000.

Le site est généré avec WordPress pour sa facilité de mise en place malheureusement, le peu de plugins installés dessus, les caractéristiques du Raspberry pi 2, PHP 5 et un hébergement personnel font que le site peut avoir quelques latences. N’étant pas fataliste, j’ai décidé de pallier à ces problèmes.

Choix du Raspberry

Dans un premier temps, j’ai utilisé un Raspberry Pi 2 (que vous pourrez trouver ici) que je possédais déjà, j’ai décidé de passer sur un Raspberry Pi 3 (lien vers la framboise) avec une fréquence cpu plus importante et plus de mémoire vive.

La raison qui m’a fait rester sur un Raspberry est principalement le coût (une quarantaine d’euros), une communauté très active et la possibilité de mettre un système Debian. Une autre raison est qu’il est facile de passer d’une installation de Raspbian sur Raspberry Pi 2 à Raspberry Pi 3. Il suffit de déplacer la carte SD.

Choix du serveur web

Initialement, j’avais choisis un serveur web Apache. Une grande communauté et un serveur majoritairement installé m’ont guidé vers ce choix. Ces avantages sont :

  • Riche en fonctionnalités
  • Écriture simple (fichier de config au format ASCII)
  • Efficacité

Ces inconvénients :

  • Beaucoup d’écriture dans les logs
  • Peut rapidement devenir lourd en cas de multi-requêtes
  • Lourd à l’éxecution

Du coup, en cherchant un peu, Nginx me semble pas trop mauvais notamment sur les pages statiques, mais il est plus rapide en exécution et plus léger.

Passage à PHP 7

PHP 5 est en fonctionnement depuis pas mal d’année, la version 6 n’a jamais abouti et la version 7 est apparu il y a peu (par rapport à l’écriture de l’article). Cependant, à l’heure où j’écris ces lignes, PHP 7 n’est pas encore disponible dans les dépôts officiels de Raspbian.

PHP 7 est beaucoup plus rapide que l’ancienne version (notamment sur WordPress).

Base de donnée MYSQL

Je n’ai pas voulu changer ma base de donnée, je suis resté sur Mysql, il existe cependant d’autres GSDB qui feront l’affaire (notamment MariaDB). Je reste sur Mysql afin de ne pas avoir à tout modifier d’un coup dans ma manière de faire (petit joueur !!!).

Certification SSL par Let’s Encrypt

Depuis 2017, il apparaitrait que pour une meilleur indexation, la présence d’un certificat SSL (donnant le protocole HTTPS à votre site) permet d’améliorer le classement. Il existe plusieurs solutions pour l’obtention d’un certificat reconnu (voir les conseils pour bien choisir sa certification). Utilisant, sur Apache2, Let’s Encrypt, je reste sur ce même fournisseur de certificat car celui-ci est facile à mettre en place sur un serveur internet.

Installation et configuration

Après ces petites explications, commençons notre installation. Pour ce tuto, je suis parti d’une installation vierge.

Création de la carte sd et son système d’exploitation

Pour le choix de la carte sd, préférez une carte de classe 10 de bonne qualité, elle supportera le système d’exploitation et devra donc être rapide en écriture et en lecture, la capacité sera en fonction de vos besoin, je conseillerai au moins 32G => exemple.

Rendez-vous sur la page de téléchargement de Raspbian => site officiel, j’ai choisi Raspbian lite, je vais travailler en ligne de commande.

Pour Windows

Télécharger l’application win32DiskImager sur le site officiel ou sur un autre site et installer le. Pour l’installation, vous pouvez suivre un précédent article.

Pour un système Linux (debian)

Installer votre carte sd dans un lecteur de carte, pour trouver votre carte sd, dans un terminal saisir :

sudo ls -ltr /dev/*

Votre carte sd doit se trouver en bas et commencer par mm ou sd.

Installer le paquet fdisk : sudo apt-get install -y fdisk

Nous allons écrire l’image sur la carte sd, dans un terminal :

sudo dd bs=1M if=chemin_vers_le_img_de_raspbian of=/dev/votre_carte

Une fois la copie réalisé (cela peu prendre du temps), mettez votre carte dans le Raspberry, branchez un écran et un clavier  (indispensables pour la configuration).

Configuration de Raspbian

Pour l’identification, par défaut le login est pi et le mot de passe est raspberry (en minuscule). Ensuite taper dans la console sudo raspi-config , rendez-vous à cette page pour la configuration de base. Profitez pour récuperer l’adresse ip utilisée : sudo ifconfig  et prenez l’adressse IP correspondant à votre connexion, eth0 en filaire ou wlan0 en wifi.

Après avoir suivi ce petit tutoriel, vous devriez être en mesure de vous connecter en ssh sinon visiter ce lien.

Modification du hostname du Raspberry

Nous allons modifier le nom du Raspberry, il s’agit du nom qui s’affiche sur le réseau, on va modifier le nom simplement dans le fichier /etc/hostname.

Création d’un nouvel utilisateur et suppression de l’utilisateur pi

L’identifiant et le mot de passe par défaut étant connu, nous allons commencer par créer un nouvel utilisateur et son dossier et supprimer pi.

Commençons par créer le nouvel utilisateur :

sudo useradd -m nom_utilisateur -G sudo

Puis son mot de passe :

sudo passwd nom_utilisateur

Donner les droits super-utilisateur au nouvel utilisateur, saisir et valider  sudo visudo  et ajouter :

nouvel_utilisateur ALL=(ALL) NOPASSWD: ALL

Puis supprimer pi :

sudo deluser -remove-home pi

Changement du port ssh

Le port 22 étant le port par défaut, il peut se faire attaquer automatiquement, nous allons donc le remplacer par un port supérieur à 1024 et inférieur à 65535, pour ce faire, aller dans le fichier (pour l’édition j’utilise nano) : sudo nano /etc/ssh/sshd_config  et remplacer le port 22 par celui que vous avez choisi et redémarrer votre raspberry sudo reboot .

Installation du serveur ftp

Il est toujours utile d’avoir accès à son Raspberry en ftp, suivez ce tutoriel.

Installation de mysql

Nous allons commencer par instaler le paquet pour la base de donnée Mysql, saisir sudo apt-get install mysql-server , un mot de passe root vous sera demandé.

Suppression du compte root de mysql

Pour assurer un minimum de sécurité, nous allons créer un utilisateur avec tous les droits pour toutes les tables et supprimer le compte root, dans la console :

mysql -u root -p

Le mot de passe vous sera demandé. Dans la console de Mysql, saisir :

GRANT ALL PRIVILEGES ON *.* TO nom_utilisateur@"%" IDENTIFIED BY 'un_mot_de_passe' WITH GRANT OPTION;
FLUSH PRIVILEGES;

Puis on supprime l’utilisateur root , commencer par quitter mysql en tapant et validant quit, puis reconnectez-vous avec votre nouvel utilisateur :

mysql -u nouvel_utilisateur -p

Puis dans la console mysql :

DELETE FROM mysql.user WHERE user='root';

Installation PHP7 et Nginx

Les paquets ne sont toujours pas disponibles sur les dépôts officiels mais il existe des dépôts fonctionnel, en cherchant pas mal sur internet, je suis tombé sur un script. Le script se trouve sur un git : git de LewisCowles1986.

Voici le script bash :

#!/bin/bash

if [ "$EUID" -ne 0 ]
	then echo "Must be root"
	exit
fi

echo "deb http://mirrordirector.raspbian.org/raspbian/ stretch main contrib non-free rpi" > /etc/apt/sources.list.d/stretch.list
echo "APT::Default-Release \"jessie\";" > /etc/apt/apt.conf.d/99-default-release

apt-get update -y
apt-get upgrade -y
apt-get dist-upgrade -y

apt-get install -y rpi-update

apt-get install -t stretch -y php7.0 php7.0-curl php7.0-gd php7.0-fpm php7.0-cli php7.0-opcache php7.0-mbstring php7.0-xml php7.0-zip
apt-get install -t stretch -y nginx-full

update-rc.d nginx defaults
update-rc.d php7.0-fpm defaults

cat > /etc/nginx/sites-enabled/default << "EOF"
# Default server configuration
server {
        listen 80 default_server;
        listen [::]:80 default_server;

        root /var/www/public;

        index index.html index.htm index.php default.html;

        server_name _;

        location / {
                # First attempt to serve request as file, then
                # as directory, then fall back to displaying a 404.
                try_files $uri $uri/ =404;
        }

        # pass the PHP scripts to FastCGI server
        location ~ \.php$ {
                include snippets/fastcgi-php.conf;
                fastcgi_pass unix:/run/php/php7.0-fpm.sock;
        }

        # deny access to .htaccess files, should an Apache document root conflict with nginx
        location ~ /\.ht {
                deny all;
        }
}

Il faut l’exécuter en sudo.

Pour communiquer avec mysql, il faut installer le paquet php-mysql en faisant sudo apt-get install php-mysql .

Certificat SSL avec Let’s Encrypt

Maintenant en ayant exécuter se script vous vous retrouvez avec un serveur internet Nginx, PHP7, mysql. Après avoir créer votre site internet et après l’avoir mis en ligne (avec un nom de domaine), nous allons mettre en place le certificat SSL, je e suis basé sur cette page.

Installation de Let’s Encrypt

Commençons par installer l’outil, faite un sudo apt-get install git , puis saisir :

sudo git clone https://github.com/letsencrypt/letsencrypt /opt/letsencrypt --depth=1

Plus tard pour une mise à jour, il suffira de se placer dans /opt/letsencrypt et saisir sudo git pull

Ensuite dans la configuration de votre site Nginx (/etc/nginx/sites-available/ma_conf), insérer :

server {
        . . .

        location ~ /.well-known {
                allow all;
        }

        . . .
}

Relancer le serveur : sudo service nginx restart .

Saisir :

sudo certbot-auto certonly -a webroot --webroot-path=/var/www/html -d example.com -d www.example.com

Webroot-path correspond à la racine de votre site. Si c’est la première fois que vous utilisez Let’s Encrypt, il vous sera demandé quelques informations, à la fin vous obtiendriez un message pour dire que tout est bon :

IMPORTANT NOTES:
 - If you lose your account credentials, you can recover through
   e-mails sent to sammy@digitalocean.com
 - Congratulations! Your certificate and chain have been saved at
   /etc/letsencrypt/live/example.com/fullchain.pem. Your
   cert will expire on 2016-03-15. To obtain a new version of the
   certificate in the future, simply run Let's Encrypt again.
 - Your account credentials have been saved in your Let's Encrypt
   configuration directory at /etc/letsencrypt. You should make a
   secure backup of this folder now. This configuration directory will
   also contain certificates and private keys obtained by Let's
   Encrypt so making regular backups of this folder is ideal.
 - If like Let's Encrypt, please consider supporting our work by:

   Donating to ISRG / Let's Encrypt:   https://letsencrypt.org/donate
   Donating to EFF:                    https://eff.org/donate-le

Vous pouvez vérifiez la création des fichiers en faisant : sudo ls -l /etc/letsencrypt/live/your_domain_name

Obtention d’un Diffie-Hellman

Pour augmenter la sécurité :

sudo openssl dhparam -out /etc/ssl/certs/dhparam.pem 2048

Cela peut prendre plusieurs minutes, préparez du café !!

Configuration du serveur Nginx

Nous allons éditer l fichier de configuration de votre site sur Nginx, avec votre éditeur favoris (le mien est nano), faites sudo nano /etc/nginx/sites-available/ma_conf , puis commencer par supprimer ou commenter :

listen 80 default_server;
listen [::]:80 default_server ipv6only=on;

Puis ajouter :

        listen 443 ssl;

        server_name example.com www.example.com;
        ## N'oubliez pas root, index et les autres paramètre de votre site ##

        ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
        ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
        ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
        ssl_prefer_server_ciphers on;
        ssl_dhparam /etc/ssl/certs/dhparam.pem;
        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:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:AES:CAMELLIA:DES-CBC3-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!aECDH:!EDH-DSS-DES-CBC3-SHA:!EDH-RSA-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA';
        ssl_session_timeout 1d;
        ssl_session_cache shared:SSL:50m;
        ssl_stapling on;
        ssl_stapling_verify on;
        add_header Strict-Transport-Security max-age=15768000;

Toujours dans la même conf, on va ajouter la redirection pour que toutes les demandes de pages soit redirigées vers le SSL :

server {
    listen 80;
    server_name example.com www.example.com;
    return 301 https://$host$request_uri;
}

Tester votre configuration avec sudo nginx -t  puis relancer avec sudo service nginx restart .

Pour tester la mise en place du certificat SSL, dans votre barre de navigateur, saisir : https://www.ssllabs.com/ssltest/analyze.html?d=example.com, vous constaterez que le certificat est correctement mis en place.

Automatisation du renouvellement

Le certificat délivré par Let’s Encrypt à une validité de 90 jours, vous allez pouvoir le renouveler manuellement : sudo certbot-auto renew ou en passant par une tâche cron, faites sudo crontb -e  et ajouter :

30 2 * * 1 /usr/local/sbin/certbot-auto renew >> /var/log/le-renew.log
35 2 * * 1 /etc/init.d/nginx reload

Conclusion

Vous avez maintenant un serveur internet rapide et performant avec Nginx, PHP7 et mysql, le tout sous un certificat SSL. A l’heure où j’écris, phpmyadmin ne fonctionne pas encore.

N’hésitez pas à commenter et à partager, un mot fait toujours plaisir.

Laisser un commentaire