Configurer un routeur Turris avec Ansible

J’ai acheté un Turris Mox (via la campagne de crowdfunding en 2018-2019), et ai voulu utiliser Ansible pour rendre sa configuration reproductible, sans la figer pour autant.

Il est probable que ce qui suit soit en grande partie applicable à n’importe quel appareil basé sur OpenWRT.

Pré-requis

Activer le SSH sur le Turris : https://doc.turris.cz/doc/en/howto/ssh

Configurer une authentification par clé SSH pour le user root (avec un simple ssh-copy-id root@192.168.1.1)

Configurer l’hôte dans l’inventaire Ansible : il faut préciser l’interpréteur python (un python 3 est installé par défaut sur Turris OS, mais il faut peut-être l’installer avec opkg sur certains autres appareils OpenWRT)

turris:
  ansible_host: 192.168.1.1
  ansible_user: root
  ansible_python_interpreter: /usr/bin/python

Manipulation des fichiers UCI

La grande majorité de la configuration du routeur est gérée dans des fichiers UCI (dans /etc/config)

Le format de ces fichiers n’est pas bien adapté aux manipulations avec les modules natifs de Ansible (comme lineinfile) car leur structure est bien particulière (et qu’ils sont modifiés par l’interface graphique aussi). Il est facile de copier ces fichiers avec les modules copy ou template, mais cela implique d’écraser les fichiers complets : si on ajoute d’autres options manuellement, et qu’on relance le playbook, les modifications manuelles seront perdues.

Ce que je voulais, c’est pouvoir paramétrer certaines sections, mais sans toucher aux autres sections du fichier UCI.

J’ai commencé en utilisant https://github.com/robinoburka/ansible-uci/. Il fonctionne bien, mais ne permet de modifier qu’une seule option à la fois. Le playbook devient rapidement très verbeux et lourd à maintenir. D’autre part, ce module Ansible ne supporte pas le mode « check », ce qui est vraiment dommage.

Après avoir brièvement envisagé d’utiliser directement la ligne de commande uci, j’ai trouvé une bien meilleure solution : https://github.com/gekmihesg/ansible-openwrt , qui a un module uci qui permet de renseigner plusieurs options à la fois, et supporte le mode check. Cerise sur le gâteau : il accélère largement l’exécution des tâches Ansible.

Il faut mettre l’hôte correspondant au routeur dans un groupe openwrt de l’inventaire Ansible. Et attention à ne pas oublier de lancer un « uci commit » à la fin, pour que toutes les modifications apportées soient enregistrées dans les fichiers uci.

Exemples

Section non nommée

Pour configurer un bail DHCP permanent, ainsi que le nom DNS correspondant, on peut le faire dans l’interface web. Il faut aller dans l’interface LUCI, menu Réseau -> DHCP et DNS -> baux statiques.

Le fichier de configuration correspondant est /etc/config/dhcp (astuce pour le trouver : quand on modifie des choses dans l’interface de LUCI, avant de les enregistrer, il affiche en haut « Changements non appliqués ». Quand on clique dessus, il affiche les commandes uci qu’il souhaite appliquer, ce qui révèle le nom du fichier. Exemple : « uci set dhcp.… »)

Une section de ce fichier a la forme suivante :

config host
        option mac '01:02:03:04:05:06'
        option ip '192.168.1.10'
        option dns '1'
        option name 'mymachine'

Et on peut facilement la produire avec Ansible :

  - name: Configure DHCP and DNS for a machine
    uci:
      command: section
      config: dhcp
      type: host
      find_by:
        mac: '01:02:03:04:05:06'
      value:
        ip: '192.168.1.10'
        dns: '1'
        name: 'mymachine'
    notify: uci commit

  handlers:
  - name: uci commit
    uci:
      command: commit

Section nommée

Quand la section est nommée, on peut la retrouver directement via son nom, plutôt que par la valeur d’une de ses options.

Exemple pour configurer une interface réseau dans /etc/config/network :

config interface 'vpn_turris'
        option proto 'none'
        option ifname 'tun_turris'
        option auto '1'
        option enabled '1'

qui peut être généré par Ansible via :

  - name: Configure vpn_turris network section
    uci:
      command: section
      config: network
      type: interface
      name: vpn_turris
      value:
        proto: 'none'
        ifname: 'tun_turris'
        auto: '1'
        enabled: '1'
    notify: uci commit

Réinitialisation du routeur Turris

Après avoir bien « joué » et bidouillé le routeur, je l’ai réinitialisé (« factory reset »), via la commande suivante en root :

schnapps rollback factory

Au reboot, inutile de cocher des items dans la « package list » du wizard (qui s’affiche si votre appareil a été livré avec une ancienne version de Foris), cela finira en erreur 404. Par contre, on peut le faire plus tard dans l’interface reForis (après l’installation de toutes les mises à jour)

Ensuite on peut réappliquer le playbook Ansible pour retrouver sa config.

Évidemment une alternative aurait été d’utiliser les fonctions proposées par Turris OS (restauration d’une sauvegarde de la config, ou d’un snapshot avec schnapps). Mais Ansible apporte plusieurs avantages : le fait que le playbook documente précisément ce qui a besoin d’être modifié par rapport à une configuration de base, et le mode check qui permet de vérifier si, après plein de bidouilles, on n’a rien modifié sur notre config importante (avec la possibilité de la restaurer en lançant le playbook, sans pour autant écraser le reste)

Une réflexion sur « Configurer un routeur Turris avec Ansible »

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *