Ansible — Setup, bonnes pratiques & déploiement Nginx

De 0 → prod : structure, inventaire, playbooks, Vault, idempotence, CI/CD & dépannage.

Debian/Ubuntu SSH Idempotence Vault Roles CI/CD

🧭 0) Objectif & rôle d’Ansible

Ansible est un outil d’automatisation open‑source permettant de déployer, configurer et maintenir des serveurs de manière déclarative et reproductible, sans agent sur les machines (SSH + Python).

En pratique : une seule commande Ansible installe Nginx, copie les fichiers du site, active le vhost, génère le certificat Let’s Encrypt et vérifie la conformité — le tout sans SSH manuel.

1) Installation & prérequis

Contrôleur (poste d'admin)
# Debian/Ubuntu
sudo apt update
sudo apt install -y ansible sshpass python3-venv

# (optionnel) environnement virtuel
python3 -m venv .venv && source .venv/bin/activate
pip install --upgrade pip ansible ansible-lint
Cibles (gérés par Ansible)
# Linux: Python doit être dispo (souvent déjà présent)
# SSH activé, clé publique copiée :
ssh-copy-id debian@vps.example

Windows (option) : WinRM à configurer (non couvert ici).

2) Arborescence recommandée

ansible/
├─ ansible.cfg
├─ inventories/
│  ├─ prod/
│  │  ├─ hosts.ini
│  │  ├─ group_vars/
│  │  │  └─ all.yml
│  │  └─ host_vars/
│  │     └─ vps-ovh.yml
├─ roles/
│  ├─ common/
│  │  ├─ tasks/main.yml
│  │  └─ files/ ...
│  └─ nginx_site/
│     ├─ tasks/main.yml
│     ├─ templates/site.conf.j2
│     └─ files/site/ (index.html, assets/...)
├─ playbooks/
│  ├─ site.yml
│  └─ check.yml
└─ vault/
   └─ secrets.yml (chiffré)

3) Configuration de base

ansible.cfg
[defaults]
inventory = inventories/prod/hosts.ini
interpreter_python = auto
host_key_checking = False
stdout_callback = yaml
timeout = 30
remote_user = debian
retry_files_enabled = False

[privilege_escalation]
become = True
become_method = sudo
become_ask_pass = False
inventaire (hosts.ini)
[web]
vps-ovh ansible_host=51.210.181.58

[web:vars]
ansible_user=debian
ansible_become=true
site_root=/var/www/nico-cv
server_name=nicolas-sapin.fr www.nicolas-sapin.fr

4) Variables & Vault

group_vars/all.yml
nginx_packages:
  - nginx
  - certbot
  - python3-certbot-nginx

tls_email: "admin@nicolas-sapin.fr"
cache_max_age: 2592000  # 30j

# (ex) mot de passe sudo si nécessaire (utiliser Vault)
# ansible_become_password: !vault |
#   $ANSIBLE_VAULT;1.1;AES256;[...]
Vault (chiffrage)
# créer le fichier chiffré
ansible-vault create vault/secrets.yml

# éditer plus tard
ansible-vault edit vault/secrets.yml

# utiliser dans un play:
# vars_files:
#   - ../vault/secrets.yml

# exécution : ajouter --ask-vault-pass ou --vault-password-file

5) Rôle nginx_site (site statique + HTTPS)

Ce rôle installe Nginx, déploie le contenu du site, crée le vhost, puis active le HTTPS via Certbot.

tasks/main.yml
---
- name: Packages requis
  apt:
    name: "{{ nginx_packages }}"
    state: present
    update_cache: true

- name: Créer le dossier site
  file:
    path: "{{ site_root }}"
    state: directory
    owner: www-data
    group: www-data
    mode: "0755"

- name: Déployer le contenu (HTML/CSS/JS)
  copy:
    src: "files/site/"
    dest: "{{ site_root }}/"
    owner: www-data
    group: www-data
    mode: "0644"
  notify: Reload nginx

- name: Vhost HTTP (temporaire)
  template:
    src: "templates/site.conf.j2"
    dest: "/etc/nginx/sites-available/nicolas-sapin.fr"
    owner: root
    group: root
    mode: "0644"

- name: Activer vhost
  file:
    src: "/etc/nginx/sites-available/nicolas-sapin.fr"
    dest: "/etc/nginx/sites-enabled/nicolas-sapin.fr"
    state: link
  notify: Reload nginx

- name: Vérifier conf Nginx
  command: nginx -t
  register: nginx_test
  changed_when: false
  failed_when: nginx_test.rc != 0

- name: Certbot — émettre/renouveler
  command: >
    certbot --nginx -d {{ server_name | replace(' ', ' -d ') }} -m {{ tls_email }} --agree-tos --no-eff-email
  args:
    creates: "/etc/letsencrypt/live/{{ (server_name.split(' '))[0] }}/fullchain.pem"

handlers:
  - name: Reload nginx
    service:
      name: nginx
      state: reloaded
templates/site.conf.j2
server {
  listen 80;
  listen [::]:80;
  server_name {{ server_name }};
  root {{ site_root }};
  index index.html;

  location / {
    try_files $uri $uri/ =404;
  }

  location ~* \.(?:css|js|png|jpg|jpeg|gif|ico|svg|webp|pdf|woff2?)$ {
    expires 30d;
    add_header Cache-Control "public, max-age={{ cache_max_age }}, immutable";
    try_files $uri =404;
  }

  access_log /var/log/nginx/nicolas-sapin_access.log;
  error_log  /var/log/nginx/nicolas-sapin_error.log;
}

6) Playbooks

playbooks/site.yml
---
- name: Déployer le site CV sur Nginx (HTTPS)
  hosts: web
  become: true
  vars_files:
    - ../vault/secrets.yml
  roles:
    - nginx_site
playbooks/check.yml (dry-run)
---
- name: Vérifier les changements potentiels
  hosts: web
  gather_facts: false
  tasks:
    - name: Ping
      ping:
# Dry-run global :
ansible-playbook playbooks/site.yml --check --diff

# Limiter :
ansible-playbook playbooks/site.yml --limit vps-ovh --tags nginx

# Exécuter réellement :
ansible-playbook playbooks/site.yml

7) Bonnes pratiques

8) Dépannage

← Retour aux réalisations
Ansible Nginx Let’s Encrypt