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
| « Revisited: Asterisk and FreePBX under Ubuntu 9.10 and Lighttpd on a Linode VPS | Team of RIT engineering students wins IEEE Student Design Contest » |
Keep track of configuration changes using etckeeper
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/passwdand 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 thesudocommand to temporarily assume root privileges./etc/network/interfaceson Debian-derived systems or/etc/sysconfig/network-scriptson RedHat-derived systems: Network configuration, such as IP addresses and interfaces.
... 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.
- Server: Linode 360 Xen-based virtual private server
- Distribution: Ubuntu 9.10, 32-bit
First, since this is a brand-new system, I edit /etc/apt/sources.list to enable the universe repositories, by uncommenting the relevant lines:
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.confas 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
/etcto 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
Comments are closed for this post.
![And this is a newly-deployed system. I get the same feeling looking at a mature /etc as I do looking at the Hubble Deep Field. [screenshot of /etc]](../../../media/blogs/ryan/etc-screenshot.png)
![[screenshot of /etc/apt/sources.list being edited in vi]](../../../media/blogs/ryan/sources-list-enable-universe-ubuntu-9.10.png)