WordPress Rocket Stack : envoyez WordPress sur orbite !

Sur Orion, j’ai installé ma WordPress Rocket Stack qui est configurée avec la stack suivante:

  • Ubuntu Server 22.04 LTS
  • MySQL 8+
  • NginX 1.25+
  • PHP 8.3
  • Redis
  • Nginx FastCGI Cache
  • Fail2ban
  • LetsEncrypt avec acme.sh

Hébergement

L’hébergement est la base de votre site, c’est tout simplement la fondation sur laquelle va reposer votre code.

Vous avez tout intérêt à avoir un très bon hébergeur : il doit être rapide dès le départ et offrir de bonnes garanties en termes de performance et de sécurité.

Si vous avez un site WordPress ou WooCommerce, je ne peux que vous recommander Kinsta, WPEngine ou Nexcess. Tous trois sont de très bons hébergeurs, particulièrement orientés vers la performance avec des ressources garanties et un support technique réactif et efficace en cas de besoin.

Personnellement, j’utilise un serveur dédié chez OVH parce que j’héberge pas mal de sites et j’ai besoin d’avoir un contrôle fin sur la configuration de chacun des services.

Ubuntu Server

J’étais auparavant sous Debian mais j’ai finalement opté pour Ubuntu Server 22.04 LTS pour ce nouveau serveur.

L’avantage d’Ubuntu est de pouvoir disposer des mises à jour plus rapidement que sous Debian.

Installation de la WordPress Rocket Stack

# MySQL
# Latest link is always on the apt page: https://dev.mysql.com/downloads/repo/apt/
wget -c https://dev.mysql.com/get/mysql-apt-config_0.8.29-1_all.deb
dpkg -i mysql-apt-config_0.8.29-1_all.deb

# Packages
apt install software-properties-common tmux curl wget zip unzip git
add-apt-repository ppa:ondrej/php
add-apt-repository ppa:ondrej/nginx-mainline
apt update -y
apt upgrade -y
apt install mysql-server -y # accept all defaults

# PHP 8.3
# Note: the json module is now part of PHP core
apt install php8.3 php8.3-apcu php8.3-bcmath php8.3-bz2 php8.3-cli php8.3-common php8.3-curl php8.3-fpm php8.3-gd php8.3-gmp php8.3-igbinary php8.3-imagick php8.3-imap php8.3-intl php8.3-mbstring php8.3-mysql php8.3-opcache php8.3-phpdbg php8.3-readline php8.3-redis php8.3-soap php8.3-xml php8.3-zip -y

# Run installs
apt install nginx -y
apt install fail2ban -y
apt install redis -y
apt install libnginx-mod-http-brotli-filter libnginx-mod-http-brotli-static -y

# Get NginX config files
git clone https://github.com/skyminds/wordpress-rocketstack
cp wordpress-rocketstack/nginx/* /etc/nginx/ -R
rm wordpress-rocketstackCode language: PHP (php)

DNS : ajout du site sur le serveur

Mon serveur est hébergé chez OVH donc il faut ajouter le domaine aux DNS secondaires du serveur.

Sur l’interface Kimsufi, cela se fait très simplement:

Ajouter le domaine au serveur (dns secondaire)
Ajouter le domaine au serveur (dns secondaire)

Configurer Cloudflare

Si vous utilisez Cloudflare – ce que je vous recommande fortement – et que vous obtenez une erreur 403 ou alors une page “Welcome to NginX” en lieu et place de votre nouveau site, veillez bien à sélectionner la bonne option SSL dans Cloudflare > Example.com > SSL/TLS > Overview : il faut sélectionner Full ou Full (Strict) mais surtout pas “Flexible“:

Choisissez toujours l'option SSL/TLS Full (Strict) chez Cloudflare
Choisissez toujours l’option SSL/TLS Full (Strict) chez Cloudflare

Ensuite, il ne nous reste qu’à faire pointer le CNAME vers l’adresse IP du serveur et d’ajouter le champs TXT qui a été indiqué par OVH dans l’étape précédente:

Ajout de l'enregistrement DNS au format TXT pour valider le DNS secondaire chez OVH
Ajout de l’enregistrement DNS au format TXT pour valider le DNS secondaire chez OVH

Ajout du server block NginX

DOMAIN="example.com"
DOMAINDIR="example"

mkdir -p /home/www/$DOMAINDIR
chown www-data:www-data /home/www/$DOMAINDIR

mkdir -p /home/nginx-cache/$DOMAINDIR
chown -R www-data:www-data /home/nginx-cache/

cp /etc/nginx/sites-available/wprocketstack.conf /etc/nginx/sites-available/$DOMAINDIR.conf

rm /etc/nginx/sites-enabled/default
rm /etc/nginx/sites-available/defaultCode language: PHP (php)

On édite ensuite la configuration:

nano /etc/nginx/sites-available/$DOMAINDIR.confCode language: PHP (php)

Mettez l’adresse du site dans la directive server_name:

server_name example.comCode language: CSS (css)

Installation du certificat SSL avec acme.sh

curl https://get.acme.sh | shCode language: JavaScript (javascript)

Quittez votre session SSH puis rouvrez la session SSH, vérifiez qu’acme.sh est bien installé:

acme.sh -hCode language: CSS (css)

On peut créer un certificat avec acme.sh de différentes manières.

Personnellement, j’aime bien la procédure qui ajoute un enregistrement DNS au domaine pour vérifier que vous en êtes bien le propriétaire.

Trouvez votre hébergeur dans la liste. Ici un exemple avec GoDaddy:

export GD_Key="W7N7hKxHk99kr7ubx"
export GD_Secret="WUbD5ejrsxBe52"
acme.sh --issue -d $DOMAIN -d *.$DOMAIN --keylength ec-384 --dns dns_gdCode language: JavaScript (javascript)

J’utilise CloudFlare donc j’ajoute mes identifiants au fichier .bashrc:

nano .bashrc

export CF_Key="1111111111111111111111111"
export CF_Email="user@example.com"Code language: JavaScript (javascript)

On lance ensuite la demande de certificat wildcard pour le domaine:

acme.sh --issue -d $DOMAIN -d *.$DOMAIN --keylength ec-384 --dns dns_cfCode language: PHP (php)

On déplace ensuite les fichiers de notre nouveau certificat dans un répertoire de la configuration nginx, pour rassembler toute notre configuration au même endroit:

mkdir -p /etc/nginx/ssl/$DOMAIN

acme.sh --install-cert --ecc -d $DOMAIN --key-file /etc/nginx/ssl/$DOMAIN/privkey.pem --fullchain-file /etc/nginx/ssl/$DOMAIN/fullchain.pem --reloadcmd "service nginx force-reload"Code language: PHP (php)

Le certificat SSL est automatiquement régénéré tous les 60 jours, automatiquement via un cronjob.

Il vous reste à éditer la configuration de votre server block SSL dans votre fichier de configuration nginx pour ajouter les références aux fichiers du certificat:

server{
  # ...
  # acme.sh cert
  ssl_certificate           /etc/nginx/ssl/example.com/fullchain.pem;
  ssl_certificate_key       /etc/nginx/ssl/example.com/privkey.pem;
  # ...
}Code language: PHP (php)

On vérifie la configuration :

nginx -t

Et on peut désormais activer notre bloc serveur :

ln -s /etc/nginx/sites-available/$DOMAINDIR.conf /etc/nginx/sites-enabled/Code language: PHP (php)

Et on relance nginx :

service nginx restart

Configuration du firewall

Nous sommes sous Ubuntu donc UFW est déjà installé mais n’est pas activé :

ufw status verbose

Status: inactive

Première chose à faire, lister les applications détectées par UFW :

ufw app list

Available applications:
  Nginx Full
  Nginx HTTP
  Nginx HTTPS
  OpenSSHCode language: PHP (php)

Deuxième chose extrêmement importante à faire : autoriser la connexion SSH, autrement lorsque le firewall sera activé, on ne pourra plus joindre le serveur :

ufw allow ssh
ufw allow 'Nginx Full'
ufw allow from XXX.XXX.XXX.XXXCode language: JavaScript (javascript)

Par précaution, ajoutez aussi votre IP, on ne sait jamais. On active ensuite le pare-feu :

ufw enable

Command may disrupt existing ssh connections. Proceed with operation (y|n)? y
Firewall is active and enabled on system startupCode language: JavaScript (javascript)

Configuration de MySQL

On commence par sécuriser notre installation de MySQL :

mysql_secure_installation

Vous pouvez répondre Y à toutes les questions pour tout bétonner.

On passe ensuite à la création de notre base de données et utilisateur SQL :

mysql -u root -p

[MOT DE PASSE ROOT]Code language: CSS (css)

Une fois dans la console MySQL :

CREATE DATABASE example;
CREATE USER 'example-USER'@'localhost' IDENTIFIED BY '1nyXI7Y)$spmslgz4HhdE4Lc_vm&)Gh!MsZFk';
GRANT ALL PRIVILEGES ON example.* TO 'example-USER'@'localhost';
FLUSH PRIVILEGES;
EXIT;Code language: PHP (php)

On optimise un peu notre instance MySQL :

nano /etc/mysql/mysql.conf.d/mysqld.cnf

Et on ajoute à la fin du fichier :

innodb_buffer_pool_size = 200M
innodb_log_file_size = 100M
innodb_buffer_pool_instances = 8
innodb_io_capacity = 5000
max_binlog_size = 100M
expire_logs_days = 3

On redémarre ensuite le serveur MySQL :

service mysql restart

Configuration de PHP

On édite le fichier de configuration de PHP-FPM:

# PHP 8.3
nano /etc/php/8.3/fpm/php.iniCode language: PHP (php)

Et on modifie les directives suivantes :

max_execution_time = 6000
max_input_vars = 6000
memory_limit = 512M
upload_max_filesize = 100M
post_max_size = 100M

opcache.enable=1
opcache.memory_consumption=1024
opcache.interned_strings_buffer=64
opcache.max_accelerated_files=50000
opcache.revalidate_freq=60

On édite ensuite notre pool PHP :

# PHP 8.3
nano /etc/php/8.3/fpm/pool.d/www.confCode language: PHP (php)

Avec la configuration suivante :

pm = dynamic

pm.max_children = 120
pm.start_servers = 20
pm.min_spare_servers = 10
pm.max_spare_servers = 30

; MATT : SECURITY
php_admin_value[disable_functions] = passthru,shell_exec,system

; MATT : NEXTCLOUD
clear_env = no

On enregistre le fichier et on redémarre PHP :

# PHP 8.3
service php8.3-fpm restartCode language: CSS (css)

Installation de WordPress avec wp-cli

On peut maintenant installer wp-cli pour gérer WordPress :

wget https://raw.githubusercontent.com/wp-cli/builds/gh-pages/phar/wp-cli.phar
chmod +x wp-cli.phar
mv wp-cli.phar /usr/local/bin/wp

# update
wp cli updateCode language: PHP (php)

Et lancer l’installation de WordPress :

# DB connection details used for WP install
DB="example"
DBUSER="example-USER"
DBPASSWORD="1nyXI7Y)$spmslgz4HhdE4Lc_vm&)Gh!MsZFk"

cd /home/www/$DOMAINDIR

wp core download --allow-root
chown www-data:www-data * -R
wp core config --dbhost=localhost --dbname=$DB --dbuser=DBUSER --dbpass=$DBPASSWORD --allow-root
chmod 600 wp-config.php

# WP admin user
WPADMINPASSWORD="CzHCI&uBoyRJuIVHLdTg_Sn9RtV$w#B8G51KYn$o@o8q78ANu-GpU7iDg9nlRRq"
WPADMINEMAIL="root@example.com"

wp core install --url="https://${SITEURL}" --title="Rocket Stack" --admin_name=$DB-admin --admin_password=$WPADMINPASSWORD --admin_email=$WPADMINEMAIL --allow-root

chown www-data:www-data /home/www/$DOMAINDIR -RCode language: PHP (php)

Configuration de Redis

Le serveur dispose de 32 Go de RAM, on alloue donc 3 Go pour redis:

echo "maxmemory 3000mb" >> /etc/redis/redis.conf
echo "maxmemory-policy allkeys-lru" >> /etc/redis/redis.conf

sed -i 's/^save /#save /gi' /etc/redis/redis.confCode language: JavaScript (javascript)

Et on redémarre le service :

service redis-server restart

Ensuite, il vous suffit d’installer le plugin Redis Object Cache de Till Krüss, et d’activer le cache Redis dans les options du plugin pour servir le site directement depuis les objets mis en cache mémoire par Redis.

Conclusion

Et voilà, vous devriez avoir tout ce qu’il faut pour avoir une très bonne base pour lancer votre site WordPress sur votre propre serveur dédié ou VPS.

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 »

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 !

Opinions