Déploiement d’un site web sur WordPress

Déployer un site web fait partie de ces sujets très simples à démarer, aux ramifications infinies. Je vais vous expliquer comment et pourquoi ce site a vu le jour, auto-hébergé sur Docker : de son installation aux enjeux impliqués

Ce site web est développé sur WordPress et auto-hébergé au sein de mon Homelab (voir : Vue d’ensemble de mon Homelab). Il a pour objectif d’offrir une vitrine de mes projets et de se conformer aux exigences de l’épreuve du BTS SIO. En plus de compétences techniques, sa mise en place nécessite de cerner les enjeux de l’exposition sur Internet de données personnelles et la gestion de la visibilité et de l’image exposée.

I - Installation du site web sur Docker

Docker est une plateforme de conteneurisation qui permet de déployer facilement des applications isolées les unes des autres. Comparativement aux machines virtuelles, les conteneurs utilisent plus efficacement les ressources car ils partagent le noyau Linux de l’OS hôte. Docker est particulièrement adapté aux serveurs web, qui peuvent être déployés, déplacés et décommissionnés très efficacement.

Il y a beaucoup de façon de déployer des applications avec Docker. Ici, le serveur WordPress est installé sur un hôte seul avec Docker Compose.

1 - Système hôte

L’infrastructure de déploiement est un cluster d’hyperviseurs Proxmox. Proxmox gère les conteneurs LXC, mais n’intègre pas nativement la gestion des conteneurs Docker. L’équipe de Proxmox Server Solutions recommande officiellement de déployer Docker au sein d’une machine virtuelle.

Une machine virtuelle Debian (bookworm) correspond parfaitement dans ce cas. Elle servira à héberger d’autres conteneurs, donc on peut déjà lui accorder les ressources nécessaires :

Paramètres initiaux

La machine étant destinée à être déployée sur tous les hôtes du cluster, on s’assure de choisir un emplacement de stockage partagé (Ceph) et un type de processeur compatible pour tous (x86-64-v2-AES).

Deux interfaces réseau lui sont affectées : une sur le VLAN 20, DMZ où sera exposé le serveur web, et l’autre sur le VLAN 10 uniquement pour l’administration.

Pour isoler les interfaces, il faut mettre en place un pare-feu. Proxmox a cette capacité intégrée ce qui permet de centraliser la gestion du pare-feu pour toutes les VMs, mais aussi de garantir son fonctionnement même en cas de compromission de la VM.

C’est un pare-feu avec états, dont la politique par défaut est DROP pour les paquets entrants, et ACCEPT pour les paquets sortants (peut être modifiée).

Tel que configuré ci-dessus, le pare-feu permet de :

  • Autoriser l’accès SSH et Portainer par les administrateurs.
  • Bloquer et loguer toute tentative d’accès depuis la VM au réseau d’administration.
  • Autoriser l’accès aux serveurs hébergés sur la VM depuis l’interface DMZ.

Avant d’installer Docker, il faut prendre soin de faire les configurations minimales :

  • Renommer la machine (dans /etc/hostname et /etc/hosts)
  • Configurer les interfaces réseau en IP statiques (/etc/network/interfaces)
  • Indiquer le bon serveur DNS dans /etc/resolv.conf

Installation de Docker

On suit les recommandations officielles de Docker pour son installation. Je vous invite à consulter la documentation officielle actuelle. Au moment de la rédaction, l’installation se présente comme ceci :

# Add Docker's official GPG key:
sudo apt update
sudo apt install ca-certificates curl
sudo install -m 0755 -d /etc/apt/keyrings
sudo curl -fsSL https://download.docker.com/linux/debian/gpg -o /etc/apt/keyrings/docker.asc
sudo chmod a+r /etc/apt/keyrings/docker.asc
# Add the repository to Apt sources:
echo \
  "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/debian \
  $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | \
  sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt update
sudo apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin

On peut aussi ajouter l’utilisateur admin au groupe Docker :

sudo usermod -aG Docker <monutilisateur>

On peut vérifier que l’installation s’est bien passée avec :

docker -v

2 - Docker Compose

Docker compose permet de définir tous les paramètres nécessaires en un seul fichier YAML. Le fichier docker-compose.yml utilisé est le suivant (mots de passes utilisés mis à part) :

version: '3.8'

volumes:
    webserver:
    database:

networks:
    dmz_network:
        name: DMZ
        external: true
    backend:


services:
    webserver:
        image: wordpress:6.4.3
        container_name: portfolio-webserver
        restart: unless-stopped
        ports:
            - 10.10.20.200:8080:80
        environment:
            - WORDPRESS_DB_HOST=database
            - WORDPRESS_DB_USER=wordpress
            - WORDPRESS_DB_PASSWORD=MOTDEPASSEDB
            - WORDPRESS_DB_NAME=wordpress
        depends_on:
            - database
        networks:
            - dmz_network
            - backend
        volumes:
            - webserver:/var/www/html

    database:
        image: mysql:8.0
        container_name: portfolio-database
        restart: unless-stopped
        environment:
            - MYSQL_ROOT_PASSWORD=MOTDEPASSEROOT
            - MYSQL_DATABASE=wordpress
            - MYSQL_USER=wordpress
            - MYSQL_PASSWORD=MOTDEPASSEDB
        volumes:
          - database:/var/lib/mysql
        networks:
          - backend

Quelques explications sur le fichier :

  • 3-5 : Volumes persistants : enregistrent les données à garder à long terme du site
  • 7-11 : Réseaux utilisés par les conteneurs : Le Réseau DMZ est défini globalement dans Docker et n’autorise pas la communication entre conteneurs
  • 16 et 35 : Version taguée : pour plus de contrôle sur les updates. À modifier pour mettre à jour
  • 19-20 : Exposition des ports sur l’adresse DMZ de l’hôte
  • 21-25 : Variables d’environnement : À accorder avec celles de la base de données
  • 28-30 : Accès au réseau pour la communication extérieure et avec la base de données
  • 38-42 : Variables d’environnement : À accorder avec celles du serveur web
  • 45-46 : Pas d’accès extérieur. La communication est exclusive avec le serveur web

Avec ce simple fichier, idéalement placé dans un dossier à part, toute la configuration côté serveur est faite.

II - Sécurisation et exposition sur Internet

1 - Pare-feu pfSense

Le site web doit être accessible depuis Internet par tous en IPv4 et en IPv6. L’accès va se faire depuis un reverse-proxy HAProxy tournant directement sur le pare-feu pfSense.

HAProxy va écouter en TCP sur les ports 80 (HTTP) et 443 (HTTPS) sur le WAN. Il faut donc ouvrir les ports en conséquence.

Petite particularité : L’adresse IPv4 sur le WAN est attribuée par DHCP. Au démarrage de pfSense, HAProxy se lance avant que le routeur n’ait pu récupérer une adresse IPv4 depuis le serveur DHCP. HAProxy ne se lance donc pas au démarrage de pfSense et il faut le lancer manuellement.

Pour y remédier, il suffit de faire écouter HAProxy sur localhost (127.0.0.1) sur deux ports aléatoires, et de faire une redirection NAT depuis les ports 80 et 443. De cette manière, HAProxy aura une adresse IPv4 existante au démarrage et se lancera automatiquement.

2 - Configuration des DNS

Il est indispensable d’avoir une configuration DNS fonctionnelle sur un site web. Le nom du site web doit être facile à retenir et bien représenter son contenu et sa fonction. C’est aussi un point essentiel à l’établissement du certificat TLS.

Le site sera accessible principalement à l’adresse www.arthur-reaute.fr, mais aussi vers arthur.reaute.fr (sans www). Il y a donc deux enregistrements A et deux enregistrements AAAA (pour l’IPv4 et l’IPv6 respectivement) à instaurer, pointant vers l’adresse IP publique du serveur HAProxy (donc l’adresse de l’interface WAN de pfSense). Les adresses sont ici fixes, dans le cas contraire il faudrait paramétrer un enregistrement DNS dynamique.

D’autres enregistrements seront à configurer par la suite

3 - Certificat TLS avec Let's Encrypt

Le chiffrement des communications entre le client et le serveur web se fait par le protocole HTTPS reposant sur le chiffrement asymétrique TLS. Le certificat est le fondement de ce protocole. Il contient la clé publique du serveur qui doit être signée par une autorité de certification de confiance.

Let’s Encrypt fait partie de ces autorités, et fourni un service permettant de générer et renouveler automatiquement ces certificats : ACME (Automated Certificate Management Environment). PfSense intègre un module ACME au sein de son interface, et permet donc de générer facilement le certificat nécessaire pour mon site.

Plusieurs méthodes sont disponibles, dont la validation par challenge DNS que j’ai présentée ici : Obtenir un certificat SSL Valide avec Let’s Encrypt pour les serveurs internes sans exposition.

Pour aller plus loin, on peut ajouter un enregistrement CAA dans la zone DNS, pointant que seul Let’s Encrypt peut délivrer un certificat TLS pour ce domaine.

4 - Reverse proxy HAProxy

HAProxy est un reverse proxy très complet permettant de faire de l’équilibrage de charge entre plusieurs serveurs en aval. Ici, seule sa fonction de reverse proxy nous intéresse : Il va nous permettre de gérer le chiffrement TLS avec le client, et renvoyer les requêtes en clair sur le réseau local uniquement au serveur WordPress. Il sert aussi à définir des règles d’accès et des configurations spécifiques, et offre la possibilité d’héberger plusieurs serveurs web différents sur la même combinaison d’adresse IP et de port (80/443).

Le serveur se configure en deux temps : une partie Backend pour définir les modalités de communication entre HAProxy et le/les serveur(s) web, et une partir Frontend qui concerne la communication avec le client.

PfSense permet de faire une configuration graphique de HAProxy, les fichiers de configuration générés sont disponibles dans /var/etc/haproxy.

Backend

Ici, la configuration Backend est très simple : un seul serveur, sans chiffrement.

Frontend

HAProxy va écouter en HTTPS sur les ports 443 en IPv6 et IPv4. Pour rappel, l’IPv4 affectée est natée depuis le WAN. En indiquant l’option SSL Offloading, on indique à HAProxy d’effectuer la terminaison TLS avec le client.

Pour déterminer quel Backend utiliser, on défini des ACL pour chaque domaine.

Si le domaine demandé correspond au portfolio, HAProxy utilise le Backend défini précédemment. On peut aussi rediriger les requêtes de arthur-reaute.fr vers www.arthur-reaute.fr.

En utilisant l’option « forwardfor », un header X-Forwarded-For va être ajouté à la requête HTTP. Grâce à cela, le serveur WordPress va comprendre qu’il est derrière un reverse proxy et va ajuster son comportement automatiquement.

On détermine le certificat à présenter pour le chiffrement TLS de deux manières.

Un certificat de base sera retourné quels que soient les ACL définies plus haut. Il est indispensable pour les rares clients web qui ne supportent pas le SNI (Server Name Indication), mais un seul domaine peut supporter ce mode de fonctionnement. Si il y a besoin de faire fonctionner plusieurs sites web de cette façon, il faut utiliser un certificat « wildcard », qui fonctionnera pour tous les sous-domaines.

Sinon, on peut ajouter les certificats pour les différents sites web en fonction du SNI.

Enfin, on peut configurer une redirection de HTTP vers HTTPS automatique, avec un autre Frontend écoutant sur le port 80

Avec les mêmes ACL que pour le Frontend principal, on ajoute une action de redirection.

Pour valider la configuration, on peut s’aider d’outils comme ssllabs.com qui vont donner un score sur la sécurisation du site web.

III - Configuration du site : enjeux et bonnes pratiques

Maintenant que toute l’infrastructure est en place, on peut s’attaquer au cœur du sujet et commencer à construire le site.

1 - Choix du design

WordPress est un CMS très complet, mais aussi très documenté donc il y a énormément de ressources disponibles pour des conseils et tutoriels. L’étape la plus importante est de choisir un thème. Il ne faut pas hésiter à tester et changer de thème au fur et à mesure que les idées viennent et que le projet de site se concrétise, mais il est fastidieux de changer une fois que tout est construit.

J’ai choisi le thème Astra pour sa flexibilité. Couplé au plugin Starter Templates, il permet de créer très rapidement un squelette de site web.

Avec le builder Elementor, les capacités du site sont adéquates avec l’usage recherché.

Le développement web est un métier à part entière. WordPress facilite le développement d’un site web simple et efficace. Néanmoins, il est préférable de faire appel à un expert du domaine lorsque les enjeux sont importants.

2 - Mise en conformité

En tant que site web publiquement exposé, il est impératif de surveiller son contenu. Il ne doit pas divulguer des informations confidentielles ou illégales. Il est soumis à la réglementation en vigueur, dont le RGPD.

Toute collecte de donnée personnelle doit être consentie, justifiée et proportionnée au but recherché. Il faut mettre à disposition une politique de confidentialité en tout point où des données sont collectées.

WordPress intègre une fonction pour proposer facilement une politique de confidentialité, à personnaliser selon le site.

Le formulaire envoie un mail par SMTP via Proton Mail à mon adresse mail de contact contact@platy.bzh. Des règles de filtrages sont appliquées pour automatiquement classer les mails dans le bon dossier et appliquer une délétion automatique au bout de 90 jours.

require ["fileinto", "imap4flags", "vnd.proton.expire"];

if allof (address :all :comparator "i;unicode-casemap" :is "To" "contact@platy.bzh", address :all :comparator "i;unicode-casemap" :is "From" "notif@platylab.com", header :is "X-Pm-Origin" "internal") {
    fileinto "Contact";
    # Permanetly delete after 90 days
    expire "day" "90";
}

Les mails reçus sont bien automatiquement supprimés au bout de 90 jours :

Outre l’aspect légal, le site doit aussi respecter d’autres règles de conformité qui peuvent lui être imposées.

Dans le cas présent, ce portfolio fait l’objet d’une épreuve pour le BTS SIO. Il faut donc impérativement s’assurer que le contenu correspond aux attentes. Par exemple, aucune mention explicite du centre de formation ne doit apparaître. Il faut conjuguer les exigences de conformité avec les objectifs du site.

3 - Sécurisation supplémentaire

Près de la moitié des sites du monde utilisent WordPress. Il s’agit donc d’une cible de choix pour les attaquants, et il convient de la protéger au maximum.

Le principal vecteur d’attaque sur WordPress est les plugins. Pour imiter les risques, il ne faut garder installé que les plugins et thèmes qui sont utilisés par le site web. Ces derniers doivent être maintenus à jour le plus souvent possible tout comme le reste de WordPress .

Fort heureusement, WordPress intègre un système de mise à jour automatique qui permet de garder l’esprit tranquille. Mieux vaut un site qui ne fonctionne plus suite à une mise à jour qu’on peut facilement restaurer depuis des sauvegardes, qu’un site plein de vulnérabilités.

On préfèrera gérer les mises à jour de WordPress en lui-même via la mise à jour du conteneur docker.

On peut aussi restreindre l’accès à l’interface d’administration de WordPress seulement depuis le réseau local. Dans notre cas, on peut se servir de HAProxy : On bloque tout accès aux pages d’administration sur le Frontend extérieur, et on vient créer un autre Frontend uniquement accessible depuis le LAN d’administration qui n’a pas cette restriction.

ACL sur le Frontend principal
Action à réaliser
Page d’erreur affichée en cas de refus (modifiable)
Configuration du Frontend local

Le LAN d’administration a un serveur DNS dédié pour indiqué aux administrateurs d’utiliser l’adresse du deuxième Frontend pour accéder au site.

On peut aussi rajouter HSTS (HTTP Strict Transport Security) sur le serveur web pour indiquer à l’utilisateur compatible qu’il doit interagir en utilisant HTTPS.

ATTENTION : il faut être sûr que HTTPS fonctionne parfaitement avant de mettre en place cette fonctionnalité, car HTTP pourrait ne plus fonctionner du tout ensuite.

4 - Référencement Web (SEO)

La visibilité sur internet est très importante pour tout site web public. Ce site web doit apparaître dans les premiers résultats sur le moteurs de recherche et doit être référencé sur tous les médias possibles.

La SEO (Search Engine Optimisation) est parfois considérée comme une science à part entière. On peut suivre quelques principes de base pour être bien référencé :

  • Autoriser le référencement : Sur WordPress, il est possible de décourager les moteurs de recherche d’indexer le site. Il faut bien entendu désactiver ce paramètre si on veut que notre site soit bien référencé.

  • Contenu long et de qualité : Les longs articles sont priorisés par rapports aux pages courtes. Plus généralement, un site bien fonctionnel aura plus de chance d’être mieux référencé.

  • Enregistrer son site web chez les acteurs principaux : Il est possible d’indiquer volontairement à Google et Bing comment est structuré le site, et monitorer son référencement grâce à Google search console et Bing webmaster. On peut s’aider de plugins comme YoastSEO pour contruire et maintenir sa sitemap.

Conclusion

La mise en place d’un site web est un travail demandant de nombreuses compétences différentes. Il faut des compétences solides en réseau, mais aussi des facultés en design, des qualités d’organisation et de rigueur en respectant les contraintes de conformité.

Généralement, les différentes étapes sont réparties au sein d’une entreprise selon les compétences et droits de chacun. De nombreux outils et produits permettent aussi de faciliter un ou plusieurs aspects de la mise en place et la maintenance du site.

Ce projet est une mise en pratique personnelle d’un besoin concret de visibilité de mes compétences. Bien que d’étendue moindre, les enjeux abordés et les compétences développées sont transférables à la gestion d’un site professionnel d’une entreprise.

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *