I woke up this morning to a fresh install of Ubuntu 8.04 I was just itching to configure, but I had to work. So it wasn't until after the kids got fed and put to bed I could get started. What I'm aiming to accomplish tonight it to get the server configured and upgraded. The first thing I did was trim the install, I don't really want a LAMP server. I want to cut everything I don't need. The only daemon process I want is SSH at the moment so I went into aptitude and selectively removed packages I didn't want. It's worth noting here that if you're removing packages that you've no intention of installing again, make sure you do an apt-get purge or equivalent so you lose the config as well. You could probably do this with puppet and I want to automate as much of this process as I can, but I can't figure out how I can automate the upgrade, unfortunately, so I'm not going to bother with anything until I get 10.04 installed. The next step was to run the upgrade by installing the upgrade manager, and launching the process.
# apt-get install update-manager-core # do-release-upgrade -p -m server
You'll be asked a few questions, I went for all the defaults except when asked about the grub menu. I chose to throw away the existing config and go with the package maintainer's - it's the only one that worked for me. Eventually you'll be told the upgrade is complete and asked if you want to reboot. You and I now have an Ubuntu 10.04 LTS server, next stop puppet.

Puppet

The first big question I started having about my infrastructure was how I wanted to send the config to the servers. It wasn't such a big deal with this install, since it was just the one box. There are two main ways of managing config with puppet, the first is to use the bundled puppetmaster server. There is one puppetmaster, each client machine contacts at regular intervals and asks it if there are any changes and applies the ones that it needs. Out of the box they say it's good to 20-30 machines, you can tweak a few things to get a little more out of it or run it in a more powerful web process. The second way of running it is as a more or less standalone system. You update the config however you choose on each node, then execute the puppet command to apply it. The real benefit here is you control when the config is applied. One simple way of doing that is with post-recieve or post-update hooks in git and there is an excellent article from Bitfield Consulting about doing just that. I'm leaning towards manging the Hadoop cluster I'm looking to manage with puppet after this initial install in a very similar manner. I want to either make a change and have the change pushed immediately across the cluster or control the deployment of a change - it wouldn't do for the whole cluster to suddenly go down to update some software at exactly the same time. Part of the point of using puppet on top of hudson and the other tools I'll be getting into over the coming weeks and months is to allow me to push changes across the cluster, but more importantly roll back the bad ones. Let's get the packages
# apt-get install puppet git-core
By default puppet won't be configured to start puppetd, which is fine - we'll be triggering it manually.

Chicken or the egg

We want to store all of our configuration in git, but we also need puppet to manage and ensure there is a git repository on the server that's storing the config. With git it's actually pretty easy, we can create a repo in place, commit to it, then add the actual remote repo later.
# cd /etc/puppet # mkdir modules # git init .
That's our repository created, the only change we want to make is we need to ignore the puppet.conf file - we'll be managing that with puppet as well. Create the file
/etc/puppet/.gitignore
puppet.conf
Basically once we've set the repository up, managing a machine with puppet should be as simple as cloning the repository and running puppet. So let's get there - Now that everything seems to be setup properly, let's create a simple puppet recipe, as is the standard, let's enforce some permissions on /etc/sudoers, just to make sure it all works. This is a bit of an extension to the standard first recipe, but we'll be extending it later.

Sudoers module

First let's create the package, this is a pretty standard layout most modules will follow.
# cd /etc/puppet/modules # mkdir -p sudo/files sudo/manifests
Create the following files:
sudo/manifests/init.pp
import "*" class sudo { include sudo::install, sudo::service }
sudo/manifests/install.pp
class sudo::install { package{ "sudo": ensure => installed,} }
sudo/manifests/sudoers.pp
class sudo::sudoers { file { "/tmp/sudoers": mode => 440, source => "puppet:///modules/sudo/sudoers", notify => Exec["check-sudoers"], } exec { "check-sudoers": command => "/usr/sbin/visudo -cf /tmp/sudoers && cp /tmp/sudoers /etc/sudoers", refreshonly => true, } }

Set the rest of puppet up to call the module

Finally we need to set up puppet to call the module we've just created. We need to create a site.pp, everything else is loaded from there. In our installation we could call the file anything we like, but to keep things 'standard' we'll keep it as site.pp. Create the file
/etc/puppet/manifests/site.pp
import "sudo" node default { include sudo::install include sudo::sudoers }
That's it, puppet should now be up and running - test your configuration by executing the command:
# puppet -v --modulepath=/etc/puppet/modules /etc/puppet/manifests/site.pp

Finished for the day.

That's about all I can manage tonight. Tomorrow I'll continue with the puppet configuration, get it creating users and lock the server down a bit. After that I'll finally be able to start installing the software I need on the box.