Introduction

La sauvegarde régulière des configurations réseau est une bonne pratique essentielle. Perdre la configuration d’un switch peut entraîner des heures de reconfiguration manuelle. Dans cet article, nous allons mettre en place une solution complète et automatisée avec Ansible, systemd et un partage réseau Windows, pour sauvegarder les configurations de vos switches localement et à distance.


Prérequis

  • Ansible installé sur le serveur Linux
  • SSH activé sur les switches
  • Un partage réseau Windows monté (optionnel, pour la sync distante)
  • Les collections Ansible nécessaires selon vos équipements :
    • dellemc.os6
    • arubanetworks.aoscx
    • cisco.ios

1. Préparation de l’environnement

Créer le dossier de destination des sauvegardes :

1
mkdir /home/user1/switch_backups

2. Inventaire des switches

Créer un fichier switches.yml listant tous les équipements à sauvegarder :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
switches:
  - ip: 192.168.1.10
    name: SWITCH01
    os: dellemc.os6.os6
    password: 1!2$3*4@5678
    user: user1
  - ip: 192.168.1.20
    name: SWITCH02
    os: zyxel
    password: 1!2$3*4@5678
    user: user1
  - ip: 192.168.1.30
    name: SWITCH03
    os: arubanetworks.aoscx.aoscx
    password: 1!2$3*4@5678
    user: user1
  - ip: 192.168.1.40
    name: SWITCH04
    os: cisco.ios.ios
    password: 1!2$3*4@5678
    user: user1

⚠️ En production, utilisez Ansible Vault pour chiffrer les mots de passe.


3. Le playbook Ansible

Créer le fichier backup_conf_switches.yml dans votre dossier de projet :

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
---
- hosts: localhost
  gather_facts: no
  vars:
    backup_dir: "/home/user1/switch_backups"
    backup_day: "{{ lookup('pipe', 'date +%Y%m%d') }}"
    backup_time: "{{ lookup('pipe', 'date +%H%M%S') }}"
  vars_files:
    - switches.yml

  tasks:
    - name: Créer le répertoire du jour pour la sauvegarde
      file:
        path: "{{ backup_dir }}/{{ backup_day }}"
        state: directory
        mode: '0755'

    - name: Créer l'inventaire dynamique
      add_host:
        name: "{{ item.name }}"
        groups: switches_to_backup
        ansible_host: "{{ item.ip }}"
        ansible_network_os: "{{ item.os }}"
        ansible_connection: network_cli
        ansible_user: "{{ item.user }}"
        ansible_password: "{{ item.password }}"
        ansible_ssh_common_args: '-o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null'
        backup_dir: "{{ backup_dir }}"
        backup_day: "{{ backup_day }}"
        backup_time: "{{ backup_time }}"
      loop: "{{ switches }}"

- name: Sauvegarder les configurations des switches
  hosts: switches_to_backup
  gather_facts: no
  vars:
    ansible_become: yes
    ansible_become_method: enable

  tasks:
    - name: Récupérer la configuration running
      dellemc.os6.os6_command:
        commands:
          - show running-config
      register: switch_config
      ignore_errors: yes

    - name: Tentative alternative si la première échoue
      dellemc.os6.os6_command:
        commands:
          - show run
      register: switch_config_alt
      when: switch_config is failed
      ignore_errors: yes

    - name: Déterminer quelle configuration utiliser
      set_fact:
        final_config: "{{ switch_config.stdout[0] if switch_config is success
                          else (switch_config_alt.stdout[0] if switch_config_alt is success else '') }}"

    - name: Sauvegarder la configuration sur le disque
      copy:
        content: "{{ final_config }}"
        dest: "{{ backup_dir }}/{{ backup_day }}/{{ inventory_hostname }}_{{ backup_day }}_{{ backup_time }}_config.txt"
      delegate_to: localhost
      when: final_config | length > 0

    - name: Confirmer la sauvegarde
      debug:
        msg: "✅ {{ inventory_hostname }} sauvegardé"
      when: final_config | length > 0

    - name: Signaler les erreurs
      debug:
        msg: "❌ {{ inventory_hostname }}: impossible de récupérer la configuration"
      when: final_config | length == 0

- name: Rapport final
  hosts: localhost
  gather_facts: no
  vars:
    backup_dir: "/home/user1/switch_backups"
    backup_day: "{{ lookup('pipe', 'date +%Y%m%d') }}"

  tasks:
    - name: Lister les fichiers créés
      find:
        paths: "{{ backup_dir }}/{{ backup_day }}"
        patterns: "*_config.txt"
      register: backup_files

    - name: Afficher le résumé
      debug:
        msg:
          - "=========================================="
          - "📁 Sauvegarde du jour : {{ backup_day }}"
          - "✅ Configurations : {{ backup_files.matched }}"
          - "📂 Dossier : {{ backup_dir }}/{{ backup_day }}"
          - "=========================================="

    - name: Créer ou mettre à jour le journal
      lineinfile:
        path: "{{ backup_dir }}/backup_log.txt"
        line: "{{ backup_day }} - {{ backup_files.matched }} switch(es) sauvegardé(s)"
        create: yes
        mode: '0644'

Le playbook fonctionne en trois phases :

  1. Phase localhost — création du répertoire horodaté et génération de l’inventaire dynamique à partir du fichier switches.yml
  2. Phase switches — connexion SSH à chaque équipement, récupération du running-config avec fallback, et écriture locale du fichier texte
  3. Phase rapport — comptage des fichiers créés et mise à jour d’un journal de bord

4. Le service systemd

Créer /etc/systemd/system/backup-switches.service :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
# /etc/systemd/system/backup-switches.service
[Unit]
Description=Sauvegarde Ansible des configurations switches
After=network-online.target

[Service]
Type=oneshot
User=admin01
WorkingDirectory=/home/user1/netbox_ansible
ExecStart=/home/admin01/netbox_ansible/venv/bin/ansible-playbook backup_conf_switches.yml -vvv
StandardOutput=journal
StandardError=journal

[Install]
WantedBy=multi-user.target

Un service Type=oneshot s’exécute une seule fois puis s’arrête — c’est parfaitement adapté à une tâche planifiée. Il ne faut surtout pas l’activer directement avec enable seul, mais l’associer à un timer.


5. Le timer systemd

C’est le timer qui déclenche le service de façon planifiée. Créer /etc/systemd/system/backup-switches.timer :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
# /etc/systemd/system/backup-switches.timer
[Unit]
Description=Lancement mensuel du backup des switches

[Timer]
# Déclenchement le 1er de chaque mois à 05h00
OnCalendar=*-*-01 05:00:00
# Rattraper un déclenchement manqué si le serveur était éteint
Persistent=true

[Install]
WantedBy=timers.target

Activer et démarrer le timer

1
2
3
4
5
# Recharger la configuration systemd
sudo systemctl daemon-reload

# Activer et démarrer le TIMER (pas le service directement)
sudo systemctl enable --now backup-switches.timer

Vérifications utiles

1
2
3
4
5
6
7
8
# Voir quand le prochain déclenchement aura lieu
systemctl list-timers backup-switches.timer

# Consulter les logs d'exécution
journalctl -u backup-switches.service -f

# Tester manuellement le service
sudo systemctl start backup-switches.service

6. Synchronisation vers un partage réseau (optionnel)

Si vous souhaitez synchroniser les sauvegardes vers un partage Windows (SMB), ajoutez un rsync-switches.service et son timer associé, en ciblant le point de montage :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
# /etc/systemd/system/rsync-switches.service
[Unit]
Description=Backup local et distant des configurations switches
After=network-online.target
Requires=mnt-windows_share.automount
After=mnt-windows_share.automount

[Service]
Type=oneshot
User=toto
WorkingDirectory=/home/toto/ansible
ExecStart=/bin/bash /home/toto/ansible/backup_wrapper.sh
StandardOutput=journal
StandardError=journal

[Install]
WantedBy=multi-user.target

Avec son timer pour une exécution toutes les 6 heures :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
# /etc/systemd/system/rsync-switches.timer
[Unit]
Description=Timer pour sync des configs switches vers partage réseau

[Timer]
OnBootSec=5min
OnUnitActiveSec=6h
Persistent=true
Unit=rsync-switches.service

[Install]
WantedBy=timers.target
1
2
sudo systemctl daemon-reload
sudo systemctl enable --now rsync-switches.timer

Récapitulatif de l’architecture

Composant Rôle
switches.yml Inventaire des équipements
backup_conf_switches.yml Playbook Ansible de sauvegarde
backup-switches.service Exécute le playbook (oneshot)
backup-switches.timer Planifie l’exécution (1er du mois à 5h)
rsync-switches.service Synchronise vers le partage réseau
rsync-switches.timer Planifie la sync (toutes les 6h)

Conclusion

Cette solution combine la puissance d’Ansible pour l’automatisation réseau multi-constructeur avec la fiabilité de systemd pour la planification. Les points forts :

  • Multi-constructeur : Dell, Zyxel, Aruba, Cisco supportés nativement
  • Résilience : fallback automatique en cas d’échec de commande, Persistent=true pour rattraper les exécutions manquées
  • Traçabilité : journal horodaté, logs systemd consultables avec journalctl
  • Extensible : ajout d’un switch = une ligne dans switches.yml