Introduction
Ansible permet de :
- Configurer des serveurs en YAML (playbooks)
- Sans agent : juste SSH + Python sur la cible
- Idempotent : on peut rejouer un playbook 100 fois, le resultat est le meme
- Modules pour tout : apt, systemd, file, docker, k8s, postgres, etc.
- Roles reutilisables (Ansible Galaxy)
- Vault pour chiffrer les secrets
Cas d'usage : configurer 50 serveurs identiques, deployer une app, faire des updates de masse.
Prerequis
- Poste de controle (poste de travail Linux / macOS, ou VPS)
- Cibles : VPS Linux avec SSH + Python 3
- Cles SSH configurees pour acceder aux cibles
Etape 1 : Installation
sudo apt update
sudo apt install -y ansible
ansible --version
Ou via pip :
sudo apt install -y python3-pip
pip install ansible
Etape 2 : Inventaire
hosts.ini :
[web]
web1 ansible_host=192.168.1.10
web2 ansible_host=192.168.1.11
[db]
db1 ansible_host=192.168.1.20
[all:vars]
ansible_user=admin
ansible_ssh_private_key_file=~/.ssh/id_ed25519
ansible_become=yes
Ou en YAML (inventory.yml) :
all:
vars:
ansible_user: admin
ansible_become: yes
children:
web:
hosts:
web1:
ansible_host: 192.168.1.10
web2:
ansible_host: 192.168.1.11
db:
hosts:
db1:
ansible_host: 192.168.1.20
Etape 3 : Test de connectivite (ad-hoc)
ansible -i hosts.ini all -m ping
Si tout est ok :
web1 | SUCCESS => {"changed": false, "ping": "pong"}
web2 | SUCCESS => {"changed": false, "ping": "pong"}
db1 | SUCCESS => {"changed": false, "ping": "pong"}
Commande ad-hoc utile :
ansible -i hosts.ini web -m apt -a "name=nginx state=present" --become
ansible -i hosts.ini all -m shell -a "uptime"
ansible -i hosts.ini all -m setup # voir tous les facts
Etape 4 : Premier playbook
site.yml :
---
- name: Configurer serveurs web
hosts: web
become: yes
tasks:
- name: Installer paquets
apt:
name:
- nginx
- htop
- curl
state: present
update_cache: yes
- name: Demarrer nginx
systemd:
name: nginx
state: started
enabled: yes
- name: Deployer page index
copy:
content: "Hello from {{ inventory_hostname }}"
dest: /var/www/html/index.nginx-debian.html
owner: www-data
group: www-data
mode: '0644'
notify: Reload nginx
handlers:
- name: Reload nginx
systemd:
name: nginx
state: reloaded
Executer :
ansible-playbook -i hosts.ini site.yml
Sortie :
PLAY [Configurer serveurs web] ********
TASK [Gathering Facts] ****************
ok: [web1]
ok: [web2]
TASK [Installer paquets] **************
changed: [web1]
changed: [web2]
TASK [Demarrer nginx] *****************
ok: [web1]
ok: [web2]
PLAY RECAP ***************************
web1 : ok=4 changed=2 unreachable=0 failed=0
web2 : ok=4 changed=2 unreachable=0 failed=0
Etape 5 : Variables et templates
group_vars/web.yml :
nginx_port: 80
domain: monsite.fr
admin_email: [email protected]
Template templates/nginx.conf.j2 :
server {
listen {{ nginx_port }};
server_name {{ domain }};
root /var/www/{{ domain }};
location / {
try_files $uri $uri/ =404;
}
}
Dans le playbook :
- name: Deployer config nginx
template:
src: templates/nginx.conf.j2
dest: /etc/nginx/sites-available/{{ domain }}
notify: Reload nginx
Etape 6 : Conditionals et loops
- name: Installer packages selon l'OS
apt:
name: "{{ item }}"
state: present
loop:
- nginx
- mariadb-server
- php-fpm
when: ansible_os_family == "Debian"
- name: Installer Apache si pas Nginx
apt:
name: apache2
state: present
when: web_server == "apache"
Etape 7 : Roles
Organisez les playbooks complexes en roles :
roles/
webserver/
tasks/
main.yml
handlers/
main.yml
templates/
nginx.conf.j2
defaults/
main.yml
files/
logo.png
meta/
main.yml
roles/webserver/tasks/main.yml :
- name: Installer nginx
apt:
name: nginx
state: present
- name: Deployer config
template:
src: nginx.conf.j2
dest: /etc/nginx/sites-available/default
notify: Reload nginx
roles/webserver/handlers/main.yml :
- name: Reload nginx
systemd:
name: nginx
state: reloaded
Utilisation dans site.yml :
- hosts: web
become: yes
roles:
- webserver
- common
Etape 8 : Ansible Vault (secrets)
Pour chiffrer des secrets :
ansible-vault create group_vars/all/vault.yml
Entrez un mdp. Editez :
mysql_root_password: "secret-tres-fort"
api_key: "abc123xyz"
Le fichier est chiffre. Utilisez-le normalement :
- name: Set mysql root password
mysql_user:
name: root
password: "{{ mysql_root_password }}"
Pour executer un playbook avec vault :
ansible-playbook -i hosts.ini site.yml --ask-vault-pass
Ou avec un fichier de mdp :
echo "votre-mdp" > .vault_pass
chmod 600 .vault_pass
ansible-playbook -i hosts.ini site.yml --vault-password-file .vault_pass
Etape 9 : Ansible Galaxy
Reutilisez des roles communautaires :
ansible-galaxy install geerlingguy.nginx
ansible-galaxy install geerlingguy.mysql
Dans votre playbook :
- hosts: web
roles:
- geerlingguy.nginx
- geerlingguy.mysql
Browse : https://galaxy.ansible.com
Etape 10 : Dry-run et check mode
Tester sans appliquer :
ansible-playbook -i hosts.ini site.yml --check
Voir les diffs :
ansible-playbook -i hosts.ini site.yml --check --diff
Etape 11 : Tags
Pour executer une partie d'un playbook :
- name: Installer nginx
apt:
name: nginx
state: present
tags: install
- name: Config nginx
template:
src: nginx.conf.j2
dest: /etc/nginx/sites-enabled/default
tags: config
ansible-playbook -i hosts.ini site.yml --tags config
ansible-playbook -i hosts.ini site.yml --skip-tags install
Etape 12 : Integration avec Terraform
Workflow typique :
- Terraform provisionne les VPS (Hetzner, Scaleway, etc.) et genere un inventaire dynamique
- Ansible configure les VPS provisionnes
Generez l'inventaire depuis Terraform :
terraform output -json | jq -r '...' > inventory.ini
Ou utilisez le module community.general.terraform_inventory.
Depannage
"Failed to connect via SSH"
Verifiez :
- Connectivite reseau (ping, traceroute)
- Cle SSH (
ssh user@targetmanuellement) ansible_usercorrect- Python 3 installe sur la cible
"Missing sudo password"
Ajoutez --ask-become-pass ou become_method: sudo dans le playbook.
Performance lente
Activez le pipelining et le fact caching dans ansible.cfg :
[ssh_connection]
pipelining = True
[defaults]
gathering = smart
fact_caching = jsonfile
fact_caching_connection = /tmp/ansible-facts
fact_caching_timeout = 86400
forks = 50
"ERROR! Unexpected Exception"
Ansible plante. Verifiez la syntaxe YAML (indentation, espaces) :
ansible-playbook --syntax-check site.yml
Variables non resolves
Verifiez l'ordre de precedence (cli > playbook > host_vars > group_vars > role defaults).
ansible -i hosts.ini web1 -m debug -a "var=hostvars[inventory_hostname]"
Commandes utiles
# Test connectivite
ansible all -i hosts.ini -m ping
# Ad-hoc
ansible web -i hosts.ini -m apt -a "name=htop state=present" --become
# Playbook
ansible-playbook -i hosts.ini site.yml
# Limiter a un host
ansible-playbook -i hosts.ini site.yml --limit web1
# Tester sans appliquer
ansible-playbook -i hosts.ini site.yml --check --diff
# Tags
ansible-playbook -i hosts.ini site.yml --tags config
ansible-playbook -i hosts.ini site.yml --skip-tags slow
# Vault
ansible-vault create file.yml
ansible-vault edit file.yml
ansible-vault encrypt existing.yml
ansible-vault decrypt encrypted.yml
# Galaxy
ansible-galaxy install role_name
ansible-galaxy collection install community.general
# Voir les facts
ansible web1 -i hosts.ini -m setup
Conclusion
Ansible vous donne :
- Configuration management agentless
- Idempotence (re-execution safe)
- Ecosysteme massif (Galaxy)
- Integration aisee avec Terraform
Pour aller plus loin :
- Utilisez Ansible Tower / AWX pour une UI et CI/CD
- Combinez avec Terraform pour la provisioning
- Pour des deploiements applicatifs, considerez ArgoCD (k8s) ou Kamal (containers)
Ressources
- Documentation officielle : https://docs.ansible.com
- Ansible Galaxy : https://galaxy.ansible.com
- Ansible AWX : https://github.com/ansible/awx
- Best practices : https://docs.ansible.com/ansible/latest/tips_tricks/index.html


















