Red Hat Enterprise Linux 9 — Release Summary & Best Practices
Red Hat Enterprise Linux 9 — Release Summary & Best Practices
Release Summary
Red Hat Enterprise Linux 9 (RHEL 9) was released in May 2022, based on CentOS Stream 9 and the Linux kernel 5.14. It is the current production workhorse for most enterprise Red Hat deployments and represents a significant modernization over RHEL 8 — particularly around security defaults, container tooling, and observability. RHEL 9 is currently in Full Support and is the recommended version for all new deployments.
Key Highlights
| Area | Detail |
|---|---|
| Kernel | 5.14 base — updated per minor release (9.1 → 9.2 → 9.3 → 9.4) |
| Python | Python 3.9 default; 3.11 available via module streams |
| Security | SHA-1 deprecated in signatures; OpenSSH uses Ed25519 by default |
| Networking | nftables default (iptables deprecated); NetworkManager mandatory |
| Storage | XFS default; Stratis 2.x for advanced storage management |
| Init | systemd 250 |
| Containers | Podman 4.x default; Buildah and Skopeo included |
| Web Console | Cockpit with enhanced performance monitoring |
| Observability | Performance Co-Pilot (PCP) deeply integrated |
| Support Lifecycle | Full Support until 2027; Maintenance until 2032; ELS until 2035 |
Notable Changes from RHEL 8
- nftables replaces iptables as the default packet filtering framework (iptables still available but deprecated)
- ifcfg network scripts deprecated — use NetworkManager keyfiles instead (mandatory in RHEL 10)
- OpenSSL 3.0 — significant API/ABI changes for compiled applications
- SSH root login disabled by default
- SHA-1 deprecated for digital signatures across all system crypto policies
- nsswitch.conf now managed exclusively by authselect
- ReaR (Relax-and-Recover) is the supported bare metal backup/recovery tool
Minor Release Timeline
| Release | Date | Kernel |
|---|---|---|
| RHEL 9.0 | May 2022 | 5.14.0-70 |
| RHEL 9.1 | Nov 2022 | 5.14.0-162 |
| RHEL 9.2 | May 2023 | 5.14.0-284 |
| RHEL 9.3 | Nov 2023 | 5.14.0-362 |
| RHEL 9.4 | May 2024 | 5.14.0-427 |
| RHEL 9.5 | Nov 2024 | 5.14.0-503 |
Installation Best Practices
- Use Kickstart files for automated, reproducible installs — store in version control alongside your infrastructure code
- During partitioning, separate
/var,/tmp,/home,/boot, and/boot/efionto dedicated logical volumes - Use the Minimal Install base environment for servers — add only required packages post-install
- Register immediately after install:
subscription-manager register --auto-attach - Apply all available updates before first use:
dnf update -y && reboot - Disable unused services at install time — use
systemctl disableor Kickstartservices --disabled
Security Best Practices
System Crypto Policies
RHEL 9 uses a unified crypto policy framework — this is your primary lever for compliance:
# Check current policy
update-crypto-policies --show
# Set to FIPS (required for many regulatory frameworks)
update-crypto-policies --set FIPS
reboot # Required after FIPS change
# Available policies: DEFAULT, FUTURE, FIPS, LEGACY (avoid)
- Never use LEGACY policy in production — it re-enables weak ciphers including RC4 and DH < 1024-bit
- FUTURE policy is stricter than DEFAULT — good for high-security environments
- SHA-1 is deprecated but not fully disabled in RHEL 9 DEFAULT — use FUTURE or FIPS to disable it completely
SSH Hardening
# /etc/ssh/sshd_config
PermitRootLogin no
PasswordAuthentication no
PubkeyAuthentication yes
X11Forwarding no
MaxAuthTries 3
ClientAliveInterval 300
ClientAliveCountMax 2
AllowGroups ssh-users
Banner /etc/issue.net
# Restart SSH after changes
systemctl restart sshd
# Verify configuration
sshd -T | grep -i 'permitroot\|passwordauth'
SELinux
# Verify status
getenforce # Should return: Enforcing
sestatus # Full status
# Never do this in production:
# setenforce 0
# sed -i 's/SELINUX=enforcing/SELINUX=disabled/' /etc/selinux/config
# Troubleshoot denials instead
ausearch -m avc -ts recent
audit2why < /var/log/audit/audit.log
audit2allow -a # Review before applying
- Always fix SELinux denials with proper policy — disabling is not a fix
- Use
semanage port -a -t http_port_t -p tcp 8443to allow custom ports for known services - Enable
dontauditrules selectively to reduce noise without weakening policy
Firewall
# List current configuration
firewall-cmd --list-all
# Add a service permanently
firewall-cmd --permanent --add-service=https
firewall-cmd --reload
# Add a custom port
firewall-cmd --permanent --add-port=8443/tcp
firewall-cmd --reload
# Remove a service (lock down defaults)
firewall-cmd --permanent --remove-service=dhcpv6-client
firewall-cmd --reload
- Use zones to segment traffic — don't dump everything into the
publiczone - Block ICMP redirects and IP source routing: set kernel parameters via
/etc/sysctl.d/ - Enable connection tracking logging for audit trails
Kernel Hardening (sysctl)
# /etc/sysctl.d/99-hardening.conf
net.ipv4.ip_forward = 0
net.ipv4.conf.all.send_redirects = 0
net.ipv4.conf.default.send_redirects = 0
net.ipv4.conf.all.accept_redirects = 0
net.ipv4.conf.all.log_martians = 1
net.ipv4.tcp_syncookies = 1
kernel.randomize_va_space = 2
kernel.dmesg_restrict = 1
fs.protected_hardlinks = 1
fs.protected_symlinks = 1
# Apply without reboot
sysctl -p /etc/sysctl.d/99-hardening.conf
Networking Best Practices
RHEL 9 strongly favors NetworkManager — configure via nmcli, nmtui, or keyfiles:
# Show all connections
nmcli connection show
# Configure static IP
nmcli connection modify "Wired connection 1" \
ipv4.method manual \
ipv4.addresses 10.10.100.30/24 \
ipv4.gateway 10.10.100.1 \
ipv4.dns "10.10.100.10 10.10.100.11"
nmcli connection up "Wired connection 1"
# Disable IPv6 on a connection if required
nmcli connection modify eth0 ipv6.method disabled
- Set hostname correctly:
hostnamectl set-hostname server01.casino.local - Configure NTP via chrony:
dnf install chrony && systemctl enable --now chronyd - Verify time sync:
chronyc trackingandchronyc sources - Use bonding or teaming for NIC redundancy on physical hosts
Storage Best Practices
# Check filesystem usage
df -hT
# Extend an LVM logical volume + filesystem online
lvextend -L +10G /dev/mapper/rhel-var
xfs_growfs /var
# Check XFS filesystem health
xfs_info /var
xfs_repair -n /dev/sdb1 # -n = dry run, no changes
# Enable fstrim for SSDs
systemctl enable --now fstrim.timer
- Mount
/tmpontmpfsfor security and performance on stateless systems:systemctl enable --now tmp.mount - Use
nodev,nosuid,noexecmount options on/tmp,/home, and removable media - Set disk quotas on
/homeif it's shared storage
System Management Best Practices
Patching with DNF
# List available security advisories
dnf updateinfo list security
# Apply security patches only
dnf update --security -y
# Apply a specific advisory
dnf update --advisory RHSA-2024:1234 -y
# Exclude a package from updates (use sparingly)
dnf update --exclude=kernel* -y
# Check history and roll back if needed
dnf history list
dnf history undo <ID>
Service Management
# List all failed services
systemctl --failed
# Check service status and recent logs
systemctl status sshd
journalctl -u sshd -n 50 --no-pager
# Enable and start a service
systemctl enable --now httpd
# Mask a service to prevent it from starting under any condition
systemctl mask bluetooth
Log Management
# View logs for a specific time range
journalctl --since "2024-01-01" --until "2024-01-02"
# Follow logs for a unit
journalctl -fu httpd
# Export logs to file
journalctl --since today > /tmp/today-logs.txt
# Check disk usage of journal
journalctl --disk-usage
Configure persistent logging:
# /etc/systemd/journald.conf
Storage=persistent
SystemMaxUse=2G
SystemKeepFree=500M
Compress=yes
Performance Monitoring
# Quick system overview
top
htop # if installed
# CPU/IO stats
iostat -xz 5
vmstat 5
# Memory details
free -h
cat /proc/meminfo
# Performance Co-Pilot (built into RHEL 9)
dnf install pcp pcp-system-tools
systemctl enable --now pmcd
pmstat # System-level stats
pmrep # Report-format metrics
Container Best Practices (Podman 4.x)
# Pull and run a container
podman pull registry.access.redhat.com/ubi9/ubi:latest
podman run -it --rm ubi9/ubi:latest bash
# Run as a systemd service (rootful)
podman run -d --name nginx -p 80:80 nginx:latest
podman generate systemd --name nginx --files --new
cp container-nginx.service /etc/systemd/system/
systemctl daemon-reload
systemctl enable --now container-nginx
# Rootless container
podman run -d --name myapp --userns=keep-id myimage:latest
- Use Red Hat Universal Base Images (UBI) as your base — supported, scannable, redistributable
- Scan images before deployment:
podman scan myimage:latest(requires subscription) - Use SELinux labels for container volumes:
podman run -v /data:/data:Z myimage - Enable auto-update for containers:
podman auto-updatewithio.containers.autoupdate=registrylabel
Automation Integration
# Install RHEL System Roles
dnf install rhel-system-roles
# Example: Apply timesync role
cat > timesync.yml << 'EOF'
---
- hosts: all
roles:
- rhel-system-roles.timesync
vars:
timesync_ntp_servers:
- hostname: time.casino.local
iburst: yes
EOF
ansible-playbook -i inventory timesync.yml
- Use Red Hat Insights for proactive risk identification —
insights-client --register - Integrate with Ansible Automation Platform for at-scale patching, hardening, and drift remediation
- Use OpenSCAP for automated compliance scanning:
dnf install openscap-scanner scap-security-guide oscap xccdf eval --profile xccdf_org.ssgproject.content_profile_cis \ --results results.xml \ /usr/share/xml/scap/ssg/content/ssg-rhel9-ds.xml
RHEL 9 support lifecycle: Full Support until 2027 · Maintenance until 2032 · Extended Life until 2035
No comments to display
No comments to display