The Puppet Labs Issue Tracker has Moved: https://tickets.puppetlabs.com

Bootstrapping With Puppet

A functional example based around partial automatic installation and upgrading puppet to a functional version, primarily for Ubuntu but possibly adaptable to other Debian-based distributions.

Requirements

  • A local apt repository
  • I use the reprepro package to manage my repository
  • A quick google found this tutorial [http://ianlawrence.info/random-stuff/setting-up-a-personal-debian-repository]
  • Backported packages for $lsbdistrelease, available in said repository.
  • Ubuntu has a package called prevu for automating the backporting process, take a look at [https://wiki.ubuntu.com/Prevu]
  • A trusted.gpg file containing the necessary GPG public keys for said repository, so that apt doesn’t complain
  • A sources.list file containing said repository
  • The upgradepuppet class below (or similar, adapt as necessary)

Usage

  • Define a node in Puppet for your to-be-bootstrapped machine
  • Install your Ubuntu machine as per usual, with a preseed or without
  • Install Puppet from the official repositories (it’ll be old, 0.22.something)
  • Note: These last two steps can be replaced if you can work out how to make a preseed disk with 0.22 installed already, although, why you’d put 0.22 on your disk instead of 0.24.1 beats me..)
  • Personally here I stop the puppetd daemon (apt-get install puppet && /etc/init.d/puppet stop) and run puppetd —test
  • Magical things will happen! Packages will be upgraded, Puppet will be started, then stopped and disabled.
  • Using a case statement in your node (see below) normal operations will continue.

upgradepuppet class

This is the upgradepuppet class:

class upgradepuppet {
   file { "/etc/apt/sources.list":
      source => "puppet://puppet/files/sources.list.${lsbdistcodename}",
      ensure => present;
          "/etc/apt/trusted.gpg":
      source => "puppet://puppet/files/trusted.gpg",
      ensure => present;
          "/etc/puppet/puppetd.conf":
      ensure => absent,
      require => [ Package[puppet], Package[facter] ];
   }

   exec { "/usr/bin/apt-get update":
      alias => "aptgetupdate",
      require => [ File["/etc/apt/sources.list"], File["/etc/apt/trusted.gpg"] ],
      subscribe => [ File["/etc/apt/sources.list"], File["/etc/apt/trusted.gpg"] ],
      refreshonly => true;
   }

   package { "puppet":
      ensure => latest,
      require => Exec["aptgetupdate"];
             "facter":
      ensure => latest,
      require => Exec["aptgetupdate"];
   }

   service { "puppet":
      enable => false,
      require => Package[puppet];
   }
}

Example Node

This is an example of a node:

node proxy {
   case $puppetversion {
     "0.24.1": {
       $munin_group = "infrastructure"
       $apache2_port = "80"
       $apache2_ssl = "enabled"
       include generic-systems
       include firewall-ftp
       include users
       include util
       include monitoring
       include squidproxy
       include apache2::no_default_site
       include git::daemon

       apache2::site { "repository":
           ensure => present,
           source => "puppet:///apache/maxrepo";
       }

       munin::plugin { [ squid_cache, squid_requests, squid_traffic ]:
           config => "user root\nenv.squidport 8080"
       }
   }

     default: {
       include upgradepuppet
     }
   }
}

Bootstrapping RHEL/Centos and Puppet

Building the system

To begin with we need to build the system. For this, unless you already have something in place, look at using Cobbler [http://cobbler.et.redhat.com/]. This handles the tftp/dhcp/kickstart part of building a RHEL/Centos system. Once you have installed this and set it up, you’ll need to change it to use dnsmasq. This is so that you can provide —hostname=systemname to cobbler when adding systems, and have DHCP serve up this information to the host.

I also recommend adding EPEL to your cobbler configuration, via something like:

cobbler repo add --name=EPEL-x86_64 --mirror=http://download.fedora.redhat.com/pub/epel/5/x86_64

This will download ALL of EPEL locally. If you want you can add —mirror-locally=0 to this line, which will direct kickstart to download files directly from EPEL. For this to work, the addresses you serve via DHCP must have full internet access.

Next, edit the kickstart file you use to include something like:

%packages
@base
ruby
ruby-libs
puppet
facter
ruby-shadow
rubygems

%post --nochroot
# Copy netinfo, which has our FQDN from DHCP, into the chroot
test -f /tmp/netinfo && cp /tmp/netinfo /mnt/sysimage/tmp/

##
## Workflow:  Turn on puppet for next boot, set hosts and resolv.conf, then
## figure out the hostname.  Write a new /etc/sysconfig/network file to keep
## the hostname, then set the hostname and run puppet to get the certificate.
## Sign it on the other side during first boot.

%post
/sbin/chkconfig --level 345 puppet on
/bin/echo "$PUPPETIP puppet" >> /etc/hosts
/bin/echo "nameserver $NAMESERVERIP" >> /etc/resolv.conf
hostname $hostname
# Write out the hostname to a file for reboot.
/bin/echo -e "NETWORKING=yes\nHOSTNAME=$hostname" > /etc/sysconfig/network
/usr/sbin/puppetd -tv

/usr/sbin/rhnreg_ks --profile="$hostname" --username="" --password=""
$yum_config_stanza
$kickstart_done

You need to replace $PUPPETIP with the host name or IP address of the Puppet server, and $NAMESERVERIP with a working nameserver from whatever DHCP range you set up as part of cobbler. This bit is only required if you use RHEL, and want to automate the RHN registration, or if you turned on —mirror-locally=0 when adding EPEL. Otherwise skip the resolv.conf and rhnreg section.

This will run puppetd against the puppet master while still kickstarting. You then need to sign the certificate, so that it can run Puppet during the initial boot.