It can be a challenge to administer multiple Linux machines, particularly when this isn’t your primary job.  I deal with about 6 machines on a daily basis, and the various configurations tend to blur together.  If I didn’t have a system for keeping it straight, I’d be lost.  I know because I still have memories of “the time before the system” and it was madness.

I tried a few existing configuration management tools (cfengine, puppet, bcfg2) and everything seemed to be more complex than I wanted, so I wrote my own: Xenadu. Originally, Xenadu was specialized for creating Xen guest images, but I now use it to administer both virtual and physical machines.  It’s one of those “makes the impossible possible” tools, for me, and I’m actually using it on a few production systems.

My primary goal with Xenadu is to track my system administration with a version control program like git.  By doing this, I essentially get automatic documentation and backups of my sysadmin activities.  If I made a change to a system and it broke, I would always be able to get a previous version of the system configuration out of git.

Once you have fully defined a system with Xenadu, it becomes quite easy to create other machines that have similar configurations.  This is great for keeping a stage/production environment in sync, or for creating several instances of a particular production server.

An example Xenadu configuration for a computer named “davidbowie” might look like this:

:::python
#!/usr/bin/env python
from Xenadu import XenaduConfig, Perm
mapping = [
    ['/etc/hosts', "hosts", Perm.root_644],
    ['/etc/network/interfaces', "interfaces", Perm.root_644],
    ]
env = { 'ssh': { "user": "root", "address": "davidbowie.example.com" } }
XenaduConfig(env, mapping)

Save the file as davidbowie.py, and you’re ready to manage that computer.  In this case, two files (hosts and interfaces) are going to be tracked by Xenadu.  Now you can edit the files locally, check them into version control, etc.  If you’ve edited your local copy of hosts and want to send it to your remote system:

:::bash
./davidbowie.py --push hosts

A particularly useful feature is that you can specify a file according to its local or remote filename, so the following are equivalent:

:::bash
./davidbowie.py --push hosts
./davidbowie.py --push /etc/hosts

You can also --get, which downloads a file, and --getall, which downloads every file specified in your Xenadu system definition.  Check out the readme file on the Xenadu website for more information.

In the olden days, I would perform system administration by logging onto the system itself, editing files as I went along.  You can still do this with Xenadu, but make sure to --get your changes from the remote host, so that you can check it into version control.  My current workflow is to make changes locally, then --push them to the remote host.  Give it a try!