Je configure macOS avec Ansible !

Je configure macOS avec Ansible !

Cet article a été mis à jour le 21 mars 2024, j'ai retravaillé le playbook et les rôles associés pour macOS Sonoma. De plus, j'ai ajouté quelques sections au sein de l'article pour étoffer le contenu et expliquer plus en profondeur certains concepts.

Introduction

La fin du mois de Mars est synonyme de passage au printemps, l'occasion de réaliser un grand nettoyage dans ses machines voire de réinstaller son système d'exploitation.

Dans cet article, je vais vous présenter ma méthode d'installation de macOS, plus particulièrement sur la dernière version en date : Sonoma.

Au quotidien, j'essaye d'automatiser le plus possible de choses, c'est aussi le cas pour mon ordinateur portable qui se configure avec l'outil le plus approprié pour ça : Ansible.

En effet, Ansible permet de définir un ensemble de tâches à exécuter pour installer, mettre à jour ou configurer plusieurs outils et logiciels présents au sein d'un système d'exploitation.

Bien évidemment, je vais vous détailler l'ensemble des rôles que j'ai conçu pour faciliter la configuration de macOS.

Mais avant, on va s'intéresser à la manière de personnaliser ce système d'exploitation.

Configurer macOS

Installation de paquets

Quand on parle installation sur macOS, il est difficile de ne pas mentionner Homebrew, qui comble un manque assez important sur ce système d'exploitation : disposer d'un gestionnaire de paquets et de dépendances.

Cela permet d'installer de simples binaires comme ansible (formulae) ou des applications avec une interface graphique comme firefox (casks).

La ligne de commande brew permet de totalement éviter les installations mannuelles et propose de mettre à jour d'un seul trait l'ensemble de votre système.

Pour ce qui est du Mac App Store, la commande mas permet d'installer via un identifiant sous forme d'une suite de chiffres, les applications désirées.

Fichiers de configuration

Comme vous le savez, macOS est un système propriétaire ce qui rend parfois la tâche plus compliquée pour automatiser certains paramètres ou fonctionnalités.

Néanmoins, il est possible de passer par des outils en ligne de commande pour réaliser des modifications. Ces outils permettent de mettre à jour des fichiers .plist qui contiennent la configuration d'une application.

Ce format de fichier n'est pas propre à macOS, mais se retrouve aussi dans iOS, iPadOS ainsi que l'ensemble des systèmes propres à Apple.

Côté structure, c'est un XML composé d'une multitude de couples clé / valeur, sachant que la valeur est forcément typée.

Par exemple, pour modifier des paramètres au sein du Finder, vous devrez passer par le fichier com.apple.finder.plist.

Ces fichiers .plist sont des binaires que vous pouvez lire avec l'utilitaire plutil comme cela : plutil -p file.plist.

De plus, et comme dit plus haut, macOS fournit deux outils en lignes de commande pour les manipuler :

  • La première commande defaults, assez complète permet de réaliser des ajouts, modifications et suppressions au sein de ces fichiers ;
  • La seconde commande /usr/libexec/PlistBuddy donne les mêmes possibilités que la première via une syntaxe moins facile à prendre en main mais qui offre plus de choix pour gérer de multiples valeurs au sein des fichiers.

Maintenant, comment tout ça se met en place du côté d'Ansible ?

Ansible et macOS

Sans vous représentez une énième fois Ansible, cet outil offre un catalogue assez large de modules au sein des différentes tâches définies.

Première étape, l'installation des formulae et casks, Ansible dispose de modules comme community.general.homebrew et community.general.homebrew_cask qui sont suffisamment paramétrables pour convenir à mon usage.

Il est même possible, pour les dépôts externes (taps) de les référencer dans le module community.general.homebrew_tap, ce qui offre un large choix de possibilité !

Pour la configuration du système, il est recommandé d'utiliser le module community.general.osx_defaults pour réaliser les opérations de la commande defaults. En revanche, pour PlistBuddy, il n'existe pas à ce jour de module, j'ai donc utilisé le bon vieux ansible.builtin.shell avec quelques vérifications en amont pour assurer la résilience du résultat.

Le playbook

Avant de commencer

Vous trouverez mon dépôt de code à cette adresse sur GitHub :

https://github.com/axinorm/macbook-setup

Je vous invite à le cloner et à ajuster les paramètres du fichier mymac.yml en fonction de vos besoins.

De plus, je vous invite à tester l'exécution de ce playbook sur une machine virtuelle avant de le réaliser sur votre propre système pour éviter les déconvenues.

Les rôles

Au sein du playbook, plusieurs rôles ont été définis pour séparer et rendre la configuration évolutive :

  • preflight : Étape préliminaire qui vérifie que l'application des paramètres du système (System Settings) est bien fermée. Le cas contraire pourrait interférer dans la modification de certains paramètres ;

  • hostname : Modification du nom de la machine ainsi que son nom réseau ;

  • homebrew : Installation des taps, formulae et casks à l'aide des modules associés à Homebrew ;

  • appstore : Installation de logiciels au sein de l'App Store. Pour le bon fonctionnement de ce rôle, vous devez être connecté avec votre Apple ID ;

  • zsh : Configuration de zsh et des plugins. Ce rôle ajoute Oh My Zsh pour plus de personnalisation ainsi que le thème powerlevel10k ;

  • tmux : Configuration de tmux et installation des plugins sans oublier tous les scripts de personnalisation associés ;

  • vim : Configuration basique de Vim ;

  • iterm2 : Installation et configuration de d'iTerm2 : modification de quelques réglages et ajout d'un thème ;

  • vscodium : Installation de VSCodium et des extensions définies ;

  • macos_settings : Configuration du système et de la plupart des applications installées avec macOS. Ce rôle se compose de sous catégories :

    • configure_settings.yml : Modification des valeurs par défaut et suppression du son au lancement de macOS ;
    • configure_systemuiserver.yml : Modification des valeurs par défaut ;
    • configure_clock.yml : Paramétrage de l'horloge en haut à droite de l'écran ;
    • configure_dock.yml : Modification des valeurs par défaut et configuration des applications présentes dans le Dock ;
    • configure_finder.yml : Modification des valeurs par défaut, mise à jour de la visibilité des dossiers et suppression des tags ;
    • configure_safari.yml et configure_textedit.yml : Modification des valeurs par défaut pour Safari et TextEdit ;
    • configure_network.yml : Configuration des DNS pour les interfaces définies ;
    • configure_others.yml : Modification des valeurs par défaut pour les paramètres qui ne sont pas définis plus haut et configuration de Night Shift avec l'outil nightlight.

Si vous voulez en savoir plus sur tmux, j'avais réalisé un article qui explique les fonctionnalités et la configuration de l'outil. Vous pouvez le retrouver ici.

À noter que ces rôles ont été testés sur macOS Sonoma et ne sont peut être pas adapté aux autres versions. Notamment car ce macOS a modifié plusieurs structures au sein des fichiers .plist de différents services.

Inventaire et variables

Pour vous faciliter la vie, un inventaire a déjà été défini dans inventory/hosts, pointant sur le localhost qui est le macOS cible à configurer.

Par défaut un groupe mymac est paramétré, aussi bien dans l'inventaire que dans le dossier inventory/group_vars sous le nom de mymac.yml avec quelques valeurs en guise d'exemple.

Les goûts et les couleurs ne sont pas forcément les mêmes pour tous, je vous recommande d'y jeter un œil attentif et de personnaliser vos réglages.

Voici quelques exemples pour définir des formulae et casks au sein d'Homebrew :

homebrew:
  taps: []

  formulae:
    - ansible
    - ansible-lint

[...]

  casks:
    - firefox
    - iina
    - vscodium

De même, pour configurer le Finder, vous pouvez modifier la variable finder.defaults pour configurer le fichier .plist :

finder:
  defaults:
    - { name: Allow quitting via ⌘ + Q; doing so will also hide desktop icons, key: QuitMenuItem, type: bool, value: true }
    - { name: Show hidden files, key: AppleShowAllFiles, type: bool, value: true }
    - { name: Show status bar, key: ShowStatusBar, type: bool, value: true }
    - { name: Show path bar, key: ShowPathbar, type: bool, value: true }
    - { name: Use list view in all Finder windows by default, key: FXPreferredViewStyle, type: string, value: Nlsv }
    - { name: Keep folders on top when sorting by name, key: _FXSortFoldersFirst, type: bool, value: true }
    - { name: When performing a search, search the current folder by default, key: FXDefaultSearchScope, type: string, value: SCcf }
[...]

Installation

Avant de commencer à exécuter le playbook setup.yml, assurez-vous d'avoir suivi la section du dessus pour configurer votre inventaire.

De plus, sur un système vierge, certains outils sont indispensables au bon fonctionnement du playbook. Vous pouvez les retrouver dans le script setup.sh.

Cette histoire de la poule et de l'œuf, encore et toujours !

Voici le cheminement de ce script :

  • Installation des Command Line Tools de macOS :

    xcode-select --install

  • Mise en place du gestionnaire de paquets Homebrew :

    /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"

  • Installation et configuration d'Ansible :

    brew install ansible

  • Création d'un dossier pour le code Git :

    mkdir -p ~/dev

  • Clonage du dépôt de code, cette partie est à adapter en fonction de vos besoins :

    git clone https://github.com/axinorm/macbook-setup ~/dev/macbook-setup

Tout semble bon pour passer au lancement du playbook !

Lancement du playbook

Avant de lancer le playbook, une dernière petite chose est à configurer. En effet pour accéder à certaines propriétés, l'application qui exécute le playbook a besoin d'avoir accès au disque complet.

Pour cela, vous pouvez ajouter l'application Terminal dans `Privacy & Security>Full Disk Access`` au sein des paramètres systèmes (System Settings).

Pour exécuter le playbook, rien de plus simple :

ansible-playbook setup.yml --inventory inventory/hosts --ask-become-pass

Le paramètre --ask-become-pass est indispensable car certaines des tâches jouées par Ansible demandent des privilèges élevés.

Une fois le playbook terminé, je vous conseille de redémarrer votre mac pour finaliser l'installation !

Conclusion

Comme vous pouvez le voir, réaliser un playbook d'installation est relativement facile. La plus grosse tâche reste de fouiller dans les réglages et dans les fichiers .plist à la recherche de la valeur qui vous correspond. Sans oublier de réaliser une série de tests pour voir si le résultat correspond à vos attentes.

De mon côté, à chaque version majeure de macOS, j'en profite pour refaire une installation propre en passant par ce playbook que je tiens à jour au fil des versions.

Comme dit plus haut, n'hésitez pas à vous servir de cet extrait de code comme une base pour l'installation de votre système d'exploitation.

J'espère en tout cas que ces quelques lignes de code vous seront bien utiles tout en vous faisant économiser du temps !