La plupart des gens installent WordPress le facile way. We’re going to install it the droite way. secure, repeatable and for what it’s worth, it’s still easy.
WordPress doesn’t get hacked because it’s bad. It gets hacked because people cut corners.
WordPress propulse plus d'un tiers du web. Bien qu'il soit réputé pour son installation en cinq minutes, la plupart des utilisateurs le configurent de manière à laisser des failles aux pirates et des soucis à long terme. Bien l'installer ne vise pas à compliquer les choses, mais à établir des bases solides pour la performance, la sécurité et la stabilité. Une configuration bâclée ou copiée-collée cache souvent des failles dangereuses que les robots et les scanners savent exploiter. En consacrant quelques minutes supplémentaires à configurer correctement la base de données, à verrouiller PHP et à utiliser une configuration Nginx renforcée, vous vous protégez des problèmes qui peuvent mettre des sites entiers hors ligne. Imaginez la construction d'une maison : n'importe qui peut y mettre quatre murs, mais seule une construction soignée résistera à une tempête. Ce guide vous guide pas à pas dans le processus complet pour vous permettre de profiter pleinement de WordPress sans commettre les erreurs courantes.
Alright, Let’s skip the chit-chat
What we’ll be using?
- Système:Ubuntu 22.04 ou 24.04 est recommandé
- Base de données: MariaDB pour les performances et la stabilité
- Serveur Web: NGINX pour les performances et la stabilité
- Mise en cache: Redis - magasin de données en mémoire hautes performances
- SSL: CertBot
- Suppléments: Rechargement automatique Nginx, compression Brotli, journalisation sécurisée, obfuscation des e-mails
Ubuntu has become my go-to server operating system ever since Red Hat “Killed” CentOS. The ease of use, extensive documentation, strong community support, and wide availability of up-to-date software packages make it a natural fit for both beginners and professionals. It strikes the right balance between stability and modern features, which is exactly what you want when you’re running something as widely targeted as WordPress.
Préparez votre serveur
sudo apt install python-software-properties
sudo add-apt-repository ppa:ondrej/nginx
sudo apt update && sudo apt upgrade -y
sudo apt install -y nginx nginx-extras mariadb-server unzip curl redis-server imagemagick
sudo apt install -y php8.3-fpm php8.3-mysql \
php8.3-curl php8.3-xml php8.3-zip php8.3-gd php8.3-mbstring php8.3-bcmath \
php8.3-intl php8.3-soap php8.3-imagick
# Allow NGINX in the Firewall (For this instance UFW)
sudo ufw allow OpenSSH
sudo ufw allow 'Nginx Full'
sudo ufw enable
Comme toujours, je recommande de désactiver la connexion root SSH via ssh_config et de désactiver l'authentification par mot de passe et de recourir aux clés SSH pour des raisons de sécurité.
Configurer la base de données
Exécutez le durcisseur intégré
sudo mysql_secure_installation
Switch to unix_socket authentication [Y/n] N
Change the root password? [Y/n] As you wish
Remove anonymous users? [Y/n] Y
Disallow root login remotely? [Y/n] Y
Remove test database and access to it? [Y/n] Y
Reload privilege tables now? [Y/n] Y
Créer une base de données dédiée + un utilisateur
# Change the DB/User Names, Password as you wish
CREATE DATABASE wp CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE USER 'wpuser'@'localhost' IDENTIFIED BY 'VERY_STRONGPASS!';
GRANT ALL PRIVILEGES ON wp.* TO 'wpuser'@'localhost';
FLUSH PRIVILEGES;
Réglage de la base de données recommandé, modifier /etc/mysql/mariadb.conf.d/50-server.cnf
[mysqld]
bind-address = 127.0.0.1
# Adjust as you like.
# ~50-70% of RAM on DB-only servers
innodb_buffer_pool_size = 1G
innodb_log_file_size = 256M
innodb_flush_method = O_DIRECT
max_connections = 200
query_cache_size = 0
query_cache_type = 0
sudo systemctl restart mariadb
Optimiser PHP pour WordPress
Ouvrir /etc/php/8.3/fpm/php.ini
ou 8.4 et décommentez/ajoutez ce qui suit
memory_limit = 256M
; These values are kinda low. So adjust as you like
upload_max_filesize = 64M
post_max_size = 64M
max_execution_time = 120
; Security: prevent path-info exploits
cgi.fix_pathinfo = 0
expose_php = Off
; Enable OPcache
zend_extension=opcache
opcache.enable=1
opcache.memory_consumption=128
opcache.max_accelerated_files=10000
opcache.validate_timestamps=1
# Reload PHP-fpm
sudo systemctl reload php8.3-fpm # or 8.4
Télécharger WordPress via WP-CLI
Installer WP-CLI
sudo -u ubuntu -i # Login as a user other than the root
sudo apt install -y php-cli php-mbstring unzip less file
curl -sS -o /usr/local/bin/wp https://raw.githubusercontent.com/wp-cli/builds/gh-pages/phar/wp-cli.phar
chmod +x /usr/local/bin/wp
Créer une racine Web
mkdir -p /var/www/blog
cd /var/www/blog
Télécharger et configurer
wp core download --locale=en_US
# The DB/User/Password you created earlier
wp config create --dbname=wp --dbuser=wpuser --dbpass=VERY_STRONGPASS! --dbhost=localhost --dbprefix=wp_
# Do not use default username: admin, Choose something more secure
wp core install --url="https://example.com" --title="My Site" --admin_user="myusername" --admin_password="ANOTHERSTRONGPASS" --admin_email="me@example.com"
sudo chown -R www-data:www-data /var/www/blog
find /var/www/blog -type d -exec chmod 755 {} \;
find /var/www/blog -type f -exec chmod 644 {} \;
# WP-CONFIG should always have 600 or 440 (-rw-------) permission
chmod 600 /var/www/blog/wp-config.php
# https://developer.wordpress.org/advanced-administration/security/hardening/#file-permissions
Sécuriser et optimiser WordPress
# Set unique salts & keys
wp config shuffle-salts
Modifierwp-config.php
et ajoutez ce qui suit
# Disable file editing inside WP-Admin
define('DISALLOW_FILE_EDIT', true);
# Limit Revisions to 5
define('WP_POST_REVISIONS', 5);
# Disable WP cron (use system cron)
define('DISABLE_WP_CRON', true);
# Save/Exit the file
sudo -u ubuntu crontab -e
# Append the following at the end of the file
* * * * * /usr/local/bin/wp --path=/var/www/blog cron event run --due-now --quiet
Configurer le serveur Web NGINX
First, Let’s setup Certbot to Issue an SSL Certificate | Clé API CloudflareSi vous n'utilisez pas Cloudflare, trouvez votre fournisseur ici ou utilisez la méthode HTTP.
Gardez à l'esprit that “blog.conf” can be renamed anything you like. In case that wasn’t clear.
sudo apt install -y certbot python3-certbot-dns-cloudflare
sudo mkdir -p /etc/letsencrypt
echo "dns_cloudflare_api_token = YOUR_API_TOKEN_HERE" > /etc/.cloudflare.ini
sudo chmod 600 /root/.cloudflare.ini
# Issue a Certificate
sudo certbot certonly -d example.com -d "*.example.com" \
--dns-cloudflare \
--dns-cloudflare-credentials /etc/.cloudflare.ini \
--key-type rsa \
--rsa-key-size 2048 \
--agree-tos \
--force-renewal\
--no-eff-email\
--email YOUR@EMAIL.COM
# The cert output should be in /etc/letsencrypt/live/example.com/
Now, Let’s setup NGINX. Config Files: Dans mon Github. Don’t forget to change “example.com” inside the files to your domain and SSL Cert path.
nano /etc/nginx/nginx.conf
# Apend/Modify the following inside http{} block
http2 on;
ssl_protocols TLSv1.2 TLSv1.3; # Drop v1, v1.1 - Keep only 1.2 & 1.3
cd /etc/nginx/sites-available/
wget -O /etc/nginx/sites-available/blog.conf https://raw.githubusercontent.com/abdessalllam/cloud-setup/refs/heads/main/wordpress/blog.conf
# Disable directory browsing
echo "autoindex off;" > /etc/nginx/snippets/no-autoindex.conf
# Enable the Website and Reload NGINX
sudo ln -s /etc/nginx/sites-available/blog.conf /etc/nginx/sites-enabled/
sudo nginx -t && sudo systemctl reload nginx
Activer la prise en charge de Cloudflare
If you’ll be using Cloudflare for with Reverse Proxy, we need to add Gammes CF to make sure our Server gets the real IP of the Visitor. Latest Cloudflare’s IPv4 – IPv6 Gammes
The same can apply to other Load balancers, All you have to do is modify the file below to include their IP Ranges “only”.
wget -O /etc/nginx/conf.d/realip.conf https://raw.githubusercontent.com/abdessalllam/cloud-setup/refs/heads/main/wordpress/realip.conf
sudo nginx -t && sudo systemctl reload nginx
Tous les fichiers .conf sous conf.d seront inclus automatiquement par défaut
Ensuite, créez ip.php dans le dossier /var/www/blog et testez si Nginx obtient la véritable IP.
<?php
header('Content-Type: text/plain');
foreach (['REMOTE_ADDR','HTTP_CF_CONNECTING_IP','HTTP_X_FORWARDED_FOR'] as $h) {
echo "$h: " . ($_SERVER[$h] ?? '') . "\n";
}
Maintenant, installez le plugin Cloudflare et appliquez les paramètres recommandés.
Configurer la mise en cache Redis
Redis est l'un des meilleurs moyens d'accélérer WordPress (mise en cache d'objets, parfois mise en cache de pages)
sudo systemctl enable redis-server
sudo systemctl start redis-server
Sécurisez Redis en éditant /etc/redis/redis.conf
# Append/Uncomment/Modify the following
supervised systemd
maxmemory 256mb # adjust for your RAM
maxmemory-policy allkeys-lru # evict least-used keys
Installer les plugins essentiels
wp plugin install redis-cache --activate
wp redis enable
wp plugin install nginx-helper --activate
Installer et configurer Brotli
Brotli makes your website load faster by sending fewer bytes over the internet — like zipping files before emailing them, but automatic and invisible to the user. It’s better than Gzip.
# Only with ppa:ondrej/nginx Repo
sudo apt install libnginx-mod-http-brotli-filter libnginx-mod-http-brotli-static
nano /etc/nginx/nginx.conf
# Append the following to inside http{} block, above "gzip on"
brotli on;
brotli_comp_level 5;
brotli_static on; # serve precompressed .br if present (harmless if not)
brotli_types
text/plain text/css text/javascript application/javascript
application/json application/xml application/rss+xml
application/vnd.ms-fontobject application/font-sfnt
application/x-font-ttf font/ttf font/otf image/svg+xml;
# Append/Uncomment the following
gzip on;
gzip_comp_level 6;
gzip_types text/plain text/css application/javascript application/json application/xml image/svg+xml;
Rechargez NGINX et testez si Brotli fonctionne
sudo nginx -t && sudo systemctl reload nginx
# Brotli client
curl -sI -H 'Accept-Encoding: br' https://yourdomain | grep -i content-encoding
# Response → Content-Encoding: br
# Gzip client
curl -sI -H 'Accept-Encoding: gzip' https://yourdomain | grep -i content-encoding
# Response → Content-Encoding: gzip (or nothing if already tiny)
Rechargement automatique NGINX
if you start using plugins such as Smush, Yoast SEO Redirects, etc… Any plugin that requires include files in “blog.conf” or “nginx.conf”. Everytime the plugin changes that file, we need to reload NGINX. So let’s create a service that does that automatically.
# Create a /etc/systemd/system/nginx-auto-reload.service
[Unit]
Description=Validate and reload Nginx when watched files change
[Service]
Type=oneshot
# Validate config & Stop if there are errors
ExecStart=/usr/sbin/nginx -t
# Reload ONLY if ExecStart succeeded
ExecStartPost=/bin/systemctl reload nginx
# Create /etc/systemd/system/nginx-auto-reload.path
[Unit]
Description=Watch specific Nginx-related files
[Path]
# Add one line per file you want to monitor for changes
# Add/Remove Lines as needed
PathChanged=/var/www/blog/foo.conf
PathChanged=/var/www/blog/bar.conf
PathChanged=/var/www/blog/baz.conf
[Install]
WantedBy=multi-user.target
Activer et démarrer
sudo systemctl daemon-reload
sudo systemctl enable --now nginx-auto-reload.path
# (optional first run)
sudo systemctl start nginx-auto-reload.service
Test: Modifiez l’un des fichiers surveillés, puis
journalctl -u nginx-auto-reload.service -n 20 --no-pager
# You should see nginx: configuration file /etc/nginx/nginx.conf test is successful followed by a reload. If the config is broken, nginx -t will fail and no reload happens.
Sûr Enregistrement
Logs are your black box recorder: they tell you what happened, when, and why. They’re essential for debugging and for spotting performance or security issues. But without rotation, logs grow endlessly and can fill your disk. Do it right, enable only what you need, store it safely, and rotate/compress on a schedule.
mkdir -p /var/log/blog
sudo chown www-data:www-data /var/log/blog
sudo chmod 750 /var/log/blog
sudo tee /etc/logrotate.d/wordpress >/dev/null <<'EOF'
/var/log/blog/debug.log {
weekly
rotate 12
compress
missingok
notifempty
create 640 www-data www-data
}
EOF
# Enable file logging only in wp-config.php
if ( ! defined( 'WP_DEBUG' ) ) {
define( 'WP_DEBUG', true );
}
// Set display to false, We don't want errors displayed on our frontend
define( 'WP_DEBUG_DISPLAY', false );
@ini_set( 'display_errors', 0 );
// Log to a file (outside web root is best)
define('WP_DEBUG_LOG', '/var/log/blog/debug.log');
// Set error logging to a seperate file (optional)
@ini_set('log_errors', 1);
@ini_set('error_log', '/var/log/blog/error.log');
Suppléments
If you’re not using Cloudflare’s “Email Obfuscation”, I recommend this plugin Pour protéger votre adresse e-mail des robots et des scrapers. Votre adresse e-mail n'est affichée que lorsque JavaScript est activé, ce qui la rend invisible à la source de la page et plus difficile à récupérer pour les robots spammeurs.
# Let's create a Must-Use folder
mkdir -p /var/www/blog/wp-content/mu-plugins
chown ubuntu:www-data //var/www/blog/wp-content/mu-plugins
wget -O /var/www/blog/wp-content/mu-plugins/protect-my-email.php https://raw.githubusercontent.com/abdessalllam/cloud-setup/refs/heads/main/wordpress/protect-my-email.php
Usage:
Full Shortcode: [js_email label="Reach out to me via Email:" user="info" domain="example.com" display="inline" subject="Hello" msg="Please enable JS for the Email" class="optional-extra-class"]
Minimal Use: [js_email user="info" domain="example.com"]
Output: info@example.com
What’s next?
Les journaux Nginx sont situés à /var/log/nginx/
That’s it, You are done. Congratulations 🎉🎉 I’d recommend Installing a Cache Plugin and Security Plugin to help speedup and secure your Setup further.
This isn’t the le plus rapide way to install WordPress — but it’s the le bon chemin.
Have suggestions or spotted something we could improve? Share your thoughts in the comments — we’d love to hear from you.