Install CentOS 7 remotely using Kickstart and GRUB

This guide assumes the target host is already running CentOS (a derivate of Red Hat Enterprise Linux) or at least running the GRUB boot loader and that you have root access to this host.

What’s this all about?

I’m going to install CentOS 7 onto a machine which I do not have physical access to. In order to achieve this, I’m going to need a Kickstart file, some files from the CentOS 7 installation and create a custom GRUB boot loader entry.

The Kickstart file

A Kickstart file will automate the whole installation process. The RedHat 7 Enterprise documentation does a good job explaining:

Red Hat Enterprise Linux 7 offers a way to partially or fully automate the installation process using a Kickstart file. Kickstart files contain answers to all questions normally asked by the installation program, such as what time zone do you want the system to use, how should the drives be partitioned or which packages should be installed. Providing a prepared Kickstart file at the beginning of the installation therefore allows you to perform the entire installation (or parts of it) automatically, without need for any intervention from the user. This is especially useful when deploying Red Hat Enterprise Linux on a large number of systems at once.

A Kickstart file is generated in /root after a successful installation of CentOS. You can use this as a start to create your custom Kickstart file.

As an example, here’s a Kickstart file which was created automatically when installing CentOS 7. However, we’ll need to make some changes to it so that it will work when remotely installing CentOS 7 via SSH.

First, we’ll have to change the installation media from “cdrom” to “url”. I’m using one of the mirrors available:

# Use CDROM installation media
#cdrom

# Use network installation
url --url="http://mirror.zetup.net/CentOS/7/os/x86_64/"

We’ll also have to tell the installation to clear out any previous partitions on “sda” (the primary disk):

# Partition clearing information
#clearpart --none --initlabel
clearpart --all --drives=sda

Since we want the machine to automatically reboot after completed installation, we’ll have to tell it to do that:

# Reboot after installation
reboot

It’s possible that we won’t know how to access the machine remotely after the installation finished if we don’t specify e.g. a static IP address. Here’s how we could do that:

# Network information
#network  --bootproto=dhcp --device=eth0 --ipv6=auto --activate
network  --bootproto=static --device=eth0 --gateway=10.0.0.1 --ip=10.0.0.100 --nameserver=8.8.8.8 --netmask=255.255.255.0 --ipv6=auto --activate
network  --hostname=mymachine

Please review all options in the Kickstart file. There are additional options which I will not cover here:

I recommend taking a minute or two to read through the Kickstart How-To.

Verify the Kickstart file

You can make sure your Kickstart file is valid by using “ksvalidator”:

Install ksvalidator:

yum install pykickstart

Run ksvalidator on your Kickstart file:

ksvalidator /path/to/anaconda-ks.cfg

Please note: ksvalidator will not attempt to validate the %pre, %post and %packages sections of the Kickstart file.

Make the Kickstart file available on a web server

During the installation phase, Anaconda will attempt to read the Kickstart file from somewhere. I’m serving it using a basic web server.

Download vmlinuz and initrd.img

Download vmlinuz and initrd.img from the desired CentOS version you wish to install and place them in /boot. For example:

curl -o /boot/vmlinuz http://mirror.zetup.net/CentOS/7/os/x86_64/isolinux/vmlinuz
curl -o /boot/initrd.img http://mirror.zetup.net/CentOS/7/os/x86_64/isolinux/initrd.img

Add custom boot entry in CentOS 6.x (or GRUB 1.x)

If you are installing CentOS 7 remotely on a CentOS 6 system, read on…

Add a custom entry into /boot/grub/grub.conf:

title Install CentOS 7
kernel /vmlinuz ks=http://some-web-server.com/anaconda-ks.cfg
initrd /initrd.img

If you make sure that this entry is the first entry in the configuration file, you will not have to bother defining this to become the default entry. But if you decide to not place this entry first, you will have to tell grub which entry this is by changing this line, also in /boot/grub/grub.conf:

default 0

Also, you should replace the URL in the custom boot entry to reflect the location of where your Kickstart file is at.

You may wish to add options to the end of the kernel line of the boot stanza in the custom boot entry. For example, if you wish to monitor the installation via VNC, you’ll have to add VNC options as well as network options with static IP address.

Add custom boot entry in CentOS 7.x (or GRUB 2.x)

If you are installing CentOS 7 remotely on a CentOS 7 system, read on…

Add a custom menu entry into /etc/grub.d/40_custom, which is where custom boot entries are defined when you use GRUB2:

menuentry "Install CentOS 7" {
    set root=(hd0,1)
    linux /vmlinuz ks=http://some-web-server.com/anaconda-ks.cfg
    initrd /initrd.img
}

You should replace the URL in the custom boot entry to reflect the location of where your Kickstart file is at.

Add any additional boot options at the end of the linux line of the boot stanza in the custom boot entry. For example, if you wish to monitor the installation via VNC, you’ll have to add VNC options as well as network options with static IP address.

Make the custom entry the default choice in /etc/default/grub:

GRUB_DEFAULT="Install CentOS 7"

Then run the following to make your changes go into effect:

grub2-mkconfig --output=/boot/grub2/grub.cfg

Reboot your system to install CentOS 7

Go grab a cup of coffee and reboot your system:

reboot

Additional notes

Personally, I find it very useful to run Pre-installation Python scripts using %pre --interpreter=/usr/bin/python and I highly recommend reading more on that in the documentation. Currently, I use this to match the machine’s MAC address against a JSON/dictionary, which will determine which hostname and static IP address the machine should use, as I’m managing a large number of computational nodes, running CentOS, on our local network.

If CentOS (or GRUB) is not present on the machine you wish to install CentOS 7 onto, you can boot via the CentOS 7 DVD or USB-stick. In the menu that appears, you can hit “tab” and enter custom commands, such as vmlinuz initrd=initrd.img ks=http://some-web-server.com/anaconda-ks.cfg to specify the Kickstart file. This will cause the installation to complete automatically without requiring any input from you. For a complete tutorial on this check this out.

If a package requires access to a specific repository, you can specify this in the Kickstart file:

repo --name="EPEL" --baseurl=http://dl.fedoraproject.org/pub/epel/7/x86_64/

If you need to know the location of the Kickstart file, from within the Kickstart file (perhaps you wish to access another file relative to its location) … you can read /proc/cmdline and parse it. Here’s an example:

%pre --interpreter=/usr/bin/python
cmdline = ''
with open('/proc/cmdline', 'r') as myfile:
  cmdline = myfile.read()
pieces = cmdline.split(' ')
for piece in pieces:
  if 'ks=' in piece:
    KS_LOCATION = piece[ piece.rfind('ks=')+3 : piece.rfind('/') ]
%end