Configurer un serveur WordPress à la main — installer nginx, PHP-FPM, MariaDB, créer les utilisateurs système, générer les certificats — prend facilement une demi-journée la première fois, et redevient un exercice de mémoire incertain la fois suivante, six mois plus tard, quand il faut provisionner un nouveau serveur pour un nouveau client. Ansible résout ce problème en transformant la configuration serveur en code versionné, rejouable à l’identique.
Contrairement à un script bash qui exécute une suite de commandes, un playbook Ansible décrit un état voulu (« le paquet nginx doit être installé », « ce fichier de configuration doit avoir ce contenu ») et se charge lui-même de vérifier ce qui doit changer. Rejouer un playbook sur un serveur déjà configuré ne casse rien : c’est la propriété d’idempotence, essentielle pour oser relancer le même playbook en confiance.
Structure d’un playbook par rôles
Un playbook bien organisé sépare chaque responsabilité dans un rôle distinct, ce qui permet de réutiliser un rôle d’un projet à l’autre sans tout dupliquer :
provisionnement/
├── inventaire.ini
├── site.yml
└── roles/
├── nginx/
│ └── tasks/main.yml
├── php/
│ └── tasks/main.yml
├── mariadb/
│ └── tasks/main.yml
└── certificats/
└── tasks/main.yml
# inventaire.ini
[serveurs_wordpress]
srv-client-cabinet.exemple.test ansible_user=deploiement
Le rôle nginx et PHP-FPM
# roles/nginx/tasks/main.yml
- name: Installer nginx
apt:
name: nginx
state: present
update_cache: yes
- name: Déployer la configuration du site
template:
src: site.conf.j2
dest: /etc/nginx/sites-available/{{ nom_domaine }}
notify: recharger nginx
- name: Activer le site
file:
src: /etc/nginx/sites-available/{{ nom_domaine }}
dest: /etc/nginx/sites-enabled/{{ nom_domaine }}
state: link
Le module template injecte les variables du projet (nom de domaine, chemin racine) dans un fichier de configuration Jinja2, ce qui évite de dupliquer un fichier statique par serveur. Le mot-clé notify déclenche un « handler » — ici un rechargement de nginx — uniquement si le fichier a réellement changé, jamais sinon.

Le rôle MariaDB et la création de la base
# roles/mariadb/tasks/main.yml
- name: Installer MariaDB
apt:
name: mariadb-server
state: present
- name: Créer la base de données du site
mysql_db:
name: "{{ nom_base }}"
state: present
- name: Créer l'utilisateur applicatif
mysql_user:
name: "{{ utilisateur_base }}"
password: "{{ mot_de_passe_base }}"
priv: "{{ nom_base }}.*:ALL"
state: present
Les modules mysql_db et mysql_user font partie de la collection community.mysql, à installer séparément via ansible-galaxy collection install community.mysql. Le mot de passe de la base ne doit jamais rester en clair dans le dépôt : on le stocke chiffré avec Ansible Vault, qui protège tout fichier de variables sensibles derrière un mot de passe maître.
ansible-vault encrypt group_vars/serveurs_wordpress/secrets.yml
ansible-playbook site.yml --ask-vault-pass
Certificats TLS automatisés
Le rôle certificats installe Certbot et obtient un certificat Let’s Encrypt sans intervention manuelle, en utilisant le plugin nginx qui configure lui-même le renouvellement automatique :
# roles/certificats/tasks/main.yml
- name: Installer certbot et son plugin nginx
apt:
name:
- certbot
- python3-certbot-nginx
state: present
- name: Obtenir le certificat
command: >
certbot --nginx -d {{ nom_domaine }}
--non-interactive --agree-tos -m {{ email_contact }}
args:
creates: "/etc/letsencrypt/live/{{ nom_domaine }}"
L’argument creates indique à Ansible de ne relancer la commande que si le dossier de certificat n’existe pas encore, préservant l’idempotence même pour une commande shell brute.
Créer les utilisateurs système avec les bons droits
Un dernier rôle, souvent oublié, gère les comptes système : un utilisateur applicatif dédié au déploiement, sans accès root direct, avec sa clé publique SSH ajoutée aux authorized_keys :
- name: Créer l'utilisateur de déploiement
user:
name: deploiement
shell: /bin/bash
groups: www-data
append: yes
- name: Ajouter la clé publique de déploiement
authorized_key:
user: deploiement
key: "{{ lookup('file', 'cles/deploiement.pub') }}"
Un playbook qu’on ne rejoue jamais devient obsolète sans qu’on s’en aperçoive. On le relance systématiquement sur chaque serveur existant après une modification, en mode
--checkd’abord, pour voir ce qui changerait avant de l’appliquer pour de vrai.
En résumé
Un playbook Ansible bien structuré transforme le provisionnement d’un nouveau serveur WordPress en une commande unique, reproductible et documentée par le code lui-même. Le temps investi dans les rôles nginx, PHP, MariaDB et certificats se rentabilise dès le deuxième serveur provisionné, et devient indispensable à partir du dixième.