Keep track of Linux configuration changes with etckeeper

version_historyThe configuration of a linux server will change over time. Keeping track of the changes of all the configuration files can be a challenge. etckeeper is a utility that makes this easy.

With the help of etckeeper, the complete /etc/ directory is placed under version control. It supports many different version control systems like git, mercurial and more. For this setup I will use git as the repository for etckeeper. To install etckeeper and git from the yum repository, run the following command.

$ yum install etckeeper git

After the packages are installed, you can edit the /etc/etckeeper/etckeeper.conf file to define the “VCS” (Version Control System). By default, git is configured as the VCS. With the package from the repository, the configuration for the package manager is also already pre-configured.

To get the /etc/ directory under version control, the next step is to initialize the repository for etckeeper. This is done by running etckeeper with the “init” argument.

$ etckeeper init
Initialized empty Git repository in /etc/.git/

This will, as the output shows, initialise the git repository inside the /etc/ directory. To commit the initial version of all the configuration files, run the following command. The last parameter contains the git commit message (where you can include whatever description you like).

$ etckeeper commit "commit initial version of files"

You might notice in the /etc/ directory a file called /etc/.etckeeper which contains detailed information about the files etckeeper is managing in the repository. As git does not care about file owners or file permissions, etckeeper stores this extra information in this file, which is also committed to its repository.

Integration into the system

Etckeeper will automatically integrate into the package manager of your system while installing. This allows it to run before and after packages are installed or updated. As shown in the example yum output below, etckeeper integrates into the package manager and will execute a “pre transaction commit” as well as a “post transaction commit” while installing new packages.

$ yum install htop
Loaded plugins: etckeeper, fastestmirror, priorities
Loading mirror speeds from cached hostfile
 * Webmin: download.webmin.com
 * base: mirror.rackspace.com
 * epel: dl.fedoraproject.org
 * extras: mirror.hmc.edu
 * rpmforge: mirror.webnx.com
 * updates: dallas.tx.mirror.xygenhosting.com
4 packages excluded due to repository priority protections
Setting up Install Process
Resolving Dependencies
--> Running transaction check
---> Package htop.x86_64 0:1.0.3-1.el6.rf will be installed
--> Finished Dependency Resolution

Dependencies Resolved

================================================================================
 Package                  Arch        Version             Repository        Size
================================================================================
Installing:
 htop                    x86_64       1.0.3-1.el6.rf      rpmforge          87 k

Transaction Summary
================================================================================
Install       1 Package(s)

Total download size: 87 k
Installed size: 209 k
Is this ok [y/N]: y
Downloading Packages:
htop-1.0.3-1.el6.rf.x86_64.rpm                           |  87 kB     00:00     
Running rpm_check_debug
Running Transaction Test
Transaction Test Succeeded
Running Transaction
etckeeper: pre transaction commit
[master e67e756] saving uncommitted changes in /etc prior to yum run
 16 files changed, 24 insertions(+), 3 deletions(-)
  Installing : htop-1.0.3-1.el6.rf.x86_64                                   1/1 
etckeeper: post transaction commit
  Verifying  : htop-1.0.3-1.el6.rf.x86_64                                   1/1 

Installed:
  htop.x86_64 0:1.0.3-1.el6.rf                                                  

Complete!

This will ensure one commit before the packages have installed as well as one after the installation. With this in place, there will be a copy of any configuration file installed to /etc/ from the package. This can be useful if you ever need to revert the configuration to its default state.

The commit messages you will find in the repository will look like the following two.

   saving uncommitted changes in /etc prior to yum run
   committing changes in /etc after yum run

Depending on the package you install and the state of the repository, you might have only one commit as in the example yum output above. As the tool “htop” does not change the /etc/ directory, there will be no commit after the yum run. If the /etc/ directory had been not modified before the yum run, there will even not be a commit from before the package was installed.

Add a remote git repository

To keep a copy of the files etckeeper is managing in a remote location, you can add a remote repository to the local git repository. This is not done through etckeeper but through the following git command.

Change to the /etc/ directory and execute the following command to add a remote to the git repository. The second command shows the remote has been added.

$ git remote add origin ssh://git@repo.example.com:1234/etckeeper-repository-name.git
$ git remote -v
origin	ssh://git@repo.example.com:1234/etckeeper-repository-name.git (fetch)
origin	ssh://git@repo.example.com:1234/etckeeper-repository-name.git (push)

As shown in the output above, the remote that was added is called “origin” as specified. etckeeper is able to push the changes to the remote every time something is committed. To let etckeeper know you want to do this, edit the etckeeper configuration file and define the remote name.

$ vim /etc/etckeeper/etckeeper.conf

Change the setting shown below to the name of the remote you specified when adding the remote.

PUSH_REMOTE="origin"

Now when yum is run and files are changed in the /etc/ directory, etckeeper will show output like this. The output shows how etckeeper commits the changes to the local repository and then pushes them to the remote repository.

$ yum install smartmontools
Loaded plugins: etckeeper, fastestmirror, priorities
Loading mirror speeds from cached hostfile
 * Webmin: download.webmin.com
 * base: mirror.rackspace.com
 * epel: dl.fedoraproject.org
 * extras: mirror.hmc.edu
 * rpmforge: mirror.webnx.com
 * updates: dallas.tx.mirror.xygenhosting.com
2 packages excluded due to repository priority protections
Setting up Install Process
Resolving Dependencies
--> Running transaction check
---> Package smartmontools.i686 1:5.43-1.el6 will be installed
--> Finished Dependency Resolution

Dependencies Resolved

================================================================================
 Package                   Arch        Version            Repository        Size
================================================================================
Installing:
 smartmontools             i686        1:5.43-1.el6       base             395 k

Transaction Summary
================================================================================
Install       1 Package(s)

Total download size: 395 k
Installed size: 1.3 M
Is this ok [y/N]: y
Downloading Packages:
smartmontools-5.43-1.el6.i686.rpm                        | 395 kB     00:00     
Running rpm_check_debug
Running Transaction Test
Transaction Test Succeeded
Running Transaction
etckeeper: pre transaction commit
[master 467c74e] saving uncommitted changes in /etc prior to yum run
 Author: username <username@example.com>
 18 files changed, 2351 insertions(+), 3 deletions(-)
Counting objects: 48, done.
Delta compression using up to 2 threads.
Compressing objects: 100% (24/24), done.
Writing objects: 100% (25/25), 11.71 KiB, done.
Total 25 (delta 20), reused 0 (delta 0)
To ssh://git@repo.example.com:1234/etckeeper-repository-name.git
   a1a75ec..467c74e  master -> master
  Installing : 1:smartmontools-5.43-1.el6.i686                              1/1 
etckeeper: post transaction commit
Counting objects: 27, done.
Delta compression using up to 2 threads.
Compressing objects: 100% (15/15), done.
Writing objects: 100% (16/16), 5.53 KiB, done.
Total 16 (delta 10), reused 0 (delta 0)
To ssh://git@repo.example.com:1234/etckeeper-repository-name.git
   467c74e..839b58f  master -> master
  Verifying  : 1:smartmontools-5.43-1.el6.i686                              1/1 

Installed:
  smartmontools.i686 1:5.43-1.el6                                               

Complete!

The package installed here includes changes to the /etc/ directory, causing a commit and push before and after the package is installed.

If you have files in the /etc/ directory that change often as happens with webmin and its “System and Server Status”. Those and other files can be set to be ignored using the .gitignore file.

Manually committing changes

When you change the configuration files in /etc/ manually, there is no hook that triggers eckeeper to handle the changed files. In this case you need to execute etckeeper manually. With the following command it is possible to check if there are uncommitted changes in the git repository.

$ etckeeper vcs status
# On branch master
# Changed but not updated:
#   (use "git add ..." to update what will be committed)
#   (use "git checkout -- ..." to discard changes in working directory)
#
# modified:   ssh/sshd_config
#
no changes added to commit (use "git add" and/or "git commit -a")

If you have uncommitted changes, the following command can be executed to commit them into the repository.

$ etckeeper commit "updated sshd config"
[master 438c43a] updated sshd config
 Author: username <username@example.com>
 1 files changed, 1 insertions(+), 0 deletions(-)
Counting objects: 7, done.
Compressing objects: 100% (4/4), done.
Writing objects: 100% (4/4), 366 bytes, done.
Total 4 (delta 3), reused 0 (delta 0)
To ssh://git@repo.example.com:1234/etckeeper-repository-name.git
   9ab4abc..438c43a  master -> master

Read more of my posts on my blog at http://blog.tinned-software.net/.

This entry was posted in Linux Administration, Version control system and tagged , , . Bookmark the permalink.