Le scénario
Nordika vient de signer avec un nouveau client, et ouvre un site dédié pour l’héberger. Il vous faut, en une seule intervention : provisionner l’accès de deux administrateurs, déployer un serveur web avec la configuration propre à ce client, mettre en place la base de données applicative avec ses secrets protégés, et vous assurer que tout ça est parfaitement rejouable si jamais un troisième serveur rejoint l’infrastructure plus tard.
C’est l’occasion de mobiliser, dans un seul projet structuré, tout ce que vous avez appris depuis la première leçon de cette formation.
Environnement disponible
Vous disposez de :
- 1 serveur de contrôle avec Ansible installé
- 2 clients Debian
nrd-web1nrd-db1
Informations de connexion
- Utilisateur :
root - Mot de passe :
formation
⚠️ Les conteneurs de ce lab repartent de zéro à chaque session. Prévoyez donc le bootstrap complet (clé SSH, inventaire) en tout début de TP.
Cahier des charges
- Accès : deux comptes administrateurs (
admin1,admin2) doivent exister sur les deux machines, avec leur propre clé SSH, membres d’un groupeadmin, et un droit sudo complet. - Web : Apache doit être installé sur
nrd-web1, avec un VirtualHost templatisé au nom du nouveau client (server_domain: "client-nouveausite.nordika.local"), redémarré uniquement si la configuration change. - Base de données : MariaDB doit être installé sur
nrd-db1, avec un mot de passe root et un mot de passe applicatif tous deux protégés par Vault, une baseclient_nouveausite_dbet un utilisateur applicatif dédié. - Structure : le projet doit être organisé en rôles (
utilisateurs,apache,mariadb), avec un inventaire propre séparantwebserversetdatabases. - Rejouabilité : l’ensemble du playbook, rejoué une seconde fois sans aucune modification, doit afficher
changed=0sur toutes les tâches. - Bonus : le playbook doit permettre de ne redéployer que la partie web via un tag, sans toucher aux comptes ni à la base de données.
Conseils
- Vous avez déjà écrit chacun de ces trois rôles séparément dans les TP précédents (6, 8 et 9) — l’exercice ici consiste à les assembler proprement pour un cas concret complet, pas à repartir de zéro.
- Pensez à l’ordre des plays : la vérification de connectivité d’abord, puis les comptes (qui concernent les deux machines), puis le web et la base de données chacun sur leur groupe.
- N’oubliez pas
validate: "visudo -cf %s"sur le fichier sudoers des administrateurs.
🧪 Lab · membre
🧪 Démarrer — 30 minVoir la solutionMasquer la solution
Installer Ansible
apt update
apt install ansible
Bootstrap complet
ssh-keygen -t ed25519 -C "ansible@control-serveur" -f ~/.ssh/id_ed25519 -N ""
ssh root@nrd-web1
nano .ssh/authorized_keys
# Coller la clé publique
ssh root@nrd-db1
nano .ssh/authorized_keys
# Coller la même clé publique
ping nrd-web1
ping nrd-db1
Structure du projet et inventaire
mkdir -p ansible/{roles,group_vars,files} && cd ansible
nano inventaire.yaml
# inventaire.yaml
all:
hosts:
nrd-web1:
ansible_host: <IP>
nrd-db1:
ansible_host: <IP>
children:
webservers:
hosts:
nrd-web1:
databases:
hosts:
nrd-db1:
ansible all -i inventaire.yaml -m ping
Générer les clés SSH des deux administrateurs
ssh-keygen -t ed25519 -C "admin1@nordika" -f files/admin1_id_ed25519 -N ""
ssh-keygen -t ed25519 -C "admin2@nordika" -f files/admin2_id_ed25519 -N ""
Le rôle utilisateurs
cd roles && ansible-galaxy init utilisateurs && cd ..
nano roles/utilisateurs/templates_sudoers_admin.j2
# roles/utilisateurs/templates_sudoers_admin.j2
{{ item.nom }} ALL=(ALL) NOPASSWD: ALL
nano roles/utilisateurs/tasks/main.yml
# roles/utilisateurs/tasks/main.yml
---
- name: Créer le groupe admin
ansible.builtin.group:
name: admin
state: present
- name: Créer les comptes administrateurs
ansible.builtin.user:
name: "{{ item.nom }}"
groups: admin
append: yes
create_home: yes
state: present
loop: "{{ administrateurs }}"
loop_control:
label: "{{ item.nom }}"
- name: Déployer la clé publique de chaque administrateur
ansible.posix.authorized_key:
user: "{{ item.nom }}"
state: present
key: "{{ lookup('file', 'files/' + item.cle) }}"
loop: "{{ administrateurs }}"
loop_control:
label: "{{ item.nom }}"
- name: Accorder les droits sudo complets à chaque administrateur
ansible.builtin.template:
src: templates_sudoers_admin.j2
dest: "/etc/sudoers.d/{{ item.nom }}"
validate: "visudo -cf %s"
owner: root
group: root
mode: "0440"
loop: "{{ administrateurs }}"
loop_control:
label: "{{ item.nom }}"
# group_vars/all.yml
administrateurs:
- { nom: "admin1", cle: "admin1_id_ed25519.pub" }
- { nom: "admin2", cle: "admin2_id_ed25519.pub" }
Le rôle apache
cd roles && ansible-galaxy init apache && cd ..
nano roles/apache/templates/nordika.conf.j2
# roles/apache/templates/nordika.conf.j2
<VirtualHost *:80>
ServerName {{ server_domain }}
DocumentRoot /var/www/html
</VirtualHost>
nano roles/apache/tasks/main.yml
# roles/apache/tasks/main.yml
---
- name: Installer Apache
ansible.builtin.apt:
name: apache2
state: present
update_cache: yes
tags: install
- name: Déployer le VirtualHost depuis le template
ansible.builtin.template:
src: nordika.conf.j2
dest: /etc/apache2/sites-available/nordika.conf
notify: Redémarrer Apache
tags: config
- name: Activer le site
ansible.builtin.command: a2ensite nordika.conf
args:
creates: /etc/apache2/sites-enabled/nordika.conf
notify: Redémarrer Apache
tags: config
# roles/apache/handlers/main.yml
---
- name: Redémarrer Apache
ansible.builtin.service:
name: apache2
state: restarted
# host_vars/nrd-web1.yml
server_domain: "client-nouveausite.nordika.local"
Le rôle mariadb, avec Vault
cd roles && ansible-galaxy init mariadb && cd ..
echo "MonMotDePasseVault123" > .vault_pass.txt
chmod 600 .vault_pass.txt
nano ansible.cfg
# ansible.cfg
[defaults]
vault_password_file = .vault_pass.txt
ansible-vault encrypt_string 'RootDB123!' --name 'mysql_root_password' --vault-password-file .vault_pass.txt
ansible-vault encrypt_string 'AppDB123!' --name 'app_password' --vault-password-file .vault_pass.txt
nano host_vars/nrd-db1.yml
# host_vars/nrd-db1.yml
app_db: client_nouveausite_db
app_user: client_nouveausite_user
mysql_root_password: !vault |
$ANSIBLE_VAULT;1.1;AES256
<collez le bloc généré>
app_password: !vault |
$ANSIBLE_VAULT;1.1;AES256
<collez le bloc généré>
nano roles/mariadb/tasks/main.yml
# roles/mariadb/tasks/main.yml
---
- name: Installer MariaDB
ansible.builtin.apt:
name:
- mariadb-server
- python3-pymysql
state: present
update_cache: yes
tags: install
- name: Démarrer MariaDB
ansible.builtin.service:
name: mariadb
state: started
enabled: yes
tags: install
- name: Définir le mot de passe root
community.mysql.mysql_user:
name: root
host: localhost
password: "{{ mysql_root_password }}"
login_unix_socket: /run/mysqld/mysqld.sock
check_implicit_admin: true
priv: "*.*:ALL,GRANT"
tags: config
- name: Créer la base applicative
community.mysql.mysql_db:
name: "{{ app_db }}"
state: present
login_user: root
login_password: "{{ mysql_root_password }}"
tags: config
- name: Créer l'utilisateur applicatif
community.mysql.mysql_user:
name: "{{ app_user }}"
password: "{{ app_password }}"
priv: "{{ app_db }}.*:ALL"
host: "%"
state: present
login_user: root
login_password: "{{ mysql_root_password }}"
tags: config
Le playbook d’orchestration final
nano playbook_nouveau_site.yaml
# playbook_nouveau_site.yaml
---
- name: Vérifier la connectivité avant tout déploiement
hosts: webservers:databases
gather_facts: yes
tasks:
- name: Ping de toute la flotte concernée
ansible.builtin.ping:
tags: always
- name: Provisionner les administrateurs
hosts: webservers:databases
become: yes
roles:
- role: utilisateurs
tags: users
- name: Déployer le serveur web du nouveau site
hosts: webservers
become: yes
roles:
- role: apache
tags: apache
- name: Déployer la base de données du nouveau site
hosts: databases
become: yes
roles:
- role: mariadb
tags: mariadb
Exécuter le tout
ansible-playbook playbook_nouveau_site.yaml -i inventaire.yaml -v
Valider la rejouabilité
ansible-playbook playbook_nouveau_site.yaml -i inventaire.yaml -v
changed=0 sur l’ensemble des tâches, sur les deux machines : l’infrastructure du nouveau site est entièrement provisionnée, de façon idempotente.
Valider le bonus : redéployer uniquement la partie web
ansible-playbook playbook_nouveau_site.yaml -i inventaire.yaml --tags apache
Seul le play ciblant webservers s’exécute — comptes et base de données restent intouchés.
🎉 Formation terminée. Vous êtes parti d’un simple ansible -m ping sans inventaire, vous terminez avec une infrastructure complète, sécurisée et rejouable, provisionnée en une seule commande. C’est exactement la compétence qui aurait évité, chez Nordika, la nuit où tout a mal tourné.