Lead Image © Michael Kempf, Fotolia.com

Lead Image © Michael Kempf, Fotolia.com

Automate CentOS and RHEL installation with PXE


Article from ADMIN 61/2021
Red Hat delivers an installer that lets you automate the installation of RHEL and CentOS in a preboot execution environment.

Extensive frameworks for Puppet, Chef, Ansible, and Salt are found in many setups for both automation and configuration. What happens once a system is installed and accessible over SSH is clearly defined by these frameworks, so how do you convince a computer to transition to this state? Several tool suites deal with the topic of bare metal deployment in different ways; the installation of the operating system, then, is part of a large task package that the respective software processes, as if by magic.

Not everyone wants the overhead of such solutions, but that doesn't mean you have to sacrifice convenience. Linux systems can usually be installed automatically by onboard resources, without a framework or complex abstraction. In this article, I show how Red Hat Enterprise Linux (RHEL, and by analogy CentOS) can be installed automatically by the normal tools of a Linux distribution with a preboot execution environment (PXE). All of the tasks in the deployment chain are addressed.

Initial State

To install the other systems automatically, you clearly require something like a manually installed nucleus. These systems are often referred to as bootstrap nodes or cluster workstations. Essentially, this is all about the infrastructure that enables the automatic installation of Red Hat or CentOS, although it does not include as many services as you might expect. All that is really needed is working name resolution, DHCP, trivial FTP (TFTP), and an HTTP server that provides the required files. If desired, Chrony or Ntpd can be added so that the freshly rolled out servers have the correct time.

In this article, I assume that all services for the operation of an automatic installation framework are running on one system. Ideally, this is a virtual machine (VM) that runs on a high-availability cluster for redundancy reasons. This setup can be easily realized on Linux with onboard resources by a distributed replicated block device (DRBD) and Pacemaker. Both tools are available for CentOS. DRBD and Pacemaker are discussed elsewhere [1] [2], so this part of the setup is left out here: It is not absolutely necessary anyway. If you can live with the fact that the deployment of machines does not work if the VM with the necessary infrastructure fails, you do not need to worry about high availability at this point.

The basis for the system offering bootstrap services for newly installed servers is CentOS in the latest version from the 8.x branch, but the work shown here can be done with RHEL, as well.

Installing Basic Services

As the first step, you need to install CentOS 8 and set it up to suit your requirements, including, among other things, storing an SSH key for your user account and adding it to the wheel group on the system so that the account can use sudo. Additionally, Ansible should be executable on the infrastructure node. Although the operating system of the bootstrap system cannot be installed automatically, nothing can prevent you from using Ansible for rolling out the most important services on this system itself to achieve reproducibility.

Assume you have a CentOS 8 system with a working network configuration, a user who can log in over SSH and use sudo, and Ansible, so that the command ansible-playbook can be executed. To use Ansible, the tool expects a specific structure in your local directory, so the next step is to create a folder named ansible/ in the home directory and then, below this folder, the roles/, group_vars/, and host_vars/ subfolders.

You also need to create in an editor an inventory for Ansible. For this purpose, create the hosts file with the content:

<full_hostname_of_the_Ansible_system> ansible_host=<Primary_IP_of_the_system> ansible_user=<login_name_of_admin_user> ansible_ssh_extra_args='-o StrictHostKeyChecking=no'

The entire entry after [infra] must be one long line. You can check whether this works by calling

ansible -i hosts infra -m ping

If Ansible then announces that the connection is working, everything is set up correctly.

Configure DHCP and TFTP

Your next steps are to get the required services running on the infrastructure VM. DHCP, TFTP, and Nginx are all it takes to deliver all the required files to requesting clients.

Of course, you can find ready-made Ansible roles for CentOS- and RHEL-based systems that set up DHCP and TFTP, and I use two roles from Dutch developer Bert van Vreckem, because they work well and can be launched with very little effort (Figure 1). In the roles/ subfolder check out the two Ansible modules from Git (installed with dnf -y install git):

VM> cd roles
VM> git clone https://github.com/bertvv/ansible-role-tftp bertvv.tftp
VM> git clone https://github.com/bertvv/ansible-role-dhcp bertvv.dhcp
Figure 1: Automation is useful when it comes to setting up the infrastructure node. Thanks to ready-made roles, the Ansible setup is completed quickly.

In the file host_vars/-<Hostname_of_infrastructure_system>.yml, save the configuration of the DHCP server as shown in Listing 1. It is important to get the hostname exactly right. If the full hostname of the system is infrastructure.cloud.internal, the name of the file must be infrastructure.cloud.internal.yml. Additionally, the values of the subnet configured in the file, the global address of the broadcast, and the address of the PXE boot server need to be adapted to the local conditions.

Listing 1

Host Variables

dhcp_global_domain_name: cloud.internal
  - ip:

The subnet must be a subrange of the subnet where the VM with the infrastructure services itself is located. However, when configuring the range, you need to make sure the addresses that the DHCP server assigns to requesting clients do not collide with IPs that are already in use locally. It is also important that the value of dhcp_pxeboot_server reflects the IP address of the infrastructure VM (Figure 2); otherwise, downloading the required files over TFTP will fail later.

Figure 2: For the DHCP role to know how to set up the DHCP daemon (dhcpd), you need to define the configuration in the host variables of the server with the infrastructure services.

TFTP is far less demanding than DHCP in terms of its configuration. Bert van Vreckem's module comes with meaningfully selected defaults for CentOS and sets up the TFTP server such that its root directory resides in /var/lib/tftpboot/, which is in line with the usual Linux standard.

As soon as the two roles are available locally and you have stored a configuration for DHCP in the host variables, you need to create an Ansible playbook that calls both roles for the infrastructure host. In the example, the playbook is:

- hosts: infra
  become: yes
    - bertvv.dhcpd
    - bertvv.tftp

Basically, for the Playbooks added in this article, you need to add a new line with the appropriate value to the entries in roles. The role's name matches that of the folder in the roles/ directory (Figure 3).

Figure 3: The Playbook for the infrastructure services is simple in its final form – even if the configuration for GRUB and Kickstart can be generated automatically by Ansible.

Buy this article as PDF

Express-Checkout as PDF
Price $2.95
(incl. VAT)

Buy ADMIN Magazine

Get it on Google Play

US / Canada

Get it on Google Play

UK / Australia

Related content

comments powered by Disqus