Over the last couple of months I have been getting to grips with Puppet, a client-server system for applying configurations to remote machines. It is a powerful tool for network administration, allowing the configuration for your entire network to be stored in one versioned repository and applied with little effort. There are other, similar tools in this space, but Puppet seems to be particularly popular at the moment.
Puppet includes a master server that serves configuration and files, and a client daemon that connects back to the master using client-certified SSL, and applies configuration on the machine on which it runs. Configurations are defined in Puppet's own declarative language.
While Puppet is described as a tool that will apply configurations to remote machines, the fact that Puppet manifests comprise definitive knowledge about the network configuration should not be overlooked. As you configure services, the Puppet rules that you write serve as documentation of the process that you followed.
This is not to say Puppet is without problems. The client is very heavy, and can consume lots of memory to apply a configuration - this can be a showstopper on an otherwise very light VM. The Puppet language is clean for simple cases, but restrictions in its syntax that stem either from incompleteness, or deliberate restrictions intended to enforce configuration sanity can defeat attempts to write complicated and re-usable recipes.
It is also difficult to test Puppet recipes. You can run them on a VM, but it's time-consuming to ensure that they apply correctly, first time, given an out-of-the-box install. It's somewhat likely that you would need to run Puppet once, then run apt-get update, and then run Puppet again.
From my point of view as a developer who generally works with normalised databases, what I find ugly is that the Puppet repository is not one fact, one place. Puppet recipes most frequently just copy configuration files onto the client, and the particulars of a configuration file may implicitly depend on facts buried in many other configuration files or Puppet manifests. For example, the IPs listed in DNS zone files must match the IPs assigned in each host's network configuration.
To avoid some of these problems, a future Puppet-like tool could perhaps take the form of a comprehensive and extensible network information system (eg. RDF), and a suite of tools and recipes for compiling that information into something as lightweight as a bash script to run on each remote machine.