Projet récap
Ce qu'on va construire
On assemble tout ce qu'on a appris pour déployer un serveur web complet de façon entièrement automatisée avec Ansible. L'architecture cible : Nginx comme reverse proxy devant une application Node.js, le tout géré par systemd.
- Un inventaire avec le groupe
web_servers - Deux rôles séparés :
nginxetnodejs - Des variables pour personnaliser port, domaine et chemin
- Un playbook principal
site.ymlqui orchestre tout
Ce projet reprend tous les concepts vus dans le module : inventaires (leçon 03), playbooks (leçon 04), rôles et variables (leçon 05). Si un concept te semble flou, relis la leçon correspondante avant de continuer.
Structure du projet
Voici l'arborescence complète du projet. Crée ces fichiers et dossiers avant de commencer à écrire le contenu.
deploy-web/
├── inventory/
│ └── hosts.ini # liste des serveurs cibles
├── group_vars/
│ └── web_servers.yml # variables communes au groupe
├── roles/
│ ├── nginx/
│ │ ├── tasks/
│ │ │ └── main.yml # installer + configurer Nginx
│ │ └── templates/
│ │ └── vhost.conf.j2 # template Jinja2 du vhost
│ └── nodejs/
│ ├── tasks/
│ │ └── main.yml # installer Node + copier l'app
│ └── files/
│ └── app.js # le code de l'application
└── site.yml # playbook principal
L'inventaire
Commence par déclarer ton serveur cible dans inventory/hosts.ini.
Remplace l'adresse IP par celle de ton propre serveur.
[web_servers]
192.168.1.10 ansible_user=ubuntu ansible_ssh_private_key_file=~/.ssh/id_ed25519
[web_servers:vars]
ansible_python_interpreter=/usr/bin/python3
Les variables
Les variables communes au groupe sont centralisées dans group_vars/web_servers.yml.
Tu peux surcharger n'importe laquelle dans les host_vars/ pour un serveur spécifique.
---
# Nginx
app_domain: monapp.exemple.fr
nginx_port: 80
# Node.js
node_app_port: 3000
node_app_path: /opt/monapp
node_app_user: deploy
node_service_name: monapp
Le playbook principal — site.yml
Le playbook principal est minimaliste : il délègue tout le travail aux rôles. C'est la bonne pratique — le playbook orchestraire, les rôles font.
---
- name: Déployer le serveur web complet
hosts: web_servers
become: true
roles:
- role: nodejs
- role: nginx
L'ordre des rôles est important : nodejs avant nginx,
car Nginx a besoin que l'application soit déjà en écoute sur le port 3000
pour que le check de santé au démarrage réussisse.
Rôle nodejs — installer et déployer l'application
Ce rôle installe Node.js, crée l'utilisateur système, copie le code de l'application et la démarre comme un service systemd.
---
- name: Installer Node.js et npm (via NodeSource)
ansible.builtin.shell:
cmd: curl -fsSL https://deb.nodesource.com/setup_20.x | bash -
creates: /etc/apt/sources.list.d/nodesource.list
- name: Installer le paquet nodejs
ansible.builtin.apt:
name: nodejs
state: present
update_cache: true
- name: Créer l'utilisateur système
ansible.builtin.user:
name: ""
system: true
shell: /usr/sbin/nologin
create_home: false
- name: Créer le répertoire de l'application
ansible.builtin.file:
path: ""
state: directory
owner: ""
mode: "0755"
- name: Copier le code de l'application
ansible.builtin.copy:
src: app.js
dest: "/app.js"
owner: ""
mode: "0644"
notify: Redémarrer monapp
- name: Déployer le service systemd
ansible.builtin.template:
src: monapp.service.j2
dest: "/etc/systemd/system/.service"
mode: "0644"
notify: Redémarrer monapp
- name: Activer et démarrer le service
ansible.builtin.systemd:
name: ""
state: started
enabled: true
daemon_reload: true
L'application Node.js — roles/nodejs/files/app.js
Pour ce projet, l'application est volontairement simple : un serveur HTTP qui répond sur le port configuré.
const http = require('http');
const PORT = process.env.PORT || 3000;
const server = http.createServer((req, res) => {
res.writeHead(200, { 'Content-Type': 'text/plain' });
res.end('Bonjour depuis Node.js — déployé par Ansible !\n');
});
server.listen(PORT, () => {
console.log(`Serveur démarré sur le port ${PORT}`);
});
Le service systemd — roles/nodejs/templates/monapp.service.j2
[Unit]
Description= — Application Node.js
After=network.target
[Service]
Type=simple
User=
WorkingDirectory=
ExecStart=/usr/bin/node /app.js
Environment=PORT=
Restart=on-failure
RestartSec=5s
[Install]
WantedBy=multi-user.target
Rôle nginx — reverse proxy devant Node.js
Ce rôle installe Nginx, génère la configuration du virtual host à partir d'un template Jinja2, active le site et recharge Nginx.
---
- name: Installer Nginx
ansible.builtin.apt:
name: nginx
state: present
update_cache: true
- name: Déployer la configuration du vhost
ansible.builtin.template:
src: vhost.conf.j2
dest: "/etc/nginx/sites-available/"
mode: "0644"
notify: Recharger Nginx
- name: Activer le vhost (lien symbolique)
ansible.builtin.file:
src: "/etc/nginx/sites-available/"
dest: "/etc/nginx/sites-enabled/"
state: link
notify: Recharger Nginx
- name: S'assurer que Nginx est démarré et activé
ansible.builtin.service:
name: nginx
state: started
enabled: true
# Handler — exécuté uniquement si une tâche notifie "Recharger Nginx"
Le fichier handlers/main.yml du rôle nginx doit contenir le handler
Recharger Nginx avec ansible.builtin.service: name=nginx state=reloaded.
Ansible n'exécute les handlers qu'une seule fois, à la fin du play, même si plusieurs tâches les notifient.
Le template du vhost Nginx — roles/nginx/templates/vhost.conf.j2
server {
listen ;
server_name ;
# Logs
access_log /var/log/nginx/_access.log;
error_log /var/log/nginx/_error.log;
location / {
proxy_pass http://127.0.0.1:;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
Déployer le projet
Une fois tous les fichiers en place, lance le playbook depuis la racine du projet :
# Vérifier la syntaxe avant de lancer
ansible-playbook site.yml -i inventory/hosts.ini --syntax-check
# Mode dry-run : voir ce qui va changer sans rien modifier
ansible-playbook site.yml -i inventory/hosts.ini --check
# Déploiement réel
ansible-playbook site.yml -i inventory/hosts.ini
# Vérifier que l'app répond
curl http://192.168.1.10
Pour aller plus loin : ajoute un rôle ufw pour configurer le pare-feu,
un rôle certbot pour le HTTPS, ou intègre ce playbook dans un pipeline CI/CD
avec GitHub Actions. Les rôles tout prêts sont disponibles sur Ansible Galaxy.
Récapitulatif du module
Tu as parcouru les 6 leçons du module Ansible. Voici ce que tu maîtrises maintenant :
- Leçon 01 : Ansible est un outil agentless, idempotent, qui décrit l'infrastructure en YAML.
- Leçon 02 : Installation sur la machine de contrôle, configuration SSH et première connexion aux hôtes.
- Leçon 03 : Les inventaires organisent les hôtes en groupes ; les variables d'inventaire personnalisent la connexion.
- Leçon 04 : Les playbooks décrivent des plays :
hosts,become,tasks, modules natifs, handlers. - Leçon 05 : Les rôles structurent le code (
tasks/,handlers/,templates/,files/,defaults/) ; les variables s'organisent en niveaux de priorité. - Leçon 06 : Projet complet — deux rôles (
nginx+nodejs), variables centralisées, templates Jinja2, service systemd.
Ressources pour aller plus loin
- Documentation officielle Ansible — référence complète des modules et bonnes pratiques.
- Ansible Galaxy — bibliothèque de rôles et collections communautaires prêts à l'emploi.
- Tips & Tricks Ansible — astuces pour écrire des playbooks robustes et maintenables.
- ansible-examples sur GitHub — projets de référence officiels avec des patterns complets.