Installation of puppet master on Ubuntu has always been a matter of luck and a lot of patience to me – there are many seemingly unrelated things to do which has to be done in the precise order, many combinations and changing behaviour of the software. So I set to write a bootstrapping script, which one day would be able to automate this task. I share it here in hope, that with help of you it will be a good starting point for many beginners.
Input:
- Name of the lxc container (
puppetmaster
) - Name of the codebase of ubuntu (i.e. whether it is precise, saucy or trusty)
mycodename
. - Fully qualified domain name for the puppetmaster (
puppetmasterfqdn
) - User used to operate the puppet on the machine; he also is an owner of the
/etc/puppet
(puppetuser
) - Location of the external git repository. It will be cloned into the lxc container.
gitlocation
- Location of the public ssh key used for login (
puppetauth
) - Static IP address of the container, preferably inside the lxc’s private network (
puppetip
) - Gateway for the lxc. It could be set automatically based on the default lxc configuration, but I am too lazy to write automation around it (
puppetgetewayip
)
Features:
- Installs the
lxc
container support on the host - Installs the ubuntu’s template (the codename can be customized)
- installs the user’s ssh key on the machine
- installs puppetmaster with puppetdb support (for stored configs)
- sets fixed IP address.
- connects the external puppet git repository with the container
The script is written in a spirit of puppet, i.e. it makes sure that certain properties of the system are set, skipping actions if they are set already. So it can be run as many times, as needed.
As an added bonus it also adjusts the user’s name from the default ‘ubuntu’
the script :
#!/bin/bash
puppetmaster=puppetmaster
puppetmasterfqdn=puppetmaster.fqdn.name
puppetuser=adam
gitlocation=/home/puppet.git
puppetauth=`cat ~/.ssh/id_rsa.pub`
puppetip='10.0.3.90'
puppetgetewayip='10.0.3.1'
#mycodename=`lsb_release -c | perl -pe 's/^Codename:\s*(.*)$/$1/'`
mycodename=saucy
######################################
mydir="/var/lib/lxc/$puppetmaster/rootfs"
#lxc installation
sudo dpkg -s lxc>/dev/null
if [ $? -eq 0 ]; then
echo "lxc already installed!"
else
sudo apt-get --yes install lxc
fi
#Container creation
sudo lxc-ls | grep $puppetmaster >/dev/null
if [ $? -eq 0 ]; then
echo "Container '$puppetmaster' already created!"
else
sudo lxc-create -t ubuntu -n $puppetmaster -- -r $mycodename
fi
#Container's hostname
sudo grep $puppetmasterfqdn $mydir/etc/hostname >/dev/null
if [ $? -eq 0 ]; then
echo "Puppet master's name is correctly set to FQDN!"
else
echo $puppetmasterfqdn | sudo tee $mydir/etc/hostname >/dev/null
fi
host=`sudo grep -E ^127\.0\.1\.1 $mydir/etc/hosts`
if [ $? -eq 0 ]; then
echo $host | grep "$puppetmasterfqdn" >/dev/null
if [ $? -eq 0 ]; then
echo "Puppet master's name is correctly set in hosts!"
else
sudo sed -i.old "s/^127\.0\.1\.1\s*/127.0.1.1 $puppetmasterfqdn /" $mydir/etc/hosts
fi
else
echo "127.0.1.1\t$puppetmasterfqdn" | sudo tee -a $mydir/etc/hosts >/dev/null
fi
#Montowanie puppet.git
sudo mkdir -p $mydir/mnt/puppet.git
sudo grep rootfs/mnt/puppet.git $mydir/../fstab >/dev/null
if [ $? -eq 0 ]; then
echo "Puppet git repository is already mounted!"
else
echo "$gitlocation $mydir/mnt/puppet.git none bind 0 0" | sudo tee -a $mydir/../fstab >/dev/null
sudo lxc-info -n $puppetmaster |grep RUNNING >/dev/null
if [ $? -eq 0 ]; then
sudo lxc-stop -n $puppetmaster
fi
fi
#Network setup
sudo grep $puppetip $mydir/etc/network/interfaces >/dev/null
if [ $? -eq 0 ]; then
echo "Static ip on the container is already set!"
else
sudo sed -i "iface eth0 inet dhcp/iface eth0 inet static \naddress $puppetip\nnetmask 255.255.255.0\ngateway $puppetgetewayip/" $mydir/etc/network/interfaces
fi
#Container startup
sudo lxc-info -n $puppetmaster |grep RUNNING >/dev/null
if [ $? -eq 0 ]; then
echo "Container is '$puppetmaster' already running!"
else
sudo lxc-start -d -n $puppetmaster
sleep 5
fi
#Learning the assigned dynamic IP. Static IP will be assigned later.
myip=`sudo lxc-info -n $puppetmaster -i | grep -oE "[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}"`
echo "puppetmaster IP = $myip"
#Preparing the puppet's configuration bare repository for cross-container mount
mount | grep $gitlocation >/dev/null
if [ $? -eq 0 ]; then
echo "Mount point '$gitlocation' is already declared"
else
sudo mount --bind $gitlocation $gitlocation
sudo mount --make-unbindable $gitlocation $gitlocation
sudo mount --make-shared $gitlocation $gitlocation
fi
#Puppet release.deb
if sudo [ -f $mydir/tmp/puppetdeb.deb ]; then
echo "Puppet release deb already exists!"
else
sudo wget -O $mydir/tmp/puppetdeb.deb http://apt.puppetlabs.com/puppetlabs-release-$mycodename.deb
fi
#Second stage script
sudo tee $mydir/tmp/bootstrap-puppetmaster-insider.sh >/dev/null <<EOT
#!/bin/bash
getent passwd $puppetuser >/dev/null
if [ \$? -eq 0 ]; then
echo "user $puppetuser already exists"
else
usermod -l $puppetuser -d /home/$puppetuser ubuntu
groupmod -n $puppetuser ubuntu
sudo mv /home/ubuntu /home/adam
fi
if [ -d /home/$puppetuser/.ssh ]; then
echo "'.ssh' folder already exists"
sudo chown $puppetuser:$puppetuser /home/$puppetuser/.ssh
else
sudo mkdir -p /home/$puppetuser/.ssh
sudo chown $puppetuser:$puppetuser /home/$puppetuser/.ssh
sudo chmod 0700 /home/$puppetuser/.ssh
fi
id $puppetuser | grep sudo >/dev/null
if [ \$? -eq 0 ]; then
echo "user $puppetuser already is a sudoer"
else
sudo usermod -a -G sudo $puppetuser
fi
if [ -f /home/$puppetuser/.ssh/authorized_keys ]; then
echo "File .ssh/authorized_keys already exists"
else
sudo -u $puppetuser touch /home/$puppetuser/.ssh/authorized_keys
fi
sudo grep "$puppetauth" /home/$puppetuser/.ssh/authorized_keys >/dev/null
if [ \$? -eq 0 ]; then
echo "proper key in authorized_keys already present"
else
echo $puppetauth | sudo -u $puppetuser tee /home/$puppetuser/.ssh/authorized_keys >/dev/null
fi
sudo dpkg -s puppetlabs-release>/dev/null
if [ \$? -eq 0 ]; then
echo "puppetlabs-release is already installed!"
else
sudo dpkg -i /tmp/puppetdeb.deb
fi
sudo dpkg -s puppetmaster>/dev/null
if [ \$? -eq 0 ]; then
echo "puppetlabsmaster is already installed!"
else
sudo apt-get update
sudo apt-get --yes install puppetmaster
fi
sudo dpkg -s git>/dev/null
if [ \$? -eq 0 ]; then
echo "git already installed!"
else
sudo apt-get --yes install git
sudo -u $puppetuser git config --global push.default simple
fi
sudo puppet module list|grep puppetlabs-puppetdb>/dev/null
if [ \$? -eq 0 ]; then
echo "PuppetDB module already installed!"
else
sudo puppet module install puppetlabs-puppetdb
fi
sudo puppet agent --test --server $puppetmasterfqdn
sudo puppet apply /tmp/puppetdb.pp
if [ -d /etc/puppet/.git ]; then
echo "Git repository is already clonned!"
else
if [ -d /etc/puppet.old ]; then
sudo rm -r /etc/puppet.old
fi
sudo mv /etc/puppet /etc/puppet.old
user=`whoami`
sudo git clone /mnt/puppet.git /etc/puppet
sudo chown -R $puppetuser:$puppetuser /etc/puppet
fi
grep "export LANG=C.UTF-8" /etc/default/puppetmaster >/dev/null
if [ \$? -eq 0 ]; then
echo "UTF-8 is properly set"
else
echo "export LANG=C.UTF-8" | sudo tee -a /etc/default/puppetmaster
sudo service puppetmaster restart
fi
sudo chown -R $puppetuser:$puppetuser /home/$puppetuser
EOT
sudo tee $mydir/tmp/puppetdb.pp >/dev/null <<'EOT'
node puppetmaster {
# Configure puppetdb and its underlying database
class { 'puppetdb': database => 'embedded'}
# Configure the puppet master to use puppetdb
class { 'puppetdb::master::config': }
}
EOT
sudo chmod +x $mydir/tmp/bootstrap-puppetmaster-insider.sh
# Disabling use of DNS on ssh
sudo lxc-attach -n $puppetmaster -- bash -x "/tmp/bootstrap-puppetmaster-insider.sh"
tmp=$(sudo grep -E '^UseDNS' $mydir/etc/ssh/sshd_config)
if [ $? -eq 0 ]; then
echo $tmp | grep UseDNS >/dev/null
if [ $? -eq 0 ]; then
echo "Puppet master's sshd is correctly configured to skip reverse DNS!"
else
sudo sed -i.old "s/^\s*UseDNS\s*.*$/UseDNS no/" $mydir/etc/ssh/sshd_config
fi
else
echo "UseDNS no" | sudo tee -a $mydir/etc/ssh/sshd_config >/dev/null
sudo lxc-attach -n $puppetmaster -- service ssh restart
fi
tmp=$(sudo grep -E '^iface eth0 inet dhcp$' $mydir/etc/network/interfaces)
if [ $? -eq 0 ]; then
sudo sed -i.old "s/iface eth0 inet dhcp/iface eth0 inet static\naddress $puppetip \nnetmask 255.255.255.0 \ngateway $puppetgetewayip/" $mydir/etc/network/interfaces
else
tmp=$(sudo grep -E '^iface eth0 inet static$' $mydir/etc/ssh/sshd_config)
if [ $? -eq 0 ]; then
echo "Networking is already configured with static IP on $puppetmaster!"
else
echo "### Cannot configure static IP on $puppetmaster! Please configure networking manually."
fi
fi
tmp=$(sudo grep -E '^iface eth0 inet static$' $mydir/etc/ssh/sshd_config)
echo "puppetmaster IP = $myip"