Install Virtual Machines on KVM using PXE and Kickstart

Posted on 86 views

By following this article to the end, you should be able to configure and use PXE and Kickstart server tools for Virtual Machine provisioning on KVM. KVM is an open source full virtualization solution for hardware architectures that support hardware virtualization. A library called libvirt provides a common API for managing KVM virtualization solution.

To create a fully automated installation of Virtual Machine on KVM, we need a network installation server that’s configured with TFTP, PXE, and a Kickstart file for initiating OS installation by booting from the network.

Preboot eXecution Environment (PXE) technology provides a mechanism for bootstrapping a computer using a network server. The computer where the operating system is installed should have a network interface that supports PXE, and the system firmware must enable PXE support.

The following list of services must be provided by the network boot infrastructure:

  • TFTP Server – Provides the boot images to start the installer, with the command-line options.
  • DHCP server – Provides initial client network configurations, and the location of TFTP server with a usable boot image
  • Kickstart and Media server – This can be HTTP, FTP, or NFS server to provide the installation media and a shared Kickstart file for OS installation.

PXE Booting Process

The following series of actions takes place when using PXE for automated OS installation.

  1. A client machine at boot, through its network interface card, sends a DHCPDISCOVER broadcast packet in the network with required PXE options
  2. Configured DHCP server on the network will respond with a DHCPOFFER. The offer contains the IP address the client will get, and information about location of the PXE server.
  3. The client then responds with a DHCPREQUEST  requesting for IP assignment
  4. DHCP server sends a DHCPACK, with this is the TFTP (Trivial FTP) server URL of a network boot loader
  5. Client downloads the boot file from TFTP server and loads it (pxelinux.0)
  6. The loaded boot loader gets configuration file and Kickstart files from TFTP and HTTP/FTP/NFS server respectively. The files instructs it how to download and start OS installer.
  7. The files are used to boot the client

Configuring the PXE Boot Environment

Our setup is based on these configuration options.

System type Hostname IP Address
DHCP/TFTP/HTTP Server bastion-server.kvmlab.net 192.168.177.2
Kickstart server bastion-server.kvmlab.net 192.168.177.2
Virtual Machine deployed via PXE vm0.kvmlab.net Assigned by DHCP Server
Our Lab setup

KVM Hypervisor is required installed and configured on your host system. Check the guides in the following links for complete setup steps:

Step 1 – Create Virtual Network (optional, you can use existing network without DHCP)

A bridge used should not have DHCP function as this will be handled by a DHCP Server virtual machine that we’ll install. These operations are to be performed on your KVM hypervisor host.

Ensure bridge utility package is installed.

### RHEL Based systems ###
sudo yum -y install vim bridge-utils

### Debian Based systems ###
sudo apt update
sudo apt install vim bridge-utils

Create a new virtual network creation configuration file.

vim br-pxe-net.xml

Modify these contents. You can replace IP information and bridge name to your liking and paste them inside the file.


  br-pxe
  
    
      
    
  
  
  
  

Create a virtual network using this file file created; modify if need be:

$ sudo virsh net-define --file br-pxe-net.xml
Network br-pxe defined from br-pxe-net.xml

Enable automatic starting on the bridge created.

$ sudo virsh net-autostart br-pxe
Network br-pxe marked as autostarted

Then ensure the bridge interface is online

$ sudo virsh net-start br-pxe
Network br-pxe started

Confirm that the bridge is available and active:

$ sudo virsh net-list
 Name      State    Autostart   Persistent
--------------------------------------------
 br-pxe    active   yes         yes
 default   active   yes         yes

$ brctl show
bridge name	bridge id		STP enabled	interfaces
br-pxe		8000.525400d64edf	yes
virbr0		8000.525400929ef5	yes

OVS Bridge

If using Open vSwitch bridge instead of Linux bridge, network script configuration file will have contents similar to below

$ sudo vim /etc/sysconfig/network-scripts/ifcfg-br-pxe
DEVICE=br-pxe
BOOTPROTO=none
ONBOOT=yes
TYPE=OVSBridge
DEVICETYPE=ovs
USERCTL=yes
PEERDNS=yes
IPV6INIT=no
IPADDR=192.168.177.1
PREFIX=24

Start the interface and check IP configurations:

$ sudo ifup br-pxe
$ ip ad show dev br-pxe
12: br-pxe:  mtu 1500 qdisc noqueue state DOWN group default qlen 1000
    link/ether 52:54:00:d6:4e:df brd ff:ff:ff:ff:ff:ff
    inet 192.168.78.1/24 brd 192.168.78.255 scope global br-pxe
       valid_lft forever preferred_lft forever

Allowing nating using IPtables firewall:

sudo iptables -t nat -A POSTROUTING -o enp0s31f6 -s 192.168.78.1/24 -j MASQUERADE

Step 2 – Create Bastion Virtual Machine (PXE,TFTP,HTTP and Kickstart Server)

Here we create a Virtual Machine that runs services to support network boot infrastructure.

  • Apache httpd web server
  • DHCP Server
  • PXE/TFTP services

Install libguestfs-tools package which provides virt-builder command line tool.

### RHEL Based systems ###
sudo yum -y install libguestfs-tools

### Fedora Linux systems ###
sudo dnf -y install guestfs-tools

### Debian Based systems ###
sudo apt -y install libguestfs-tools

List available OS templates:

sudo virt-builder -l

In this guide we’ll use Fedora template. Let’s create

sudo virt-builder fedora-36  --format qcow2 \
  --size 30G -o /var/lib/libvirt/images/kvm-bastion-server.qcow2 \
  --root-password password:StrongRootPassw0rd

Where:

  • fedora-36 is the template used to create a new virtual machine
  • /var/lib/libvirt/images/kvm-bastion-server.qcow2 is the path to VM qcow2 image
  • StrongRootPassw0rd is the root user password

Command execution output:

[   0.6] Downloading: http://builder.libguestfs.org/fedora-36.xz
############################################################################################################################################################################################### 100.0%############################################################################################################################################################################################### 100.0%
[  14.7] Planning how to build this image
[  14.7] Uncompressing
[  18.8] Resizing (using virt-resize) to expand the disk to 30.0G
[  42.7] Opening the new disk
[  47.2] Setting a random seed
[  47.2] Setting passwords
[  48.2] Finishing off
                   Output file: /var/lib/libvirt/images/kvm-bastion-server.qcow2
                   Output size: 30.0G
                 Output format: qcow2
            Total usable space: 30.0G
                    Free space: 28.9G (96%)

Create Virtual Machine from generated image.

Using Linux bridge:

sudo virt-install \
  --name kvm-bastion-server \
  --ram 2048 \
  --vcpus 2 \
  --disk path=/var/lib/libvirt/images/kvm-bastion-server.qcow2 \
  --os-type linux \
  --os-variant rhel8.0 \
  --network bridge=br-pxe \
  --graphics none \
  --serial pty \
  --console pty \
  --boot hd \
  --import

Using openVSwitch bridge: Ref How To Use Open vSwitch Bridge on KVM Virtual Machines

sudo virt-install \
  --name bastion-server \
  --ram 2048 \
  --disk path=/var/lib/libvirt/images/kvm-bastion-server.qcow2 \
  --vcpus 2 \
  --os-type linux \
  --os-variant rhel8.0 \
  --network=bridge:br-pxe,model=virtio,virtualport_type=openvswitch \
  --graphics none \
  --serial pty \
  --console pty \
  --boot hd \
  --import

Our bastion VM creation process is started. Once ready login with root and assigned password:

...omitted output ...
[  OK  ] Reached target Preparation for Network.
         Starting Network Manager...
[  OK  ] Started Network Manager.
[  OK  ] Reached target Network.
         Starting Network Manager Wait Online...
         Starting Permit User Sessions...
         Starting Hostname Service...
[  OK  ] Finished Permit User Sessions.
         Starting Hold until boot process finishes up...
         Starting Terminate Plymouth Boot Screen...
[    4.160192] IPv6: ADDRCONF(NETDEV_CHANGE): enp1s0: link becomes ready

.....
fedora login: root
Password: 

Reset root password:

[[email protected] ~]# passwd
Changing password for user root.
New password:
Retype new password:
passwd: all authentication tokens updated successfully.

You will notice the Virtual Machine doesn’t have IP address. The reason is that we disabled DHCP service in our natted bridge.

[[email protected] ~]# ip ad
1: lo:  mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
2: enp1s0:  mtu 1500 qdisc fq_codel state UP group default qlen 1000
    link/ether 52:54:00:0d:c3:34 brd ff:ff:ff:ff:ff:ff
    inet6 fe80::5054:ff:fe0d:c334/64 scope link noprefixroute
       valid_lft forever preferred_lft forever

$ nmcli con show
NAME    UUID                                  TYPE      DEVICE
enp1s0  50bdb463-8d8f-4053-9e3d-b3bbea6f5b1e  ethernet  --

Let’s create assign an IP address to the interface using NMCLI tool.

sudo nmcli con mod enp1s0 \
  ipv4.method manual \
  ipv4.address 192.168.177.2/24 \
  ipv4.gateway 192.168.177.1 \
  ipv4.dns 192.168.177.1 \
  connection.autoconnect yes

Restart the interface to ensure it uses configured settings:

$ sudo nmcli con down enp1s0 && sudo nmcli con up enp1s0
Connection 'enp1s0' successfully deactivated (D-Bus active path: /org/freedesktop/NetworkManager/ActiveConnection/5)
Connection successfully activated (D-Bus active path: /org/freedesktop/NetworkManager/ActiveConnection/6)

Check network configs:

$ nmcli con show
NAME    UUID                                  TYPE      DEVICE
enp1s0  50bdb463-8d8f-4053-9e3d-b3bbea6f5b1e  ethernet  enp1s0

$ ip ad
1: lo:  mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
2: enp1s0:  mtu 1500 qdisc fq_codel state UP group default qlen 1000
    link/ether 52:54:00:0d:c3:34 brd ff:ff:ff:ff:ff:ff
    inet 192.168.177.2/24 brd 192.168.177.255 scope global noprefixroute enp1s0
       valid_lft forever preferred_lft forever
    inet6 fe80::5054:ff:fe0d:c334/64 scope link noprefixroute
       valid_lft forever preferred_lft forever

Next we set the correct hostname of our Bastion server

sudo hostnamectl set-hostname bastion-server.kvmlab.net

Set correct timezone as well

sudo timedatectl set-timezone Africa/Nairobi
sudo chronyc sources

Enable Virtual Machine automatic start if you want on KVM:

sudo virsh autostart kvm-bastion-server

Step 3 – Setup DHCP Server for PXE Booting environment

Perform OS upgrade before deploying other services. The server being used here in this guide is Fedora.

sudo dnf -y upgrade
sudo dnf -y install git vim wget curl bash-completion tree tar libselinux-python3 firewalld

Reboot the server after the upgrade is done.

sudo reboot

Install DHCP server package

sudo dnf -y install dhcp-server

Move original DHCP server configuration file to backup:

sudo mv /etc/dhcp/dhcpd.conf,.bak

Create a new DHCP server configuration file

sudo vim /etc/dhcp/dhcpd.conf

Modify and paste the following data into the file

authoritative;
ddns-update-style interim;
default-lease-time 14400;
max-lease-time 14400;
allow booting;
allow bootp;

    #Default gateway
    option routers                  192.168.177.1;
    #DHCP network broadcast address
    option broadcast-address        192.168.177.255;
    #DHCP network subnet mask
    option subnet-mask              255.255.255.0;
    #IP address of DNS server
    option domain-name-servers      192.168.177.1;
    #Default NTP server
    option ntp-servers              time.google.com;
    #Default domain name 
    option domain-name              "kvmlab.net";

    subnet 192.168.177.0 netmask 255.255.255.0 
      range 192.168.177.20 192.168.177.50;
      # this is PXE specific
      filename "pxelinux.0";
      #PXE Server IP Address
      next-server 192.168.177.2;
   

Save the configs and start dhcpd service:

$ sudo systemctl enable --now dhcpd
Created symlink /etc/systemd/system/multi-user.target.wants/dhcpd.service → /usr/lib/systemd/system/dhcpd.service.

Check service status to confirm it started without errors:

$ systemctl status dhcpd
dhcpd.service - DHCPv4 Server Daemon
     Loaded: loaded (/usr/lib/systemd/system/dhcpd.service; enabled; vendor preset: disabled)
     Active: active (running) since Fri 2022-02-04 20:31:01 EAT; 23s ago
       Docs: man:dhcpd(8)
             man:dhcpd.conf(5)
   Main PID: 3187 (dhcpd)
     Status: "Dispatching packets..."
      Tasks: 1 (limit: 2328)
     Memory: 9.9M
        CPU: 13ms
     CGroup: /system.slice/dhcpd.service
             └─3187 /usr/sbin/dhcpd -f -cf /etc/dhcp/dhcpd.conf -user dhcpd -group dhcpd --no-pid

Feb 04 20:31:01 bastion.kvmlab.net dhcpd[3187]: Config file: /etc/dhcp/dhcpd.conf
Feb 04 20:31:01 bastion.kvmlab.net dhcpd[3187]: Database file: /var/lib/dhcpd/dhcpd.leases
Feb 04 20:31:01 bastion.kvmlab.net dhcpd[3187]: PID file: /var/run/dhcpd.pid
Feb 04 20:31:01 bastion.kvmlab.net dhcpd[3187]: Source compiled to use binary-leases
Feb 04 20:31:01 bastion.kvmlab.net dhcpd[3187]: Wrote 0 leases to leases file.
Feb 04 20:31:01 bastion.kvmlab.net dhcpd[3187]: Listening on LPF/enp1s0/52:54:00:0d:c3:34/192.168.177.0/24
Feb 04 20:31:01 bastion.kvmlab.net dhcpd[3187]: Sending on   LPF/enp1s0/52:54:00:0d:c3:34/192.168.177.0/24
Feb 04 20:31:01 bastion.kvmlab.net dhcpd[3187]: Sending on   Socket/fallback/fallback-net
Feb 04 20:31:01 bastion.kvmlab.net dhcpd[3187]: Server starting service.
Feb 04 20:31:01 bastion.kvmlab.net systemd[1]: Started DHCPv4 Server Daemon.

Allow DHCPD service on the firewall

sudo firewall-cmd --add-service=dhcp --permanent
sudo firewall-cmd --reload

Step 4 – Configure TFTP and PXE environment

Install TFTP server and syslinux packages on the bastion host.

sudo dnf -y install tftp-server syslinux

Start and enable TFTP service using systemctl command:

sudo systemctl enable --now tftp.socket

Allow tftp service on firewall:

sudo firewall-cmd --add-service=tftp --permanent
sudo firewall-cmd --reload

Copy initial configurations files and create required directories:

sudo cp /usr/share/syslinux/pxelinux.0 /var/lib/tftpboot/
sudo cp /usr/share/syslinux/menu.c32,vesamenu.c32,ldlinux.c32,libcom32.c32,libutil.c32 /var/lib/tftpboot/
sudo mkdir /var/lib/tftpboot/pxelinux.cfg

The pxelinux.cfg directory contains the default configuration file used by any system PXE-booting from this TFTP service.

Step 5 – Install and configure httpd web server

A web server is needed to host installation media files used during PXE boot process. For this guide we’ve chosen Apache httpd as a web server of choice.

sudo dnf -y install httpd

Let’s edit httpd configuration file and set Listen port to 8080. This is to avoid any conflicts with other applications that can be hosted on the same server using port 80.

$ sudo vi /etc/httpd/conf/httpd.conf
#Around line 45
Listen 8080

Start and enable httpd service

sudo systemctl enable --now httpd

Allow port 8080 if you have firewalld service active on the server.

sudo firewall-cmd --add-port=8080/tcp --permanent
sudo firewall-cmd --reload

Remove welcome page and restart httpd service

sudo /etc/httpd/conf.d/welcome.conf
sudo systemctl restart httpd

Step 6 – Download OS installation DVD ISO files

We’ll create a directory where all ISO files are to be stored.

mkdir pxe_iso_files
cd pxe_iso_files

The ISO download process will depend on your desired OS to be installed using PXE server. As this guide is geared more to RHEL based systems, we have shared download URLs for standard EL systems.

Downloading CentOS Stream 8 ISO:

wget http://centos.mirror.liquidtelecom.com/8-stream/isos/x86_64/CentOS-Stream-8-x86_64-latest-dvd1.iso

Rocky Linux 8:

wget https://download.rockylinux.org/pub/rocky/8/isos/x86_64/Rocky-8.5-x86_64-dvd1.iso

AlmaLinux 8 DVD:

wget http://iad.mirror.rackspace.com/almalinux/8.5/isos/x86_64/AlmaLinux-8.5-x86_64-dvd.iso

Oracle Linux 8:

wget https://yum.oracle.com/ISOS/OracleLinux/OL8/u5/x86_64/OracleLinux-R8-U5-x86_64-dvd.iso

Fedora 36 Server:

wget https://fedora.mirror.liquidtelecom.com/fedora/linux/releases/36/Server/x86_64/iso/Fedora-Server-dvd-x86_64-36-1.5.iso

Step 7 – Mounting ISO files on a web server root directory

List downloaded ISO files to confirm which ones are available locally.

$ ls -1
AlmaLinux-8.5-x86_64-dvd.iso
CentOS-Stream-8-x86_64-latest-dvd1.iso
OracleLinux-R8-U5-x86_64-dvd.iso
Rocky-8.5-x86_64-dvd1.iso
Fedora-Server-dvd-x86_64-36-1.5.iso

Next we create a directory in our web server root where ISO files will be mounted.

sudo mkdir /var/www/html/pxe

Create directories for each Linux distribution ISO. Customize commands shared to suit your use scenario.

### Rocky Linux 8 ###
sudo mkdir /var/www/html/pxe/rockylinux8
sudo mount -t iso9660 -o loop,ro Rocky-8.5-x86_64-dvd1.iso /var/www/html/pxe/rockylinux8

### AlmaLinux 8 ###
sudo mkdir /var/www/html/pxe/almalinux8
sudo mount -t iso9660 -o loop,ro AlmaLinux-8.5-x86_64-dvd.iso /var/www/html/pxe/almalinux8

### Oracle Linux 8 ###
sudo mkdir /var/www/html/pxe/oraclelinux8
sudo mount -t iso9660 -o loop,ro OracleLinux-R8-U5-x86_64-dvd.iso /var/www/html/pxe/oraclelinux8

### CentOS 8 Stream ###
sudo mkdir /var/www/html/pxe/centos8stream
sudo mount -t iso9660 -o loop,ro CentOS-Stream-8-x86_64-latest-dvd1.iso /var/www/html/pxe/centos8stream

### Fedora Server ###
sudo mkdir /var/www/html/pxe/fedora
sudo mount -t iso9660 -o loop,ro Fedora-Server-dvd-x86_64-36-1.5.iso /var/www/html/pxe/fedora

Mounted images can be checked with df command:

$ df -hT | grep /var/www/html/pxe
/dev/loop0     iso9660    10G   10G     0 100% /var/www/html/pxe/rockylinux8
/dev/loop1     iso9660   9.9G  9.9G     0 100% /var/www/html/pxe/almalinux8
/dev/loop2     iso9660    10G   10G     0 100% /var/www/html/pxe/oraclelinux8
/dev/loop3     iso9660    11G   11G     0 100% /var/www/html/pxe/centos8stream
/dev/loop4     iso9660   2.1G  2.1G     0 100% /var/www/html/pxe/fedora

List of files on each mount point:

$ ls /var/www/html/pxe/centos8stream
AppStream  BaseOS  EFI  LICENSE  TRANS.TBL  images  isolinux  media.repo

$ ls /var/www/html/pxe/rockylinux8/
AppStream  BaseOS  EFI  LICENSE  TRANS.TBL  images  isolinux  media.repo

$ ls /var/www/html/pxe/almalinux8
AppStream  BaseOS  EFI  TRANS.TBL  images  isolinux  media.repo

$ ls /var/www/html/pxe/oraclelinux8
AppStream  BaseOS  EFI  EULA  GPL  RELEASE-NOTES-en  RELEASE-NOTES-en.html  RPM-GPG-KEY  RPM-GPG-KEY-oracle  TRANS.TBL  extra_files.json  images  isolinux  media.repo

$ ls  /var/www/html/pxe/fedora
EFI  Fedora-Legal-README.txt  LICENSE  Packages  TRANS.TBL  images  isolinux  media.repo  repodata

View from a web browser:

Install-Virtual-Machines-on-KVM-using-PXE-Kickstart-02-1024x432

Copy Linux and initrd images to PXE boot directory /var/lib/tftpboot

Copy the files as indicated in the following commands for each Linux distribution.

### Rocky Linux 8 ###
sudo mkdir /var/lib/tftpboot/rockylinux8
sudo cp /var/www/html/pxe/rockylinux8/images/pxeboot/vmlinuz,initrd.img /var/lib/tftpboot/rockylinux8

### AlmaLinux 8 ###
sudo mkdir /var/lib/tftpboot/almalinux8
sudo cp /var/www/html/pxe/almalinux8/images/pxeboot/initrd.img,vmlinuz /var/lib/tftpboot/almalinux8

### Oracle Linux 8 ###
sudo mkdir /var/lib/tftpboot/oraclelinux8
sudo cp /var/www/html/pxe/oraclelinux8/images/pxeboot/initrd.img,vmlinuz /var/lib/tftpboot/oraclelinux8

### CentOS 8 Stream ###
sudo mkdir /var/lib/tftpboot/centos8stream
sudo cp /var/www/html/pxe/centos8stream/images/pxeboot/initrd.img,vmlinuz /var/lib/tftpboot/centos8stream

### Fedora Server ###
sudo mkdir /var/lib/tftpboot/fedora
sudo cp /var/www/html/pxe/fedora/images/pxeboot/initrd.img,vmlinuz /var/lib/tftpboot/fedora

Where:

  • initrd.img is the initial RAM disk image
  • vmlinuz is the OS Kernel

Tree structure of /var/lib/tftpboot after adding the directories and boot files.

$ sudo yum -y install tree
$ tree /var/lib/tftpboot/
/var/lib/tftpboot/
|-- almalinux8
|   |-- initrd.img
|   `-- vmlinuz
|-- centos8stream
|   |-- initrd.img
|   `-- vmlinuz
|-- fedora36
|   |-- initrd.img
|   `-- vmlinuz
|-- ldlinux.c32
|-- libcom32.c32
|-- libutil.c32
|-- menu.c32
|-- oraclelinux8
|   |-- initrd.img
|   `-- vmlinuz
|-- pxelinux.0
|-- pxelinux.cfg
|   `-- default
|-- rockylinux8
|   |-- initrd.img
|   `-- vmlinuz
`-- vesamenu.c32

6 directories, 17 files

Step 8 – Configure PXE Boot for manual OS installation without Kickstart

Let’s open the default PXE configuration file for editing.

sudo vim /var/lib/tftpboot/pxelinux.cfg/default

The following contents can be modified to work for the operating system you intend to install.

default menu.c32
#default vesamenu.c32
prompt 0
timeout 600
ONTIMEOUT 1

menu title ######## PXE Boot Menu ########
 label 1
 menu label ^1) Install Rocky Linux 8
 menu default
 kernel rockylinux8/vmlinuz
 append initrd=rockylinux8/initrd.img ip=dhcp inst.repo=http://192.168.177.2:8080/pxe/rockylinux8

 label 2
 menu label ^2) Install AlmaLinux 8
 menu default
 kernel almalinux8/vmlinuz
 append initrd=almalinux8/initrd.img ip=dhcp inst.repo=http://192.168.177.2:8080/pxe/almalinux8

 label 3
 menu label ^3) Install Oracle Linux 8
 menu default
 kernel oraclelinux8/vmlinuz
 append initrd=oraclelinux8/initrd.img ip=dhcp inst.repo=http://192.168.177.2:8080/pxe/oraclelinux8

 label 4
 menu label ^4) Install CentOS Stream 8
 menu default
 kernel centos8stream/vmlinuz
 append initrd=centos8stream/initrd.img ip=dhcp inst.repo=http://192.168.177.2:8080/pxe/centos8stream

 label 5
 menu label ^5) Install Fedora Server
 menu default
 kernel fedora/vmlinuz
 append initrd=fedora/initrd.img ip=dhcp inst.repo=http://192.168.177.2:8080/pxe/fedora

Step 9 – Configure PXE for Unattended installation using Kickstart

For better security, we generate encrypted root password:

python3 -c 'import crypt,getpass;pw=getpass.getpass();print(crypt.crypt(pw) if (pw==getpass.getpass("Confirm: ")) else exit())'

Inout and confirm password

Password: 
Confirm: 
$6$.4Cl.oED14zGg5qT$nDrjUFRjhDUS9L8dvYgsvhZLy20RykH7da.AiQspYDsvNJFYCchz9jbOmwY544WeC7exxrqGFb.Yea2YnaAMD1

Create a directory that will contain Kickstart files in your web server

sudo mkdir /var/www/html/ks

Creation of Kickstart file for each Linux distribution with ISO mounted.

### AlmaLinux 8 ###
sudo vim /var/www/html/ks/almalinux8-ks.cfg

### Rocky Linux 8 ###
sudo vim /var/www/html/ks/rockylinux8-ks.cfg

### Oracle Linux 8 ###
sudo vim /var/www/html/ks/oraclelinux8-ks.cfg

### CentoS 8 Stream ###
sudo vim /var/www/html/ks/centos8stream-ks.cfg

The following example shows a Kickstart file for an automatic installation of Rocky / AlmaLinux / Oracle / CentOS Stream 8 Linux. What is to be changed is installation source and AppStream baseurl.

# License agreement
eula --agreed

# Enable graphical installation
graphical

#Base installation source
url --url="http://192.168.177.2:8080/pxe/rockylinux8"

# AppStream installation source
repo --name="AppStream" --baseurl=http://192.168.177.2:8080/pxe/rockylinux8/AppStream

#Network bootproto and hostname
network --bootproto=dhcp --hostname=localhost.localdomain

# Encrypted root password
rootpw --iscrypted replace-me-with-encrypted-password
#rootpw --plaintext root_password_in_clear_text

# System Locale
lang en_US.UTF-8

# Keyboard layout
keyboard --vckeymap=us --xlayouts='us'

#Timezone
timezone Africa/Nairobi --isUtc

# Run the Setup Agent on first boot
firstboot --enable

#Initialize partition tables
ignoredisk --only-use=vda
zerombr
clearpart --none --initlabel

#Single / partion
##autopart
autopart --nohome --nolvm --noboot

#Reboot after installation
reboot

#Packages to install
%packages --ignoremissing --instLangs=en_US.utf8
@^graphical-server-environment
kexec-tools
vim
bash-completion
openssh-clients
selinux-policy-devel
net-tools
bzip2
rsync
dnf-utils
network-scripts
%end

Fedora Linux Kickstart file:

# License agreement
eula --agreed

# Enable graphical installation
graphical

#Base installation source
url --url="http://192.168.177.2:8080/pxe/fedora"

#Network bootproto and hostname
network --bootproto=dhcp --hostname=localhost.localdomain

# Encrypted root password
rootpw --iscrypted replace-me-with-encrypted-password
#rootpw --plaintext root_password_in_clear_text

# System Locale
lang en_US.UTF-8

# Keyboard layout
keyboard --vckeymap=us --xlayouts='us'

#Timezone
timezone Africa/Nairobi --isUtc

# Run the Setup Agent on first boot
firstboot --enable

#Initialize partition tables
ignoredisk --only-use=vda
zerombr
clearpart --none --initlabel

#Single / partion
##autopart
autopart --nohome --nolvm --noboot

#Reboot after installation
reboot

#Packages to install
%packages --ignoremissing --instLangs=en_US.utf8
@Desktop
kexec-tools
vim
bash-completion
openssh-clients
selinux-policy-devel
net-tools
bzip2
rsync
dnf-utils
network-scripts
%end

List of kickstart files as stored in the web server

Install-Virtual-Machines-on-KVM-using-PXE-Kickstart-03-1024x442

For more reading on Kickstart, check out:

Update /var/lib/tftpboot/pxelinux.cfg/default file

Updated contents of /var/lib/tftpboot/pxelinux.cfg/default file to include kickstart location.

#default menu.c32
default vesamenu.c32
prompt 0
timeout 600
ONTIMEOUT 1
display boot.msg

menu title ######## PXE Boot Menu ########
 label 1
 menu label ^1) Install Rocky Linux 8
 menu default
 kernel rockylinux8/vmlinuz
 append initrd=rockylinux8/initrd.img ip=dhcp inst.repo=http://192.168.177.2:8080/pxe/rockylinux8 inst.ks=http://192.168.177.2:8080/ks/rockylinux8-ks.cfg

 label 2
 menu label ^2) Install AlmaLinux 8
 menu default
 kernel almalinux8/vmlinuz
 append initrd=almalinux8/initrd.img ip=dhcp inst.repo=http://192.168.177.2:8080/pxe/almalinux8 inst.ks=http://192.168.177.2:8080/ks/almalinux8-ks.cfg

 label 3
 menu label ^3) Install Oracle Linux 8
 menu default
 kernel oraclelinux8/vmlinuz
 append initrd=oraclelinux8/initrd.img ip=dhcp inst.repo=http://192.168.177.2:8080/pxe/oraclelinux8 inst.ks=http://192.168.177.2:8080/ks/oraclelinux8-ks.cfg

 label 4
 menu label ^4) Install CentOS Stream 8
 menu default
 kernel centos8stream/vmlinuz
 append initrd=centos8stream/initrd.img ip=dhcp inst.repo=http://192.168.177.2:8080/pxe/centos8stream inst.ks=http://192.168.177.2:8080/ks/centos8stream-ks.cfg

 label 5
 menu label ^5) Install Fedora Server
 menu default
 kernel fedora/vmlinuz
 append initrd=fedora/initrd.img ip=dhcp inst.repo=http://192.168.177.2:8080/pxe/fedora inst.ks=http://192.168.177.2:8080/ks/fedora-ks.cfg

Explanation of key directives used:

  • ip=dhcp to obtain an IP address using DHCP
  • inst.ks directive points to a shared URL for the Kickstart file.

Save the file and proceed to usage step.

Step 10 – Create a Virtual Machine using PXE Boot

We’ll consider both command-line and Graphical interface installation.

PXE Booting through Virt-install

Installation from Virt-install command line interface:

sudo virt-install --connect qemu:///system \
    --name testvm \
    --network=bridge:br0 --pxe \
    --ram=2048 \
    --vcpus=2 \
    --os-type=linux --os-variant=rhl8.0 \
    --disk path=/var/lib/libvirt/images/testvm.qcow2,size=40

Installation through PXE using Virt-manager

Access Virt-Manager and create new Virtual Machine. Choose “Manual install“.

kvm-create-vm-pxe-01

Choose operating system type, assign resources and give it a name.

kvm-create-vm-pxe-03

Finish creation and Power-off the Virtual Machine. Once the VM is down, edit its settings under “Boot Options

kvm-create-vm-pxe-04

Tick “NIC” in the Boot device menu check boxes.

kvm-create-vm-pxe-05

Start the Virtual Machine and it should start requesting IP address

Install-Virtual-Machines-on-KVM-using-PXE-Kickstart-04-1024x561

You should see PXE Boot menu, choose your OS from the list to initiate installation.

Install-Virtual-Machines-on-KVM-using-PXE-Kickstart-05-1024x570

The normal OS installation screen should be presented to you after few seconds.

Install-Virtual-Machines-on-KVM-using-PXE-Kickstart-06-1024x772

Manual installation without Kickstart

When using Kickstart automation, manual intervention is not required.

Install-Virtual-Machines-on-KVM-using-PXE-Kickstart-10-1024x233

All pre-configurations and OS installation process begins automatically.

Install-Virtual-Machines-on-KVM-using-PXE-Kickstart-11-1024x756

Relax as the automated installation takes effect. In a few minutes your system will be ready for use.

Install-Virtual-Machines-on-KVM-using-PXE-Kickstart-12-1024x767

Below is a screenshot of automated Fedora Server installation.

Install-Virtual-Machines-on-KVM-using-PXE-Kickstart-14-1024x763

Conclusion

It is a fact that when installing Enterprise Linux operating systems on a large number of systems simultaneously, a better approach is to boot from a PXE server with installation files hosted in shared network location(FTP,HTTP,NFS). For unattended deployment, Kickstart gives you a way to fully automate the installation process of the OS. The Kickstart files contain answers to all questions normally asked by the installation program.

 

coffee

Gravatar Image
A systems engineer with excellent skills in systems administration, cloud computing, systems deployment, virtualization, containers, and a certified ethical hacker.