RHEL Installation uses the Anaconda installer — it can run interactively with a GUI or automatically using Kickstart configuration files.
Administrator makes choices through GUI screens. Good for unique systems, learning, or when requirements are unclear.
Configuration file provides all answers. Good for deploying many identical systems, ensuring consistency, and automation.
RHEL installation requires boot media and package sources. These can be the same (DVD) or separate (network boot + network repo).
| Media Type | Description | Use Case |
|---|---|---|
| DVD ISO | Full image (~10GB), all packages | Standalone, no network needed |
| Boot ISO | Minimal boot (~800MB), network packages | Network installs, latest packages |
| USB Drive | DVD or Boot ISO written to USB | Physical servers, no optical drive |
| PXE Boot | Network boot, no local media | Data center deployments, automation |
# Create bootable USB from ISO (Linux)
[root@workstation ~]# dd if=rhel-9.3-x86_64-dvd.iso \
of=/dev/sdb bs=4M status=progress
# Warning: This destroys all data on /dev/sdb!
# Always verify USB device name first
[root@workstation ~]# lsblk
⚠ Specifying the wrong device with dd destroys data. Always verify with lsblk first.
For RHCSA, focus on DVD/USB installations. PXE boot requires additional TFTP infrastructure and is more advanced.
When you boot from RHEL installation media, you see a boot menu:
Press Tab to edit boot options on the selected entry.
Press e for full GRUB-style editing.
# Press Tab at boot menu, then append options:
vmlinuz initrd=initrd.img inst.stage2=hd:LABEL=RHEL-9-3 quiet \
inst.ks=http://server/ks.cfg
# Common boot parameters:
# inst.ks=URL - Kickstart file location
# inst.repo=URL - Package repository location
# inst.vnc - Enable VNC for remote installation
# inst.text - Force text mode installation
inst.ks — essential for Kickstart automationinst.vnc — graphical install on headless systemsinst.text — text mode for systems without graphicsThe hub-and-spoke design lets you configure items in any order. Items marked ⚠ require attention before installation can proceed.
Begin Installation is disabled until all required items are configured.
Select the disk, then choose automatic or custom partitioning.
/boot - 1 GB (xfs)
/boot/efi - 600 MB (UEFI only)
/ - Remaining (LVM/xfs)
swap - Based on RAM
/home - User data
(survives reinstalls)
/var - Logs, databases
/tmp - Temporary files
RHEL 9 default: LVM with XFS filesystems — provides flexibility to resize volumes later.
/boot must be outside LVM for BIOS boot systems/boot/efi is required on UEFI systems/home preserves user data across reinstalls/var for systems with large logs or databasesFor RHCSA, understand both automatic and custom partitioning and required vs. recommended partitions.
Choose a base environment — easier to add packages later than to remove unnecessary ones.
| Base Environment | Description | Approx. Pkgs |
|---|---|---|
| Server with GUI | Full graphical server | ~1400 |
| Server | Command-line, common services | ~400 |
| Minimal Install | Bare minimum | ~300 |
| Workstation | Desktop with dev tools | ~1800 |
| Custom OS | Core only, you select everything | ~250 |
| Virtualization Host | KVM hypervisor and management | ~500 |
Best practice: Start minimal, add with dnf. Reduces attack surface and install time.
# Static IP configuration:
IPv4 Method: Manual
Address: 192.168.1.100
Netmask: 255.255.255.0 (or /24)
Gateway: 192.168.1.1
DNS: 192.168.1.1, 8.8.8.8
# Hostname — use FQDN when possible:
server1.example.com (recommended)
webserver01 (short name)
⚠ Network interfaces are disabled by default during installation. Enable them here if needed.
Network must be enabled during installation for:
Even when not strictly required, configuring network during installation saves post-installation work. Configuration persists to the installed system.
wheel group (sudo)In enterprise environments, individual administrator accounts are preferred over shared root — each person logs in as themselves, gains privileges with sudo, and all actions are logged.
# Installation sequence:
# 1. Disk partitioning applied (destructive!)
# 2. Filesystems created and formatted
# 3. Packages installed from source
# 4. GRUB2 bootloader installed
# 5. Initial configuration applied
# 6. Reboot button appears
⚠ Point of no return — disk changes applied immediately, destroying existing data on selected disks.
Remove installation media before rebooting so the system boots from the installed disk.
Kickstart automates RHEL installation by providing answers to all installer questions in a configuration file. The system installs without human intervention.
Kickstart files have four main sections — order matters:
%packages and %end%pre (before install) and %post (after install)Comments start with # and are ignored. Each Kickstart command maps to an Anaconda screen option.
# 1. Command Section
text
url --url="http://repo/rhel9"
keyboard --vckeymap=us
lang en_US.UTF-8
timezone America/New_York
rootpw --iscrypted $6$...
# 2. Disk Configuration
clearpart --all --initlabel
autopart
bootloader --location=mbr
# 3. Package Section
%packages
@^minimal-environment
vim-enhanced
-plymouth
%end
# 4. Scripts (optional)
%post
echo "Post-install script"
%end
# Installation source
url --url="http://server/rhel9/BaseOS"
cdrom # Use attached DVD/ISO
nfs --server=nfs.example.com --dir=/exports/rhel9
# Network — DHCP
network --bootproto=dhcp --device=eth0 --activate
# Network — Static IP
network --bootproto=static \
--ip=192.168.1.100 \
--netmask=255.255.255.0 \
--gateway=192.168.1.1 \
--nameserver=8.8.8.8 \
--hostname=server1.example.com
Include --activate to bring up the interface during installation.
# User accounts
rootpw --plaintext redhat123 # Not recommended
rootpw --iscrypted $6$rounds=... # Use this in production
rootpw --lock # Lock root account
user --name=alice \
--iscrypted --password=$6$... \
--groups=wheel
# Installation behavior
text # Text mode (faster)
graphical # GUI mode
reboot # Auto-reboot when done
poweroff # Shut down when done
firstboot --disabled # Skip first-boot wizard
Generate hashes: python3 -c "import crypt; print(crypt.crypt('password'))"
# Clear and initialize disk
zerombr # Clear MBR if invalid
clearpart --all --initlabel # Remove all partitions
clearpart --drives=sda # Clear specific disk only
# Automatic partitioning (recommended for most)
autopart # Default LVM layout
autopart --type=lvm # Explicitly use LVM
autopart --type=plain # Standard partitions, no LVM
# Bootloader
bootloader --location=mbr --boot-drive=sda
Always include --initlabel with clearpart to create a new partition table.
# Physical partitions
part /boot --fstype=xfs --size=1024
part /boot/efi --fstype=efi --size=600 # UEFI systems
part pv.01 --size=1 --grow # LVM physical volume
# Volume group and logical volumes
volgroup rhel pv.01
logvol / --vgname=rhel --name=root \
--fstype=xfs --size=10240
logvol /home --vgname=rhel --name=home \
--fstype=xfs --size=5120
logvol swap --vgname=rhel --name=swap \
--size=2048
Sizes in megabytes. Use --grow to fill remaining space. Bad disk config fails immediately — verify carefully.
%packages
# Environment groups (@^ prefix)
@^minimal-environment # Minimal install
@^server-product-environment # Server
# Package groups (@ prefix)
@development # Development Tools
@security-tools # Security tools
# Individual packages
vim-enhanced
tmux
httpd
# Exclude packages (- prefix)
-plymouth # Remove boot splash
-iwl*firmware # Remove WiFi firmware
%end
Find group names: dnf group list --hidden on an existing RHEL system.
--nochroot to access installer envYou can have multiple %post sections with different options. Default interpreter is bash; use --interpreter=/usr/bin/python3 for Python scripts.
%pre
echo "Starting at $(date)" > /tmp/install.log
%end
%post
# Enable services
systemctl enable httpd
systemctl enable firewalld
# Create message of the day
cat > /etc/motd << EOF
Deployed via Kickstart on $(date)
EOF
dnf -y update
%end
%post --nochroot
# Copy from installer environment to new system
cp /tmp/install.log /mnt/sysimage/root/
%end
Three approaches — easiest to hardest:
/root/, recording exactly what was doneFor enterprise use: start from a known-good config, maintain in version control, and modify incrementally.
# View auto-generated Kickstart from completed install
[root@server ~]# cat /root/anaconda-ks.cfg
# Copy and customize for new deployments
[root@server ~]# cp /root/anaconda-ks.cfg /var/www/html/ks.cfg
[root@server ~]# vi /var/www/html/ks.cfg
# Install validation tools
[root@server ~]# dnf install pykickstart
# Validate syntax (no output = valid)
[root@server ~]# ksvalidator /var/www/html/ks.cfg
# Compare two Kickstart files
[root@server ~]# ksdiff ks1.cfg ks2.cfg
Always run ksvalidator before deploying. Better to find errors before booting systems.
# Boot parameter to specify Kickstart location:
inst.ks=URL
# HTTP server (most common)
inst.ks=http://192.168.1.10/ks.cfg
inst.ks=http://server.example.com/kickstart/webserver.cfg
# NFS share
inst.ks=nfs:server.example.com:/exports/ks.cfg
# USB drive or DVD
inst.ks=hd:sdb1:/ks.cfg
inst.ks=cdrom:/ks.cfg
HTTP is most common — easy to update centrally, version control, and serve multiple configs for different server roles.
At the boot menu, press Tab and append the Kickstart parameter:
vmlinuz initrd=initrd.img inst.stage2=hd:LABEL=RHEL-9-3 \
inst.ks=http://server/ks.cfg
If using a Boot ISO (no packages on media), also specify the repo:
inst.ks=http://server/ks.cfg inst.repo=http://server/rhel9/
# Installation settings
text
url --url="http://repo.example.com/rhel9/BaseOS"
repo --name="AppStream" \
--baseurl="http://repo.example.com/rhel9/AppStream"
keyboard --vckeymap=us
lang en_US.UTF-8
timezone America/New_York --utc
network --bootproto=dhcp --device=eth0 --activate
network --hostname=webserver1.example.com
rootpw --iscrypted $6$rounds=4096$salt$hashedpassword
user --name=admin --groups=wheel \
--iscrypted --password=$6$...
zerombr
clearpart --all --initlabel
autopart
bootloader --location=mbr
firewall --enabled \
--service=ssh --service=http --service=https
selinux --enforcing
firstboot --disabled
reboot
%packages
@^minimal-environment
httpd
mod_ssl
vim-enhanced
%end
%post
systemctl enable httpd
%end
Boot with inst.ks pointing to this file and get a consistent, secure web server every time.
inst.ks=URL at boot for consistent automated deployment./root/anaconda-ks.cfg from an existing install. Validate with ksvalidator./home partitionanaconda-ks.cfg from the completed install%post script to enable services and create configuration filesNext: Managing Software with DNF and Repositories