Serveur Ansible sur ESXi pour piloter son LAN
Introduction
À partir d’un certain nombre de machines sur son réseau, se connecter en SSH sur chacune pour faire une mise à jour ou changer un fichier de config devient franchement pénible. Tu le fais une fois, deux fois, et le troisième tu oublies une machine. C’est là qu’Ansible change la donne.
L’idée est simple : une seule machine, le Control Node, parle à toutes les autres via SSH. Pas d’agent à installer, pas de daemon à gérer côté cibles. Tu écris un playbook, tu le lances, et Ansible s’occupe du reste sur l’ensemble de ton parc en parallèle.
Je mets le Control Node dans une VM dédiée sur ESXi — c’est propre, isolé, et ça tourne 24h/24 sans toucher à mes autres machines.
flowchart LR
subgraph ESXi["Serveur ESXi"]
VM_ANS["VM Ansible\nControl Node\nUbuntu 24.04"]
end
subgraph LAN["Réseau Local (192.168.1.0/24)"]
SRV1["Serveur 1\nDebian 12\n.10"]
SRV2["Serveur 2\nUbuntu 22.04\n.11"]
SRV3["NAS\nTrueNAS\n.20"]
SRV4["Cluster K8s\nNœuds\n.30-.32"]
WIN["PC Windows\n.50"]
end
VM_ANS -->|SSH| SRV1
VM_ANS -->|SSH| SRV2
VM_ANS -->|SSH| SRV3
VM_ANS -->|SSH| SRV4
VM_ANS -->|WinRM| WIN
style VM_ANS fill:#e67e22,color:#fff
style SRV1 fill:#3498db,color:#fff
style SRV2 fill:#3498db,color:#fff
style SRV3 fill:#2ecc71,color:#fff
style SRV4 fill:#9b59b6,color:#fff
style WIN fill:#1a5276,color:#fffRésumé des étapes
- Créer la VM sur ESXi (Configuration minimale)
- Installer Ubuntu Server 24.04
- Configurer le réseau (IP fixe, accès LAN)
- Installer Ansible
- Structurer le projet (Inventaire, playbooks, config)
- Déclarer les machines du LAN (Inventaire)
- Distribuer les clés SSH (Authentification sans mot de passe)
- Tester la connectivité (Premier ping Ansible)
- Premiers Playbooks (Mise à jour, durcissement SSH)
- Gérer les secrets (Ansible Vault)
C’est Parti ! 🚀
Étape 1 : Créer la VM sur ESXi
Connecte-toi à l’interface web de ton ESXi (https://<IP_ESXI>), puis navigue vers Virtual Machines > Create / Register VM.
Configuration recommandée
| Paramètre | Valeur |
|---|---|
| Nom | ansible-control |
| OS | Linux — Ubuntu Linux (64-bit) |
| CPU | 2 vCPU |
| RAM | 2 Go (Ansible est léger, c’est largement suffisant) |
| Disque | 20 Go (thin provisioned) |
| Réseau | VM Network — bridge sur le LAN |
Flux de création dans ESXi
flowchart TD
A["Interface Web ESXi\nhttps://ip-esxi"] --> B["Virtual Machines\n> Create / Register VM"]
B --> C["Create a new virtual machine"]
C --> D["Nom : ansible-control\nOS : Ubuntu Linux 64-bit"]
D --> E["Choisir le Datastore"]
E --> F["CPU : 2 vCPU\nRAM : 2 Go\nDisque : 20 Go Thin"]
F --> G["Réseau : VM Network\n(bridge sur le LAN)"]
G --> H["Attacher l'ISO Ubuntu\ndepuis le Datastore"]
H --> I["Finaliser & Démarrer"]
style A fill:#1a5276,color:#fff
style I fill:#2ecc71,color:#fffUploader l’ISO Ubuntu
Si l’ISO n’est pas encore sur le datastore, c’est rapide :
- Va dans Storage > Datastore browser
- Crée un dossier
ISOs - Clique sur Upload et dépose l’ISO Ubuntu Server 24.04
Étape 2 : Installer Ubuntu Server 24.04
Démarre la VM et suis l’installateur. Quelques choix importants à ne pas rater :
- Type d’installation : Ubuntu Server (sans interface graphique, on n’en a pas besoin)
- Nom d’hôte :
ansible-control - Utilisateur : crée un compte, par exemple
ansible - OpenSSH : coche Install OpenSSH server — on en aura besoin pour administrer la VM à distance
Pour les snaps supplémentaires proposés à la fin, passe tout, rien n’est utile ici.
Étape 3 : Configurer le réseau (IP fixe)
Si tu n’as pas configuré l’IP fixe pendant l’installation, voilà comment le faire via Netplan, le gestionnaire réseau d’Ubuntu Server.
D’abord, identifie le nom de ta carte réseau :
ip a# Tu cherches quelque chose comme : ens192, eth0, ens33...Édite ensuite la config Netplan :
sudo nano /etc/netplan/00-installer-config.yamlnetwork: version: 2 ethernets: ens192: # Remplace par ton nom d'interface dhcp4: false addresses: - 192.168.1.5/24 # L'IP fixe du Control Node routes: - to: default via: 192.168.1.1 # Ta passerelle (box/routeur) nameservers: addresses: - 192.168.1.1 - 8.8.8.8Applique et vérifie :
sudo netplan applyping -c 3 8.8.8.8Étape 4 : Installer Ansible
Sur la VM ansible-control :
# Mise à jour du systèmesudo apt update && sudo apt upgrade -y
# Ajout du dépôt officiel Ansible (PPA)sudo apt install -y software-properties-commonsudo add-apt-repository --yes --update ppa:ansible/ansible
# Installationsudo apt install -y ansible
# Vérificationansible --versionTu devrais voir quelque chose comme :
ansible [core 2.17.x] config file = /etc/ansible/ansible.cfg python version = 3.12.xÉtape 5 : Structurer le projet Ansible
Plutôt que de travailler dans /etc/ansible/ (qui demande les droits root à chaque fois), crée un répertoire de projet dans ton home. C’est plus propre et tout est versionnable avec Git.
mkdir -p ~/ansible/{inventory,playbooks,roles,group_vars,host_vars}cd ~/ansibleArchitecture du projet
flowchart TD
ROOT["📁 ~/ansible/"] --> INV["📁 inventory/\nhosts.ini"]
ROOT --> PB["📁 playbooks/\nsite.yml\nupdate.yml"]
ROOT --> GV["📁 group_vars/\nall.yml\nwebservers.yml"]
ROOT --> HV["📁 host_vars/\nserveur1.yml"]
ROOT --> ROLES["📁 roles/\nnginx/\ndocker/"]
ROOT --> CFG["⚙️ ansible.cfg"]
INV -->|"Déclare les\nmachines"| PB
GV -->|"Variables\npar groupe"| PB
HV -->|"Variables\npar hôte"| PB
ROLES -->|"Tâches\nréutilisables"| PB
style ROOT fill:#1565C0,color:#fff
style INV fill:#2E7D32,color:#fff
style PB fill:#E65100,color:#fff
style GV fill:#6A1B9A,color:#fff
style HV fill:#6A1B9A,color:#fff
style ROLES fill:#37474F,color:#fff
style CFG fill:#546E7A,color:#fffCréer le fichier de configuration
Le fichier ansible.cfg évite d’avoir à répéter les options à chaque commande :
cat > ~/ansible/ansible.cfg << 'EOF'[defaults]inventory = ~/ansible/inventory/hosts.iniremote_user = ansibleprivate_key_file = ~/.ssh/id_ed25519host_key_checking = Falsestdout_callback = yamldeprecation_warnings = False
[privilege_escalation]become = Truebecome_method = sudobecome_user = rootEOFÉtape 6 : Déclarer les machines du LAN (Inventaire)
L’inventaire, c’est la liste de toutes les machines qu’Ansible peut piloter. On les organise en groupes logiques pour pouvoir cibler “tous les serveurs Linux” ou “uniquement le cluster K8s” d’une seule commande.
nano ~/ansible/inventory/hosts.ini[linux_servers]serveur1 ansible_host=192.168.1.10serveur2 ansible_host=192.168.1.11nas ansible_host=192.168.1.20
[kubernetes]k8s-master ansible_host=192.168.1.30k8s-worker1 ansible_host=192.168.1.31k8s-worker2 ansible_host=192.168.1.32
[windows]pc-windows ansible_host=192.168.1.50 ansible_user=Administrateur ansible_password=VotreMotDePasse ansible_connection=winrm ansible_winrm_transport=basic ansible_winrm_server_cert_validation=ignore
# Groupe parent qui regroupe tout ce qui est Linux[linux:children]linux_serverskubernetes
[linux:vars]ansible_user=ansibleansible_python_interpreter=/usr/bin/python3Vue logique de l’inventaire
flowchart TD
ALL["Groupe : all"] --> LINUX["Groupe : linux"]
ALL --> WIN["Groupe : windows"]
LINUX --> LINUXSRV["Groupe : linux_servers"]
LINUX --> K8S["Groupe : kubernetes"]
LINUXSRV --> SRV1["serveur1\n192.168.1.10"]
LINUXSRV --> SRV2["serveur2\n192.168.1.11"]
LINUXSRV --> NAS["nas\n192.168.1.20"]
K8S --> MASTER["k8s-master\n192.168.1.30"]
K8S --> WK1["k8s-worker1\n192.168.1.31"]
K8S --> WK2["k8s-worker2\n192.168.1.32"]
WIN --> WINPC["pc-windows\n192.168.1.50"]
style ALL fill:#1565C0,color:#fff
style LINUX fill:#2E7D32,color:#fff
style WIN fill:#1a5276,color:#fff
style K8S fill:#6A1B9A,color:#fff
style LINUXSRV fill:#2E7D32,color:#fffÉtape 7 : Distribuer les clés SSH
Ansible se connecte via SSH. On utilise des clés SSH plutôt que des mots de passe — c’est plus sûr et ça permet l’automatisation complète sans interaction humaine.
Générer une paire de clés sur le Control Node
ssh-keygen -t ed25519 -C "ansible-control" -f ~/.ssh/id_ed25519# Laisse la passphrase vide (Entrée deux fois)Créer l’utilisateur ansible sur les machines cibles
Sur chaque machine cible, à faire manuellement une seule fois :
sudo useradd -m -s /bin/bash ansibleecho "ansible ALL=(ALL) NOPASSWD: ALL" | sudo tee /etc/sudoers.d/ansiblesudo chmod 440 /etc/sudoers.d/ansibleDistribuer la clé publique
ssh-copy-id -i ~/.ssh/id_ed25519.pub ansible@192.168.1.10ssh-copy-id -i ~/.ssh/id_ed25519.pub ansible@192.168.1.11ssh-copy-id -i ~/.ssh/id_ed25519.pub ansible@192.168.1.20# ... pour chaque machine Linux du LANCe qui se passe lors de la connexion
sequenceDiagram
participant A as Control Node<br/>(ansible-control)
participant T as Machine Cible<br/>(serveur1)
Note over A: Clé privée : ~/.ssh/id_ed25519
Note over T: Clé publique dans ~/.ssh/authorized_keys
A->>T: Connexion SSH (utilisateur: ansible)
T->>A: Challenge cryptographique
A->>T: Signature avec clé privée
T->>T: Vérifie avec clé publique
T->>A: Accès accordé ✅
A->>T: Exécute les tâches Ansible via SSHÉtape 8 : Tester la connectivité
Avant d’écrire quoi que ce soit, vérifie que tout est bien en place. La commande ping d’Ansible ne fait pas un vrai ping réseau — elle vérifie que le Control Node arrive à se connecter en SSH et à exécuter du Python sur la cible.
cd ~/ansibleansible all -m pingSi tout va bien, tu dois voir ça pour chaque machine :
serveur1 | SUCCESS => { "changed": false, "ping": "pong"}Si une machine répond UNREACHABLE, le mode verbose te donnera exactement ce qui coince :
ansible serveur1 -m ping -vvvTu peux aussi tester uniquement un groupe :
ansible linux_servers -m pingÉtape 9 : Premiers Playbooks
Place maintenant aux choses concrètes. Voici deux playbooks directement utiles pour piloter un LAN.
Playbook 1 : Mise à jour de toutes les machines Linux
nano ~/ansible/playbooks/update_all.yml---- name: Mettre à jour tous les systèmes Linux du LAN hosts: linux become: yes gather_facts: yes
tasks: - name: Mettre à jour le cache APT (Debian/Ubuntu) apt: update_cache: yes cache_valid_time: 3600 when: ansible_os_family == "Debian"
- name: Mettre à jour tous les paquets (Debian/Ubuntu) apt: upgrade: dist autoremove: yes autoclean: yes when: ansible_os_family == "Debian"
- name: Mettre à jour tous les paquets (RedHat/Rocky) dnf: name: "*" state: latest when: ansible_os_family == "RedHat"
- name: Vérifier si un redémarrage est nécessaire stat: path: /var/run/reboot-required register: reboot_required
- name: Notifier si redémarrage requis debug: msg: "⚠️ {{ inventory_hostname }} nécessite un redémarrage !" when: reboot_required.stat.existsansible-playbook ~/ansible/playbooks/update_all.ymlPlaybook 2 : Durcir SSH sur tout le LAN
---- name: Durcir la configuration SSH sur toutes les machines Linux hosts: linux become: yes
tasks: - name: Désactiver l'authentification par mot de passe SSH lineinfile: path: /etc/ssh/sshd_config regexp: '^#?PasswordAuthentication' line: 'PasswordAuthentication no' state: present notify: Redémarrer SSH
- name: Désactiver le login root par SSH lineinfile: path: /etc/ssh/sshd_config regexp: '^#?PermitRootLogin' line: 'PermitRootLogin no' state: present notify: Redémarrer SSH
- name: Définir le timeout d'inactivité (5 minutes) lineinfile: path: /etc/ssh/sshd_config regexp: '^#?ClientAliveInterval' line: 'ClientAliveInterval 300' state: present notify: Redémarrer SSH
handlers: - name: Redémarrer SSH service: name: sshd state: restartedCe qui se passe quand tu lances un playbook
flowchart TD
CMD["ansible-playbook update_all.yml"] --> PARSE["Ansible parse le Playbook\net charge l'inventaire"]
PARSE --> FACTS["Collecte des Facts sur chaque hôte\n(OS, IP, RAM...)"]
FACTS --> TASK1["Tâche 1 : Mettre à jour le cache APT\n→ Exécuté en parallèle sur tous les hôtes"]
TASK1 --> COND{"when:\nansible_os_family == Debian ?"}
COND -->|"Oui → Ubuntu/Debian"| TASK2A["apt update dist-upgrade"]
COND -->|"Non → Rocky/RedHat"| TASK2B["dnf upgrade"]
TASK2A --> CHECK["Vérifier /var/run/reboot-required"]
TASK2B --> CHECK
CHECK --> REPORT["Rapport final\nchanged / ok / failed par hôte"]
style CMD fill:#e67e22,color:#fff
style FACTS fill:#3498db,color:#fff
style COND fill:#f39c12,color:#000
style TASK2A fill:#2ecc71,color:#fff
style TASK2B fill:#2ecc71,color:#fff
style REPORT fill:#1a5276,color:#fffÉtape 10 : Gérer les secrets avec Ansible Vault
Ne jamais mettre de mots de passe en clair dans les fichiers d’inventaire ou de variables. Ansible Vault chiffre les données sensibles directement dans tes fichiers YAML.
# Crée un fichier de secrets chiffréansible-vault create ~/ansible/group_vars/all/secrets.ymlL’éditeur s’ouvre, tu peux y mettre tes secrets :
db_password: "MonMotDePasseDB_SuperSecret"api_key: "sk-xxxxxxxxxxxxxxxxxxxx"nas_password: "MotDePasseNAS"Pour lancer un playbook qui utilise ces secrets :
# Demande le mot de passe du vault à l'exécutionansible-playbook playbooks/site.yml --ask-vault-pass
# Ou stocke le mot de passe dans un fichier dédié (chmod 600 obligatoire)echo "MonMotDePasseVault" > ~/.vault_passchmod 600 ~/.vault_passansible-playbook playbooks/site.yml --vault-password-file ~/.vault_passVue d’ensemble : comment tout s’articule
flowchart TD
subgraph DEV["Ton PC (développement)"]
ED["Éditeur de code\n(VS Code + Extension Ansible)"]
GIT["Git\nVersionner les playbooks"]
end
subgraph ESXi["Serveur ESXi"]
subgraph VM["VM : ansible-control\n192.168.1.5"]
ANS["Ansible Core"]
INV["inventory/hosts.ini"]
PB["playbooks/*.yml"]
VAULT["Ansible Vault\n(secrets chiffrés)"]
end
end
subgraph LAN["LAN 192.168.1.0/24"]
L1["serveur1\n.10"]
L2["serveur2\n.11"]
NAS["NAS\n.20"]
K8S["Cluster K8s\n.30-.32"]
end
ED -->|"SSH / Push"| VM
GIT -->|"git pull"| VM
ANS --> INV
ANS --> PB
ANS --> VAULT
ANS -->|"SSH"| L1
ANS -->|"SSH"| L2
ANS -->|"SSH"| NAS
ANS -->|"SSH"| K8S
style ED fill:#546E7A,color:#fff
style GIT fill:#e74c3c,color:#fff
style VM fill:#e67e22,color:#fff
style ANS fill:#e67e22,color:#fff
style INV fill:#2E7D32,color:#fff
style PB fill:#E65100,color:#fff
style VAULT fill:#6A1B9A,color:#fff
style L1 fill:#3498db,color:#fff
style L2 fill:#3498db,color:#fff
style NAS fill:#2ecc71,color:#fff
style K8S fill:#9b59b6,color:#fffQuelques habitudes à prendre
Versionne tes playbooks avec Git. Ton infrastructure est du code. Un git commit après chaque modification, comme pour n’importe quel projet.
Organise l’inventaire par service, pas par machine. Des groupes databases, webservers, monitoring sont bien plus utiles que serveur1, serveur2.
Fais des snapshots ESXi du Control Node. Si tu perds la VM Ansible, tu perds le moyen de gérer tout ton LAN d’un coup. Un snapshot hebdomadaire coûte peu et peut te sauver.
Automatise les mises à jour avec cron. Une fois que le playbook de mise à jour tourne bien, planifie-le sur le Control Node :
# Mise à jour tous les dimanches à 3h du matin0 3 * * 0 /usr/bin/ansible-playbook ~/ansible/playbooks/update_all.yml >> /var/log/ansible-updates.log 2>&1Conclusion
Le serveur Ansible sur ESXi devient rapidement indispensable dans un homelab. Ce qui prenait une heure de connexions SSH manuelles se réduit à une commande. Et comme tout est dans des fichiers YAML versionnés, tu sais exactement dans quel état sont tes machines à tout moment.
Pour aller plus loin sur les playbooks, les rôles et les fonctionnalités avancées d’Ansible, consulte l’article Maîtriser les Playbooks Ansible.