The content of this blog is archived. No comments may be made, and no further content will be published. Thank you for your ongoing readership! -Ryan
The best of a bad lot

« Revisited: Asterisk and FreePBX under Ubuntu 9.10 and Lighttpd on a Linode VPSTeam of RIT engineering students wins IEEE Student Design Contest »

Keep track of configuration changes using etckeeper

Permalink 12/06/09 15:33, by Ryan, Categories: Geekery, Howto , Tags: , , , , , , , , ,

I do stupid things sometimes.

On a Linux system (and most other Unix-like systems), the /etc directory holds most of the fundamental system configuration files. Within its hierarchy lies a number of very important nuggets:

  • /etc/passwd and its clandestine friend /etc/shadow: Usernames, passwords, and home directories for all local users.
  • /etc/resolv.conf: Nameservers for resolving hostnames.
  • /etc/sudoers: The list of users who may use the sudo command to temporarily assume root privileges.
  • /etc/network/interfaces on Debian-derived systems or /etc/sysconfig/network-scripts on RedHat-derived systems: Network configuration, such as IP addresses and interfaces.
[screenshot of /etc]

... and much, much, MUCH more.

As you can imagine, there's a lot of room for mistakes here. Whether you're adjusting network configuration slightly, configuring your web server, or adding/removing users, there's a good chance you'll regret it later on. It happens to everyone, usually at a very inconvenient time following a supposedly-"quick" reboot.

You can't avoid mistakes, but you can make it easier to find and fix them when they emerge. If you're familiar with revision control, you understand a couple key goals: you should be able to determine what change was made, when it was made, and by whom. This is where etckeeper comes in.

Ideally, you should just be able to fire up git, svn, or what-have-you on your /etc and be done with it. However, as etckeeper's Joey Hess points out, revision control systems tend to ignore empty directories, file permissions, and other things endemic to the /etc landscape:

So instead I followed the lead of these blogs combined with David Härdeman's metastore for solving the metadata storage problem. I also hacked in a solution to the empty directory storage problem, and a few other issues with trying to use git for this thing that it was not really designed for.

He also added a killer feature to etckeeper: automatic commits before and after apt-get and aptitude runs. This means you can see exactly what installing or removing a package did to your /etc, as well as which packages were added or removed. Very awesome.

Installing etckeeper on Ubuntu

It's pretty simple. For this installation, I'll be using a freshly-deployed virtual server. etckeeper is the first thing I'm installing, but you can install it on a mature system, of course.

First, since this is a brand-new system, I edit /etc/apt/sources.list to enable the universe repositories, by uncommenting the relevant lines:

[screenshot of /etc/apt/sources.list being edited in vi]

I then run apt-get update to pull in up-to-date package lists, and apt-get upgrade to apply any updates.

That's the hard part. Now, let's install etckeeper and its friend git-core:

Code:

root@localhost:~# apt-get install etckeeper git-core
(apt-get does its thing)
...
added vim/vimrc
added vim/vimrc.tiny
added xml/catalog
added xml/catalog.old
added xml/xml-core.xml
added xml/xml-core.xml.old
Committed revision 1.                                                          
 
Processing triggers for libc-bin ...
ldconfig deferred processing now taking place
root@localhost:~#

By default, this uses the Bazaar revision control system. If you're OK with bzr, then by all means use it. However, I use git for everything else, so I prefer to use it with etckeeper.

To change to git, you'll first want to remove the existing stuff using etckeeper uninit:

Code:

root@localhost:~# etckeeper uninit
** Warning: This will DESTROY all recorded history for /etc,
** including the bzr repository and ignore file.
 
Are you sure you want to do this? [yN] y
Proceeding..

Then, edit the top of /etc/etckeeper/etckeeper.conf to comment out the bzr line and uncomment the git line:

Code:

# The VCS to use.
# VCS="hg"
VCS="git"
# VCS="bzr"
# VCS="darcs"

Then, reinitialize etckeeper with etckeeper init, and do your first commit with etckeeper commit:

Code:

root@localhost:~# etckeeper init
Initialized empty Git repository in /etc/.git/
root@localhost:~# etckeeper commit 'initial commit'
...
create mode 100644 wgetrc
create mode 100644 xml/catalog
create mode 100644 xml/catalog.old
create mode 100644 xml/xml-core.xml
create mode 100644 xml/xml-core.xml.old
root@localhost:~#

Using etckeeper

To be adequately used, anything like etckeeper must be simple and easy to use. Fortunately, it is. You just have to remember one thing:

etckeeper commit

Let's make a simple change and show how it's done. Perhaps we'll add a regrettable typo somewhere:

Code:

root@localhost:~# echo halt >> /etc/rc.local

We're done with this edit, so let's commit it into etckeeper. By the way, you can either specify a brief commit message on the command line, or it will fire up an editor to let you enter a longer log message.

Code:

root@localhost:~# etckeeper commit 'enabling alternate h in rc.local'
[master 5c403d3] enabling alternate h in rc.local
1 files changed, 1 insertions(+), 0 deletions(-)

We can now use normal git tools to examine this revision!

Code:

root@localhost:~# cd /etc
root@localhost:/etc# git log
commit 5c403d3e74c24a6f0bce5abe70f0bfac65c8d837
Author: root <root@localhost.(none)>
Date:   Sun Dec 6 16:23:08 2009 +0000
 
    enabling alternate h in rc.local
 
commit e5c3218de86f0cc2e477cbf960d381c8fcdbd8fe
Author: root <root@localhost.(none)>
Date:   Sun Dec 6 16:19:50 2009 +0000
 
    initial commit
root@localhost:/etc# git diff e5c3218 5c403d3
diff --git a/rc.local b/rc.local
index 65634df..cd0acfd 100755
--- a/rc.local
+++ b/rc.local
@@ -12,3 +12,4 @@
# By default this script does nothing.
exit 0
+halt

Reverting bad changes

And yes, you can use gitk and git bisect and git push and whatever the heck else you want to use. That's the point. Even more importantly, since this edit was clearly a serious mistake (two of them, actually), we can toast it:

Code:

root@localhost:/etc# git revert 5c403d3
Finished one revert.
[master 2a973c7] Revert "enabling alternate h in rc.local"
1 files changed, 0 insertions(+), 1 deletions(-)
root@localhost:/etc# git status
# On branch master
nothing to commit (working directory clean)
root@localhost:/etc# tail -2 rc.local
 
exit 0

Further things to explore

  • etckeeper will, by default, run before and after each apt run. If you'd rather it not run before, you can affect this behavior in /etc/etckeeper/etckeeper.conf.
  • It will also do a daily autocommit of any changes in /etc. You can turn this off in /etc/etckeeper/etckeeper.conf as well. If you do, it might be a good idea to run something that checks for uncommitted changes nightly, e-mailing you if you've been lazy.
  • You probably don't want to push your /etc to a public git repository.

I'd like to give props to Yaakov for introducing me to etckeeper. I believe it's an effective and easy way to keep yourself sane, even on single-administrator systems. I don't know how I survived working on systems with multiple administrators and no revision control, but I'd rather not do so again.

1 comment

Comment from: Antonio Touriño [Visitor]
Antonio TouriņoThanks for the tip. I wasn't aware of this command. Good stuff.
12/12/09 @ 15:24

Comments are closed for this post.

Blog posts come from a can. They were put there by a man in a factory downtown.

Recent Twitterings

    Stalk me with RSS

    Search the Blog

     

    Support the Beer Fund

    Powered by Linode: Life's too short for crappy hosting

    [Powered by Linode]

    powered by b2evolution

    © 1962-2015 by Ryan Tucker (Public Key)

    Contact | Help | b2evo skin by Asevo | open source blog | webhosting | F.P.