etckeeper est un système conçu pour suivre la configuration d'une machine (répertoire /etc, d'où le nom) à l'aide d'un gestionnaire de versions (par exemple Git). On doit donc enregistrer manuellement chacune des modifications que l'on fait sur le système, en y ajoutant un message les décrivant.

etckeeper a été conçu par Joey Hess, développeur Debian émérite, et est donc pensé pour s'intégrer à Debian : les modifications liés à l'installation ou à la suppression d'un paquet sont enregistrées automatiquement. Ce mécanisme permet de connaître très rapidement les modifications qui ont été faites par rapport à la configuration originale des paquets installés.

Principes de fonctionnement

etckeeper est assez simple et sert surtout à compenser les limitations inhérentes aux gestionnaires de versions existants. Aucun n'est en effet capable de gérer tout à fait comme il le faudrait les permissions, les fichiers spéciaux ou les répertoires vides.

etckeeper maintient donc pour cela un fichier spécial dans le dépôt[^dépôt] nommé .etckeeper. Ce dernier est un simple script shell dont les commandes effectueront les ajustements nécessaires par rapport à ce qui est normalement enregistré par le gestionnaires de versions. etckeeper s'assure qu'il soit exécuté lorsque c'est nécessaire.

[^dépôt]: Dans le langage des gestionnaires de versions, un dépôt est l'endroit où l'on enregistre l'ensemble des données et leur histoire.

Pour plus de détails, voir le README (en anglais).

Utilisation pour Grenode

Enregistrement des modifications

L'enregistrement des modifications de configuration n'est pas automatique. Sauf lors de l'installation et de la supression d'un paquet. Chaque personne doit enregistrer ses changements avec la commande :

    $ etckeeper commit

À chaque enregistrement est associé un message (nommé commitlog) décrivant les modifications. Idéalement, il faut que ce message soit le plus complet possible sur les modifications qui auront été faites. C'est donc bien de prendre des notes lorsqu'on travaille sur des changements de configuration pour ensuite pouvoir les recopier dans le commitlog.

Afin de ne pas mélanger les fichiers de configuration de nouveaux paquets, et les modifications que l'on y fait, on configure etckeeper de façon à ce qu'il empêche l'installation de nouveaux paquets tant qu'il existe des modifications n'ayant pas été enregistrées.

Autre détail : on peut ajouter à la configuration de vim un script ressemblant à celui de madcoder pour avoir accès plus facilement à des informations supplémentaires lorsqu'on rédige le commitlog. Le script donné en exemple affiche un diff complet et non pas seulement la liste des fichiers modifiés.

Pour ne pas oublier de le faire

Afin de ne pas oublier d'enregistrer nos modifications, un script a été ajouté à nos shells qui nous empêche de fermer la session tant qu'on ne l'a pas fait :

    xita:/etc$ exit
    exit
    Uncommitted changes to /etc found, please commit them

Vu que ceci n'empêche pas de débrancher son câble réseau, un cron est aussi en place pour rappeler (par mail) de faire les enregistrements. Ce rappel est envoyé une heure après la dernière modification n'ayant pas été enregistré.

Être prévenu des changements

Un clone du dépôt git est situé dans /var/backups/etc.git. À chaque synchronisation, un email sera envoyé avec le résumé des nouvelles modifications enregistrées.

Cette synchronisation aura lieu une heure après le dernier enregistrement afin de ne pas recevoir de trop nombreux emails.

Repliquer la même configuration sur plusieurs machines

Il est possible d'importer la configuration d'une autre machine en temps que « branche » dans le dépôt de la machine sur laquelle on travaille. Il devient alors assez simple de répliquer des changements via git diff, git merge ou git cherry-pick (une fois qu'on en a pris l'habitude).

Étudier l'histoire des modifications

Il est possible d'utiliser toutes les commandes de git pour faire des cherche dans l'historique des modifications : git blame, git log, et bien d'autres.

Installation/Configuration

Cette configuration est pensée pour etckeeper à partir de la version 0.22.

Pour utiliser etckeeper en provenance de squeeze, il faut ajout le dépôt dans /etc/apt/sources.list et mettre dans /etc/apt/preferences :

Package: *
Pin: release testing
Pin-Priority: 200

Package: etckeeper
Pin: release testing
Pin-Priority: 999

Paquets necessaires

aptitude install etckeeper git-core heirloom-mailx curl

heirloom-mailx est nécessaire pour que les emails envoyés par nos scripts puissent comporter de jolis accents.

Configuration

Dans /etc/etckeeper/etckeeper.conf, il faut mettre :

AVOID_COMMIT_BEFORE_INSTALL=1
AVOID_DAILY_AUTOCOMMITS=1

Le reste de la configuration doit être correcte avec les réglages par défaut.

Installation de nos scripts

cd /etc/etckeeper/init.d
BASE_URL="https://www.grenode.net/Documentation_technique/Divers/etckeeper"
sudo curl --user $USER -O $BASE_URL/30initial-package-list
sudo chmod +x 30initial-package-list

cd /etc/etckeeper/post-install.d
sudo curl --user $USER -O $BASE_URL/10refresh-package-list
sudo chmod +x 10refresh-package-list

cd /etc/etckeeper
sudo curl --user $USER -O $BASE_URL/bashrc
sudo sh -c '(echo "" ; echo ". /etc/etckeeper/bashrc") >> /etc/bash.bashrc'

cd /etc/cron.hourly
sudo curl --user $USER -O $BASE_URL/etckeeper-warn-changes
sudo chmod +x etckeeper-warn-changes

Ensuite, il faut modifier /etc/profile pour y ajouter à la fin :

sudo sh -c 'cat >> /etc/profile <<EOF

# if running bash
if [ -n "\$BASH_VERSION" ]; then
  # include .bashrc if it exists
  if [ -f /etc/bash.bashrc ]; then
    . /etc/bash.bashrc
  fi
fi
EOF
'

Celà permet de s'assurer que /etc/bash.bashrc soit pris en compte également pour les shells dit « de login ».

Pour bénéficier d'un avertissement dans le prompt, il est aussi nécessaire d'ajouter dans /etc/skel/.bashrc (ou ~/.bashrc pour les comptes déjà créé). Attention il le mettre avant le unset de color_prompt :

if [ "\$color_prompt" = yes ]; then
    set_etckeeper_prompt_color
else
    set_etckeeper_prompt
fi

Pour que ce dernier script fonctionne bien, vu qu'il appelle etckeeper à l'aide de sudo, il est nécessaire de mettre dans /etc/sudoers quelque chose comme :

%sudo ALL=(ALL:ALL) NOPASSWD: /usr/bin/etckeeper unclean

Ainsi qu'au début :

Defaults       env_keep += "GIT_AUTHOR_NAME GIT_AUTHOR_EMAIL"

Création du dépot git

cd /etc
sudo etckeeper init
sudo etckeeper commit 'Initial commit'
sudo git gc

La commande etckeeper init initialise le dépot /etc/.git/. Cette commande crée un .gitignore si il n'existe pas.

L'exécution de etckeeper commit ajoutera tous les fichiers dans /etc qui ne sont pas ignorés par git. Les ajustements nécessaires se font dans /etc/.gitignore.

Lancer git gc permet de compacter le dépôt git afin d'en accélerer les utilisations futurs.

Détails de nos scripts

  • /etc/etckeeper/bashrc est un script qui doit être « sourcé » dans /etc/bash.bashrc et qui empêche de fermer son shell lorsqu'il existe des modifications qui n'ont pas été enregistrées.

    Source

  • /etc/cron.hourly/etckeeper-warn-changes est le script qui envoie les emails de rappel si des modifications n'ont pas été enregistrées. C'est également lui qui configure et synchronise le dépôt de sauvegarde.

  • Afin de garder trace de toutes les installations/suppressions de paquets Debian (même ceux qui n'installent rien dans /etc), on a également deux petits scripts qui s'ajoute aux hooks d'etckeeper :

    Ces derniers vont tout simplement écrire un fichier /etc/.package-list qui sera mis dans le dépôt au même titre que les autres fichiers de configuration. Sa modification par le script 10refresh-package-list entraînera donc systématiquement un changement, et ce dernier sera enregistré par /etc/etckeeper/post-install.d/50vcs-commit.

    Ces scripts ont été envoyés sur le bug #519420, histoire que ça puisse profiter à d'autres gens.

Astuces

  • Voir les modifications de permissions ou des uid/gid : les modifs sont enregistrées dans .etckeeper
  • Ne pas prendre en compte des fichiers modifiés automatiquement : on peut enlever les fichiers du dépot git. Par exemple pour enlever le fichier printcap :

       $ git rm --cached printcap # modified by CUPS
       $ echo printcap >> .gitignore
       $ git commit -a -m "don't track printcap"
    
  • Voir le résumé des deux dernières modifications :

       $ git whatchanged -2
    
  • Voir la liste de tous les changements effectués depuis deux semaines :

       $ git log --since="2 weeks ago"