This is the third post in a series on building/setting up/improving a PXE boot server with CentOS.
By the end of this post, we’ll have added a pre-installation block to gather network information before installation, and some post-installation scripts to our our kickstart file to allow for copying of files and automatic configuration of the SMTP service and randomisation of our root password.
A requirement for this to work correctly is for you to have your own mail server, or an email account accessible to you – either via your own O365 or GSuite subscription, or a self-hosted mail solution like Modoboa or IRedMail. Personally I’m a fan of both self-hosted options, although in this example I’ll be using Modoboa. I’d previously it up and am using it to send alerts out from my lab (Veeam, monitoring, etc) to my own email account within GSuite.
If you do not have any of the above, you can configure the SMTP
service to use a gmail/yahoo/etc account instead, however I won’t be covering that in this post.
Prompting for network info
To get things started, we’re going to make the kickstart prompt us for the machines hostname and IP address, so there’s one less thing we have to do before we can start using the VM after it’s built.
open up the kickstart file we created previously, and delete lines 18 and 19, and replace them with the below text.
# Network Information
%include /tmp/network.ks
%pre --interpreter=/usr/bin/bash
exec < /dev/tty6 > /dev/tty6 2> /dev/tty6
chvt 6
echo "#######################################"
echo "Kickstarted CentOS 7 x64"
echo "Enter details to continue"
echo "#######################################"
read -p "Enter hostname: " HOSTNAME
read -p "Enter IP address: " IPADDR
read -p "Enter netmask: " NETMASK
read -p "Enter default gateway: " GATEWAY
read -p "Enter DNS server: " DNSSERVER
echo
sleep 1
echo "network --bootproto=static --hostname=$HOSTNAME --device=ens192 --gateway=$GATEWAY --ip=$IPADDR --netmask=$NETMASK --nameserver=$DNSSERVER --noipv6 --onboot=on --activate" > /tmp/network.ks
chvt 1
exec < /dev/tty1 > /dev/tty1 2> /dev/tty1
%end
What’s basically happening here, is that when the machine is PXE booted and the kickstart selected, the installer will prompt you to enter the requested details. The interpreter will then set the listed variables to the entered details and then echo them into the /tmp/network.ks
file.
The VM will then use this IP for the rest of the installation process, and once it reboots, the entered hostname and IP will be used for the completed VM build.
Configure SSMTP
Next, we’re going to add the ssmtp
package to our kickstart file, and also create and edit the config files for the SSMTP
service.
Inside our kickstart file, we want to add ssmtp
to the %packages
section like so:
%packages
@base
@core
...
ssmtp
...
%end
We also need to add a few lines into the kickstart file to create a temporary working directory in /tmp
and also copy our script to configure ssmtp
.
Why copy a script instead of making the kickstart create it for us? In my experience it just makes things simpler, and it means we can have a handful of kickstart files doing different configs for the VMs but referencing back to our core installation scripts.
In other words, if we need to edit the ssmtp
setup process for multiple kickstart files, we only have to update that script and not all the kickstart files.
At the top of the %post
section of our kickstart, we’ll need to add the following
%post --log=/tmp/post-build.log
...
#########################################
# Create our temporary working directory
mkdir /tmp/build
#########################################
# Copy ssmtp setup script
wget -O /tmp/build/ssmtpsetup.sh ftp://10.176.40.10/centos7/config/ssmtpsetup.sh
chmod +x /tmp/build/ssmtpsetup.sh
/bin/bash /tmp/build/ssmtpsetup.sh
%end
For ssmtp
to work correctly, there’s 2 files that need to be configured: ssmtp.conf
and revaliases
– these can both be found in /etc/ssmtp
.
To make it easier for the files to be accessed from the kickstart file, we’re going to put them in the following location: /var/ftp/centos7/config
.
We’re going to create our ssmtp.conf
file, making sure to set the username/password/server to your own, or a public mail service:
[email protected]
mailhub=mail.yourdomain.tld:587
hostname=BLANKHOSTNAME.AD.YOURDOMAIN.TLD
[email protected]
AuthPass=yourpassword
AuthMethod=LOGIN
UseSTARTTLS=YES
TLS_CA_File=/etc/pki/tls/certs/ca-bundle.crt
FromLineOverride=YES
Next we’re going to create the revaliases
file, again making sure to set the details to your own:
root:[email protected]:mail.yourdomain.tld:587
Finally, we’re going to create our ssmtpsetup.sh
script:
#!/bin/sh
# Get ssmtp config files
wget -O /tmp/build/ssmtp.conf ftp://10.176.40.10/centos7/config/ssmtp.conf
wget -O /tmp/build/revaliases ftp://10.176.40.10/centos7/config/revaliases
# Fix hostname in ssmtp.conf
sed -i s^'BLANKHOSTNAME'^"$HOSTNAME"^ /tmp/build/ssmtp.conf
# Copy files
cp -rf /tmp/build/ssmtp.conf /etc/ssmtp/
cp -rf /tmp/build/revaliases /etc/ssmtp/
# Disable sendmail and symlink to ssmtp
mv /usr/sbin/sendmail /usr/sbin/sendmail.ORIG
ln -s /usr/sbin/ssmtp /usr/sbin/sendmail
mv /usr/lib/sendmail /usr/lib/sendmail.ORIG
ln -s /usr/sbin/ssmtp /usr/lib/sendmail
The above is essentially wget
-ing the files we just created from the FTP server and storing them in the /tmp/
directory. We replace BLANKHOSTNAME
in the ssmtp.conf
file with the VM’s actual hostname as required, and then copy the files to the correct location. We also rename the default sendmail
files and replace them with symlinks to ssmtp
.
Randomised root password
The next thing we’re going to tackle here is randomly generating our root password – from a security standpoint, it’s more secure to have different root passwords across multiple machines. If an attacker is able to breach one of your machines, in theory they shouldn’t be able to access anything else if each VM’s root password is different.
One again, we need to open up our kickstart file and add a few lines into it.
Essentially this snip is generating a random string of 100 alphanumerical characters and then grabs the first 15 (or value for HOWLONG
) characters. We then create and set permissions on a temporary password file, and echo the NEWPW
value to the passwd
command and also our temporary password file.
%post --log=/tmp/post-build.log
...
#########################################
# Generate random root password
# https://serverfault.com/a/976598
HOWLONG=15 # How long our root password should be
NEWPW=$(< /dev/urandom tr -dc A-Za-z0-9 | head -c100 | head -c$((20+($RANDOM%20))) | tail -c$((20+($RANDOM%20))) | head -c${HOWLONG});
echo "${NEWPW}" | passwd --stdin root
touch /tmp/build/password
chmod 777 /tmp/build/password
echo "${NEWPW}" >> /tmp/build/password
...
%end
Next, we need to add the following underneath the above. Once again, we’re wget
-ing a script to our temp working directory, making it executable and then adding a line to the root crontab to make the script execute after the VM has rebooted.
%post --log=/tmp/post-build.log
...
#########################################
# Copy our build cleanup script
wget -O /tmp/build/buildcleanup.sh ftp://10.176.10.2/centos7/config/buildcleanup.sh
chmod + /tmp/build/buildcleanup.sh
echo "@reboot sleep 60 && /tmp/build/buildcleanup.sh && /sbin/shutdown -r now" > /var/spool/cron/root
...
%end
And here’s the buildcleanup
script we need to create in our FTP directory. This script restarts the postfix service, and then emails out the password file created above to the recipient set in MAILTO
. The script also deletes our temporary working directory and resets the root crontab.
#!/bin/bash
systemctl restart postfix
sleep 15
MAILTO='[email protected]'
PASSWORDFILE=$(cat /tmp/build/password)
echo "The root password is $PASSWORDFILE" | mail -s "$HOSTNAME build complete!" $MAILTO
sleep 30
/bin/rm -rf /tmp/build/
/bin/crontab -r
Bringing it all together
So at this point we’ve modified our kickstart file a bunch, and created a bunch of files in our /var/ftp/centos7/config
directory, so now what?
Before we do anything else, now is a good time to run ksvalidator
against the kickstart to make sure there’s nothing wrong with it. everything good? Let’s try to build a VM!
PXE boot a VM and run through the process the same as before – however, we’ll be promoted to enter a hostname, IP, subnet, default gateway and DNS server before the build starts.

Once the build has finished, you’ll be sent to a login screen – after a couple of minutes, the VM should reboot once more, and you’ll receive an email from the VM containing the root password.

Now, if all has gone to plan, we should be able to successfully login with the root account and the password in the above email

Finally, for the purpose of demonstration, I commented out line 9 of the buildcleanup.sh
script so the password file was not removed. If we now cat
the /tmp/build/password
file, we’ll see that it contains our root password.
Wrapping up
In this post we’ve covered the process of customising our kickstart file more by making it prompt us for a hostname/IP address details, install more packages, copy files to configure a package, randomly generate our root password, and then email us once everything is completed so we know the VM is ready to be used.
In the next post I’m going to cover automatically joining our VM to Active Directory so we can both login with an AD username, and also use AD to manage user permissions on the VM.