Thursday, July 2, 2026

How To Increase a Logical Volume (System Partition) on a Red Hat Enterprise Linux (RHEL) 9.x Virtual Server

Warning:  Do not attempt this procedure on a production system without making a reliable backup.  If done incorrectly there is the potential to destroy the virtual disk and require a complete re-install of the system. This article also assumes the underlying Linux file systems are the Red Hat Enterprise Linux default type XFS. 

Let's say you notice after you built a RHEL 9.x server that the /var/log partition isn't large enough and that it needs to be 2 Gig instead of 1 Gig. 

Take note of the existing partition table for the system's virtual disk.

# lsblk
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINTS
sr0 11:0 1 1024M 0 rom
vda 252:0 0 85G 0 disk
├─vda1 252:1 0 1G 0 part /boot/efi
├─vda2 252:2 0 1G 0 part /boot
└─vda3 252:3 0 83G 0 part
├─rhel_rhel98-root 253:0 0 20G 0 lvm /
├─rhel_rhel98-swap 253:1 0 8G 0 lvm [SWAP]
├─rhel_rhel98-var_log 253:2 0 1G 0 lvm /var/log
├─rhel_rhel98-tmp 253:3 0 10G 0 lvm /tmp
├─rhel_rhel98-var 253:4 0 20G 0 lvm /var
├─rhel_rhel98-home 253:5 0 20G 0 lvm /home
├─rhel_rhel98-var_tmp 253:6 0 2G 0 lvm /var/tmp
└─rhel_rhel98-var_log_audit 253:7 0 2G 0 lvm /var/log/audit

Notice that the /dev/vda3 partition is the last partition on the disk and it has the partition type for containing Linux logical volumes.  

# fdisk -l /dev/vda
Disk /dev/vda: 85 GiB, 91268055040 bytes, 178257920 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: gpt
Disk identifier: F01214C1-2860-4C76-9C65-AF38B27671F5

Device       Start       End   Sectors Size Type
/dev/vda1     2048   2099199   2097152   1G EFI System
/dev/vda2  2099200   4196351   2097152   1G Linux filesystem
/dev/vda3  4196352 178255871 174059520  83G Linux LVM

Here is a brief overview of how we will accomplish adding additional disk space to the virtual machine and then to the /var/log logical volume.  

  • Shutdown the VM/virtual server
  • Extend the underlying virtual disk from the hypervisor
  • Boot the VM back up.  
  • Delete the /dev/vda3 partition from the partition table
  • Re-create the /dev/vda3 partition with the additional new sectors
  • Write the new partition table to the virtual disk
  • Update the logical volume manager's physical volume to see the added space
  • Allocate new space to the /var/log logical volume.

Our hypervisor for this example is running QEMU, KVM and Virt-Manager on Ubuntu.

 Setting Up Virtual Machines with QEMU, KVM, and Virt-Manager on Debian/Ubuntu

On this system we need to use the virsh command line utility on the host (hypervisor) to increase the underlying virtual disk.  On a VMware system we would use the VSphere web GUI to increase the underlying disk.  

Below we find the location for the hypervisor file that contains our virtual disk and then increase it's size. But before that we need to shutdown our RHEL 9.x server from within the VM.

# shutdown -h now
Broadcast message from root@RHEL98 on pts/1 (Fri 2026-06-26 15:57:35 EDT):

The system will power off now!

From command line on the hypervisor system.

$ virsh list --all
 Id   Name     State
------------------------
 -    RHEL98   shut off

$ virsh dominfo RHEL98
Id: -
Name: RHEL98
UUID: 5529e3e2-6610-4c69-bf4c-6da0dc34f945
OS Type: hvm
State: shut off
CPU(s): 4
CPU time: 339.9s
Max memory: 4194304 KiB
Used memory: 4194304 KiB
Persistent: yes
Autostart: disable
Managed save: no
Security model: apparmor
Security DOI: 0

$ virsh domblklist RHEL98
Target Source
------------------------------------------------
vda /var/lib/libvirt/images/RHEL98.qcow2
sda -

$ sudo qemu-img resize /var/lib/libvirt/images/RHEL98.qcow2 +1G
Image resized.

Restart the VM with the command below or use the virt-manager GUI application.

$ virsh start RHEL98
Domain 'RHEL98' started

Secure shell back into the VM and inspect the partition table

$ sudo -i
[sudo] password for john: 

# fdisk -l /dev/vda
GPT PMBR size mismatch (178257919 != 180355071) will be corrected by write.
The backup GPT table is not on the end of the device.
Disk /dev/vda: 86 GiB, 92341796864 bytes, 180355072 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: gpt
Disk identifier: F01214C1-2860-4C76-9C65-AF38B27671F5

Device       Start       End   Sectors Size Type
/dev/vda1     2048   2099199   2097152   1G EFI System
/dev/vda2  2099200   4196351   2097152   1G Linux filesystem
/dev/vda3  4196352 178255871 174059520  83G Linux LVM

Now we will delete and recreate the partition table.
# fdisk /dev/vda

Welcome to fdisk (util-linux 2.37.4).
Changes will remain in memory only, until you decide to write them.
Be careful before using the write command.

GPT PMBR size mismatch (178257919 != 180355071) will be corrected by write.
The backup GPT table is not on the end of the device. This problem will be corrected by write.
This disk is currently in use - repartitioning is probably a bad idea.
It's recommended to umount all file systems, and swapoff all swap
partitions on this disk.



Command (m for help): d (delete a partition)
Partition number (1-3, default 3): 3

Partition 3 has been deleted.

Command (m for help): n (add a new partition)
Partition number (3-128, default 3): 3
First sector (4196352-180355038, default 4196352): <Enter>
Last sector, +/-sectors or +/-size{K,M,G,T,P} (4196352-180355038, default 180355038): <Enter>

Created a new partition 3 of type 'Linux filesystem' and of size 84 GiB.
Partition #3 contains a LVM2_member signature.

Do you want to remove the signature? [Y]es/[N]o: N

Command (m for help): t (change partition type)
Partition number (1-3, default 3): 3
Partition type or alias (type L to list all): L
...
 19 Linux swap                     0657FD6D-A4AB-43C4-84E5-0933C84B4F4F
20 Linux filesystem 0FC63DAF-8483-4772-8E79-3D69D8477DE4
21 Linux server data 3B8F8425-20E0-4F3B-907F-1A25A76F98E8
22 Linux root (x86) 44479540-F297-41B2-9AF7-D131D5F0458A
23 Linux root (x86-64) 4F68BCE3-E8CD-4DB1-96E7-FBCAF984B709
24 Linux root (ARM) 69DAD710-2CE4-4E3C-B16C-21A1D49ABED3
25 Linux root (ARM-64) B921B045-1DF0-41C3-AF44-4C6F280D3FAE
26 Linux root (IA-64) 993D8D3D-F80E-4225-855A-9DAF8ED7EA97
27 Linux reserved 8DA63339-0007-60C0-C436-083AC8230908
28 Linux home 933AC7E1-2EB4-4F13-B844-0E14E2AEF915
29 Linux RAID A19D880F-05FC-4D3B-A006-743F0F84911E
30 Linux LVM E6D6D379-F507-44C2-A23C-238F2A3DF928
31 Linux variable data 4D21B016-B534-45C2-A9FB-5C16E091FD2D
32 Linux temporary data 7EC6F557-3BC5-4ACA-B293-16EF5DF639D1
33 Linux /usr (x86) 75250D76-8CC6-458E-BD66-BD47CC81A812
34 Linux /usr (x86-64) 8484680C-9521-48C6-9C11-B0720656F69E
35 Linux /usr (ARM) 7D0359A3-02B3-4F0A-865C-654403E70625
36 Linux /usr (ARM-64) B0E01050-EE5F-4390-949A-9101B17104E9
37 Linux /usr (IA-64) 4301D2A6-4E3B-4B2A-BB94-9E0B2C4225EA
38 Linux root verity (x86) D13C5D3B-B5D1-422A-B29F-9454FDC89D76
39 Linux root verity (x86-64) 2C7357ED-EBD2-46D9-AEC1-23D437EC2BF5
40 Linux root verity (ARM) 7386CDF2-203C-47A9-A498-F2ECCE45A2D6
41 Linux root verity (ARM-64) DF3300CE-D69F-4C92-978C-9BFB0F38D820
42 Linux root verity (IA-64) 86ED10D5-B607-45BB-8957-D350F23D0571
43 Linux /usr verity (x86) 8F461B0D-14EE-4E81-9AA9-049B6FB97ABD
44 Linux /usr verity (x86-64) 77FF5F63-E7B6-4633-ACF4-1565B864C0E6
45 Linux /usr verity (ARM) C215D751-7BCD-4649-BE90-6627490A4C05
46 Linux /usr verity (ARM-64) 6E11A4E7-FBCA-4DED-B9E9-E1A512BB664E
47 Linux /usr verity (IA-64) 6A491E03-3BE7-4545-8E38-83320E0EA880
48 Linux extended boot BC13C2FF-59E6-4262-A352-B275FD6F7172
49 Linux user's home 773f91ef-66d4-49b5-bd83-d683bf40ad16
...
Partition type or alias (type L to list all): 30 (will not always be this number)

Changed type of partition 'Linux filesystem' to 'Linux LVM'.

Command (m for help): p (print the partition table)

Disk /dev/vda: 86 GiB, 92341796864 bytes, 180355072 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: gpt
Disk identifier: F01214C1-2860-4C76-9C65-AF38B27671F5

Device Start End Sectors Size Type
/dev/vda1 2048 2099199 2097152 1G EFI System
/dev/vda2 2099200 4196351 2097152 1G Linux filesystem
/dev/vda3 4196352 180355038 176158687 84G Linux LVM

Command (m for help): w (write table to disk and exit)
The partition table has been altered.
Syncing disks.
Now make sure the Red Hat OS sees the change.

# partprobe
# partx -u /dev/vda

Resize the physical volume Red Hat sees.

# pvs
  PV         VG          Fmt  Attr PSize   PFree
  /dev/vda3  rhel_rhel98 lvm2 a--  <83.00g    0 

# pvresize /dev/vda3
  Physical volume "/dev/vda3" changed
  1 physical volume(s) resized or updated / 0 physical volume(s) not resized

# pvs
  PV         VG          Fmt  Attr PSize   PFree
  /dev/vda3  rhel_rhel98 lvm2 a--  <84.00g 1.00g

Extend the logical volume inside Red Hat.

# lvscan
  ACTIVE            '/dev/rhel_rhel98/var_log' [1.00 GiB] inherit
  ACTIVE            '/dev/rhel_rhel98/tmp' [10.00 GiB] inherit
  ACTIVE            '/dev/rhel_rhel98/var' [20.00 GiB] inherit
  ACTIVE            '/dev/rhel_rhel98/root' [20.00 GiB] inherit
  ACTIVE            '/dev/rhel_rhel98/home' [20.00 GiB] inherit
  ACTIVE            '/dev/rhel_rhel98/swap' [8.00 GiB] inherit
  ACTIVE            '/dev/rhel_rhel98/var_tmp' [2.00 GiB] inherit
  ACTIVE            '/dev/rhel_rhel98/var_log_audit' [<2.00 GiB] inherit

NOTE: There are two variations of the lvextend command, the 1st allocates specific amounts of space to the LV. For example: lvextend -r -L +1G /dev/rhel_rhel98/var_log just adds 1Gig to the LV from the free space available on the PV. The other variation that we will be using here, adds ALL the available free space on the PV to the LV.

# lvextend -r -l +100%FREE /dev/rhel_rhel98/var_log
  File system xfs found on rhel_rhel98/var_log mounted at /var/log.
  Size of logical volume rhel_rhel98/var_log changed from 1.00 GiB (256 extents) to 2.00 GiB (512 extents).
  Extending file system xfs to 2.00 GiB (2147483648 bytes) on rhel_rhel98/var_log...
xfs_growfs /dev/rhel_rhel98/var_log
meta-data=/dev/mapper/rhel_rhel98-var_log isize=512    agcount=4, agsize=65536 blks
         =                       sectsz=512   attr=2, projid32bit=1
         =                       crc=1        finobt=1, sparse=1, rmapbt=0
         =                       reflink=1    bigtime=1 inobtcount=1 nrext64=0
data     =                       bsize=4096   blocks=262144, imaxpct=25
         =                       sunit=0      swidth=0 blks
naming   =version 2              bsize=4096   ascii-ci=0, ftype=1
log      =internal log           bsize=4096   blocks=16384, version=2
         =                       sectsz=512   sunit=0 blks, lazy-count=1
realtime =none                   extsz=4096   blocks=0, rtextents=0
data blocks changed from 262144 to 524288
xfs_growfs done
  Extended file system xfs on rhel_rhel98/var_log.
  Logical volume rhel_rhel98/var_log successfully resized.

# lvscan
  ACTIVE            '/dev/rhel_rhel98/var_log' [2.00 GiB] inherit
  ACTIVE            '/dev/rhel_rhel98/tmp' [10.00 GiB] inherit
  ACTIVE            '/dev/rhel_rhel98/var' [20.00 GiB] inherit
  ACTIVE            '/dev/rhel_rhel98/root' [20.00 GiB] inherit
  ACTIVE            '/dev/rhel_rhel98/home' [20.00 GiB] inherit
  ACTIVE            '/dev/rhel_rhel98/swap' [8.00 GiB] inherit
  ACTIVE            '/dev/rhel_rhel98/var_tmp' [2.00 GiB] inherit
  ACTIVE            '/dev/rhel_rhel98/var_log_audit' [<2.00 GiB] inherit

The /var/log logical volume is now 2 Gig in size.   

# lsblk
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINTS
sr0 11:0 1 1024M 0 rom
vda 252:0 0 86G 0 disk
├─vda1 252:1 0 1G 0 part /boot/efi
├─vda2 252:2 0 1G 0 part /boot
└─vda3 252:3 0 84G 0 part
├─rhel_rhel98-root 253:0 0 20G 0 lvm /
├─rhel_rhel98-swap 253:1 0 8G 0 lvm [SWAP]
├─rhel_rhel98-var_log 253:2 0 2G 0 lvm /var/log
├─rhel_rhel98-tmp 253:3 0 10G 0 lvm /tmp
├─rhel_rhel98-var 253:4 0 20G 0 lvm /var
├─rhel_rhel98-home 253:5 0 20G 0 lvm /home
├─rhel_rhel98-var_tmp 253:6 0 2G 0 lvm /var/tmp
└─rhel_rhel98-var_log_audit 253:7 0 2G 0 lvm /var/log/audit

  
While this is definitely a non-trivial procedure, you can (if done correctly) reliably extend filesystems on virtualized Linux systems. 

 

Monday, May 25, 2026

Part 3 - Install, STIG, and verify STIG'd Red Hat Enterprise Linux (RHEL) 9.x Server

Part 3 of a 3 part series on how to built a DISA STIG compliant RHEL 9 server.
 
In this part we will take a look at the individual findings from the DISA STIG based OpenSCAP Evaluation Report we generated in the previous article, and see what needs
to be done to correct the rule violations that were found.
 
To streamline the iterative process of fixing and re-scanning the system to verify our corrections we will temporarily enable a web server on the RHEL 9.x server we are working on.  Follow the commands below in bold.
$ sudo -i
[sudo] password for admin: ************
 
# yum install httpd
Updating Subscription Management repositories.
Red Hat Enterprise Linux 9 for x86_64 - AppStream (RPMs)            9.7 kB/s | 4.5 kB     00:00    
Red Hat Enterprise Linux 9 for x86_64 - BaseOS (RPMs)                12 kB/s | 4.1 kB     00:00    
Red Hat CodeReady Linux Builder for RHEL 9 x86_64 (RPMs)             14 kB/s | 4.5 kB     00:00    
Dependencies resolved.
====================================================================================================
 Package                Arch       Version               Repository                            Size
====================================================================================================
Installing:
 httpd                  x86_64     2.4.62-13.el9         rhel-9-for-x86_64-appstream-rpms      54 k
Installing dependencies:
 apr                    x86_64     1.7.0-12.el9_3        rhel-9-for-x86_64-appstream-rpms     126 k
 apr-util               x86_64     1.6.1-23.el9          rhel-9-for-x86_64-appstream-rpms      97 k
 apr-util-bdb           x86_64     1.6.1-23.el9          rhel-9-for-x86_64-appstream-rpms      14 k
 httpd-core             x86_64     2.4.62-13.el9         rhel-9-for-x86_64-appstream-rpms     1.5 M
 httpd-filesystem       noarch     2.4.62-13.el9         rhel-9-for-x86_64-appstream-rpms      18 k
 httpd-tools            x86_64     2.4.62-13.el9         rhel-9-for-x86_64-appstream-rpms      88 k
 redhat-logos-httpd     noarch     90.6-1.el9            rhel-9-for-x86_64-appstream-rpms      15 k
Installing weak dependencies:
 apr-util-openssl       x86_64     1.6.1-23.el9          rhel-9-for-x86_64-appstream-rpms      17 k
 mod_http2              x86_64     2.0.26-5.el9          rhel-9-for-x86_64-appstream-rpms     163 k
 mod_lua                x86_64     2.4.62-13.el9         rhel-9-for-x86_64-appstream-rpms      65 k

Transaction Summary
====================================================================================================
Install  11 Packages

Total download size: 2.2 M

Installed size: 6.0 M

Is this ok [y/N]: y

...

Installed:
  apr-1.7.0-12.el9_3.x86_64                         apr-util-1.6.1-23.el9.x86_64                    
  apr-util-bdb-1.6.1-23.el9.x86_64                  apr-util-openssl-1.6.1-23.el9.x86_64            
  httpd-2.4.62-13.el9.x86_64                        httpd-core-2.4.62-13.el9.x86_64                 
  httpd-filesystem-2.4.62-13.el9.noarch             httpd-tools-2.4.62-13.el9.x86_64                
  mod_http2-2.0.26-5.el9.x86_64                     mod_lua-2.4.62-13.el9.x86_64                    
  redhat-logos-httpd-90.6-1.el9.noarch             

Complete!
 
# firewall-cmd --permanent --zone=public --add-service=http
success
# systemctl reload firewalld
# systemctl enable --now httpd
Created symlink /etc/systemd/system/multi-user.target.wants/httpd.service → /usr/lib/systemd/system/httpd.service.
# mkdir /var/www/html/openscap 
# ls -l /var/www/html
total 0
drwx------. 2 root root 6 May 25 10:43 openscap

# chmod 755 /var/www/html/openscap
# ls -l /var/www/html
total 0
drwxr-xr-x. 2 root root 6 May 25 10:43 openscap

Re-run the DISA STIG OpenSCAP scan and specify the new web directory in the report output parameter using the commands below in bold

# oscap xccdf eval --report /var/www/html/openscap/rhel98.html --profile stig /usr/share/xml/scap/ssg/content/ssg-rhel9-ds.xml

☐ Modify the file permissions of the report so it can be viewed via the web server
# chmod 755 /var/www/html/openscap/rhel98.html 

Access the DISA STIG web report using a browser and the URL below:

http://192.168.x.x/openscap/rhel98.html  (use ifconfig command to find IP) 

Note the last time we ran the oscap scan we tried using the '--remediate' option and in the meantime this test system has been rebooted.  The report we just generated now has 8 medium (Cat 2) and 2 high (Cat 1) rule violations.


Let's tackle the Cat 1 violations first. Scroll through the most recent OpenSCAP Evaluation Report and look for the two high severity failed rules.

If you click on the red text it will expand to a detailed description of the problem and how to fix it.  Here is a simplified solution to fix both of these Cat 1 findings:
 
Edit the /etc/grub.d/01_users file as follows (csadm means cybersecurity admin):

# vi /etc/grub.d/01_users

#!/bin/sh -e

cat << EOF

if [ -f \${prefix}/user.cfg ]; then

  source \${prefix}/user.cfg

  if [ -n "\${GRUB2_PASSWORD}" ]; then

    set superusers="csadm"

    export superusers

    password_pbkdf2 root \${GRUB2_PASSWORD}

  fi

fi

EOF

 

:wq

Set the UEFI Boot Loader Password

# grub2-setpassword

Enter password: **********

Confirm password: **********

 

 Generate a new GRUB configuration file

# grub2-mkconfig -o /boot/grub2/grub.cfg
Generating grub configuration file ...
Adding boot menu entry for UEFI Firmware Settings ...
done


Reboot the system, log back in and re-run the scan as the root user and view the new report and check to make sure the high (Cat 1) violations were taken care of.
# shutdown -r now
... 
$ sudo -i
# oscap xccdf eval --report /var/www/html/openscap/rhel98.html --profile stig /usr/share/xml/scap/ssg/content/ssg-rhel9-ds.xml
 
SUCCESS!  There are NO high (Cat 1) findings.

Now let's start looking at the medium severity violation.

First red highlighted fail we come to is: "Configure SSH Client to Use FIPS 140-2 Validated
MACs: openssh.config" followed by "Configure SSH Server to Use FIPS 140-2 Validated
MACs: opensshserver.config". These are both related to the SSH server service. Click on each
and read through what the rule is looking for.
 
These first two violations appear to be due to the order that the  Message Authentication Codes
(MACs) are listed. So we will ssh into our server, sudo to root, backup and edit both files, comment
out the offending line, and paste in the line from the the OpenSCAP evaluation report into the file.
Make changes highlighted in bold below. 
 
$ sudo -i
# cd /etc/crypto-policies/back-ends
# cp openssh.config openssh.config.orig 
# vim openssh.config
... 
 Ciphers aes256-gcm@openssh.com,aes256-ctr,aes128-gcm@openssh.com,aes128-ctr
MACs hmac-sha2-256-etm@openssh.com,hmac-sha2-512-etm@openssh.com,hmac-sha2-256,hmac-sha2-512
GSSAPIKeyExchange no
...
<ESC> 
:wq
 
# cp opensshserver.config opensshserver.config.orig
vim  
Ciphers aes256-gcm@openssh.com,aes256-ctr,aes128-gcm@openssh.com,aes128-ctr
MACs hmac-sha2-256-etm@openssh.com,hmac-sha2-512-etm@openssh.com,hmac-sha2-256,hmac-sha2-512
GSSAPIKeyExchange no
...
<ESC> 
:wq
 
Now restart the SSHd service and re-run the scan and examine the new report.
# systemctl restart sshd.service
 
Re-run the oscap scan and examine the results. 
# oscap xccdf eval --report /var/www/html/openscap/rhel98.html --profile stig /usr/share/xml/scap/ssg/content/ssg-rhel9-ds.xml
 
The next red highlighted fail we come to is: "Configure Logind to terminate idle sessions after
certain time of inactivity". Click on the entry and read through what the rule is looking for.
 
To fix the issue, we will backup and modify the logind.conf file as shown below. 
# cd /etc/systemd
# cp logind.conf logind.conf.orig
# vim logind.conf (Modify the StopIdleSessionSec line to look like below)
StopIdleSessionSec=600
 
<ESC>
:wq

Re-run the oscap scan and examine the results. 
# oscap xccdf eval --report /var/www/html/openscap/rhel98.html --profile stig /usr/share/xml/scap/ssg/content/ssg-rhel9-ds.xml
  
AND THERE IS A BUG IN THE TEST CRITERIA
The test criteria is looking for logind.conf inside a directory named /etc/systemd/logind.conf.d.  That directory does not exist and the logind.conf file is in the /etc/systemd directory.

☐ We will create a symbolic link to the file we just corrected in the location where 
OpenSCAP is looking for it, and re-run the scan.
 
# cd /etc/systemd
# mkdir logind.conf.d
# ln -s /etc/systemd/logind.conf /etc/systemd/logind.conf.d/logind.conf 
 
Re-run the oscap scan and examine the results. 
# oscap xccdf eval --report /var/www/html/openscap/rhel98.html --profile stig /usr/share/xml/scap/ssg/content/ssg-rhel9-ds.xml

The next red highlighted fail we come to is: "Only Authorized Local User Accounts Exist
on Operating System". Click on the entry and read through what the rule is looking for.

We can modify the test criteria inside the ssg-rhel9-ds.xml file to allow our admin
user and the other default accounts that were created during the install.  On our test
system we will add the following as authorized accounts: fapolicyd, postfix,
your admin user, apache, and unbound.
 
# cd /usr/share/xml/scap/ssg/content
# cp ssg-rhel9-ds.xml ssg-rhel9-ds.xml.orig
# vim ssg-rhel9-ds.xml
/libstoragemgmt (search for the first approved user account in the test criteria)
n (use 'n' to jump to the next instance and find the one under 'selector="rhel9"')
 
(look for the end of the line "|tcpdump|admin)" and add the additional accounts
after the "admin" user separated by "|" symbol)
|tcpdump|admin|fapolicyd|postfix|your admin user|apache|unbound)
 
<ESC>
:wq
 
Re-run the oscap scan and examine the results. 
# oscap xccdf eval --report /var/www/html/openscap/rhel98.html --profile stig /usr/share/xml/scap/ssg/content/ssg-rhel9-ds.xml

The next red highlighted fail we come to is: "Configure Multiple DNS Servers in 
/etc/resolve.conf". Click on the entry and read through what the rule is looking for.
 
In a production environment these should be internal DNS server entries, for our test system
we can just add google's DNS server (8.8.8.8) or Cloud flare's (1.1.1.1) using the Network Manager
Command Line Interface (nmcli).
 
nmcli connection show --active
NAME UUID TYPE DEVICE
enp1s0 d5a2ae35-dd87-35f4-a340-af32cf78bdf1 ethernet enp1s0
lo 58a4c38b-d1ea-4747-9708-c88633ecad84 loopback lo
# nmcli connection show enp1s0|grep -i ip4.dns
IP4.DNS[1]: 192.168.122.1
# nmcli connection modify enp1s0 +ipv4.dns "8.8.8.8"
# nmcli connection up enp1s0
Connection successfully activated (D-Bus active path: /org/freedesktop/NetworkManager/ActiveConnection/3)
# nmcli connection show enp1s0|grep -i ip4.dns
IP4.DNS[1]: 8.8.8.8
IP4.DNS[2]: 192.168.122.1
 
Re-run the oscap scan and examine the results. 
# oscap xccdf eval --report /var/www/html/openscap/rhel98.html --profile stig /usr/share/xml/scap/ssg/content/ssg-rhel9-ds.xml

Next is "Disable the use of user namespaces", click on the entry and read through
what the rule is looking for.
 
To see what the current user.max_user_namespaces value is (if you are curious).
# sysctl -a|grep user.max_user_name
user.max_user_namespaces = 14361


Set the current runtime value for user.max_user_namespaces to 0.
# sysctl -w user.max_user_namespaces=0
 
Make this setting persistent.
# vim /etc/sysctl.d/max_user_namespaces.conf
user.max_user_namespaces = 0
<ESC> 
:wq
 
Re-run the oscap scan and examine the results. 
# oscap xccdf eval --report /var/www/html/openscap/rhel98.html --profile stig /usr/share/xml/scap/ssg/content/ssg-rhel9-ds.xml

☐ Next is "Elivate The SELinux Context When An Administrator Calls The Sudo Command", click on the entry and read through what the rule is looking for.

# cd /etc/sudoers.d 
# visudo -f selinux.conf
%wheel ALL=(ALL) TYPE=sysadm_t ROLE=sysadm_r ALL 
<ESC>
:wq
# chmod 755 selinux.conf
(note this can break your ability to sudo if it is wrong, and you will need to login as root from the console and delete the file and start over, ask me how I know)
 
Re-run the oscap scan and examine the results. 
# oscap xccdf eval --report /var/www/html/openscap/rhel98.html --profile stig /usr/share/xml/scap/ssg/content/ssg-rhel9-ds.xml

The last one is "Enable Certmap in SSSD", click on the entry and read through what the rule is looking for.
 
Backup the /etc/sssd/sssd.conf file and edit it as highlighted below. 
 
# cd /etc/sssd
# cp sssd.conf sssd.conf.orig
# vim sssd.conf
[pam]
pam_cert_auth=True

[certmap/testing.test/rule_name]
matchrule =<SAN>.*EDIPI@mil
maprule = (userCertificate;binary={cert!bin})
domains = testing.test

<ESC>
:wq
(The above settings should be tailored for your specific production environment. How
to figure out what that looks like is beyond the scope of this series of articles)
 
Re-run the oscap scan and examine the results. 
# oscap xccdf eval --report /var/www/html/openscap/rhel98.html --profile stig /usr/share/xml/scap/ssg/content/ssg-rhel9-ds.xml

 
SUCCESS!  There are NO medium (Cat 2) findings. 

☐ READ ALL of the notchecked elements in the report, these are security best practices kinds
of things you should know. 
 
☐ Shutdown your virtual test server.
# shutdown -h now
 
END. 






Saturday, May 23, 2026

Part 2 - Install, STIG, and verify STIG'd Red Hat Enterprise Linux (RHEL) 9.x Server

Part 2 of a 3 part series on how to built a DISA STIG compliant RHEL 9 server.
  
In this part we will setup OpenSCAP and demonstrate how to use it to scan a Red
Hat Enterprise Linux 9 (RHEL9) server for DISA STIG compliance and generate an
interactive web based report.
 
(Replace admin with the account name created at the beginning of Part 1) 
Open an SSH session back into the RHEL 9 server and install opensecap-scanner
 and scap-security-guide with the following commands in bold.
 
$ sudo -i
[sudo] password for admin: ********** 
# yum install openscap-scanner scap-security-guide
Updating Subscription Management repositories.
Last metadata expiration check: 1:21:46 ago on Sat 23 May 2026 01:02:10 PM EDT.
Package openscap-scanner-1:1.3.13-1.el9_7.x86_64 is already installed.
Package scap-security-guide-0.1.80-1.el9_7.noarch is already installed.
Dependencies resolved.
Nothing to do.
Complete!
 
Run 'oscap info' to check the version of the DISA STIG with the following commands in bold.
# oscap info --profile stig /usr/share/xml/scap/ssg/content/ssg-rhel9-ds.xml
Document type: Source Data Stream
Imported: 2026-03-18T05:35:29
Stream: scap_org.open-scap_datastream_from_xccdf_ssg-rhel9-xccdf.xml
Generated: 2026-03-11T00:00:00
Version: 1.3
Profile
    Title: DISA STIG for Red Hat Enterprise Linux 9
    Id: xccdf_org.ssgproject.content_profile_stig
    Description: This profile contains configuration checks that align to the DISA STIG for Red Hat Enterprise Linux 9 V2R7.  In addition to being applicable to Red Hat Enterprise Linux 9, this configuration baseline is applicable to the operating system tier of Red Hat technologies that are based on Red Hat Enterprise Linux 9, such as:  - Red Hat Enterprise Linux Server - Red Hat Enterprise Linux Workstation and Desktop - Red Hat Enterprise Linux for HPC - Red Hat Storage - Red Hat Containers with a Red Hat Enterprise Linux 9 image

 Scan the system and generate the eXtensible Configuration Checklist Description Format (XCCDF) HTML report using the following commands in bold

[root@RHEL98 ~]# oscap xccdf eval --report /home/admin/rhel98.html --profile stig /usr/share/xml/scap/ssg/content/ssg-rhel9-ds.xml 
 ...
Title   Write Audit Logs to the Disk
Rule    xccdf_org.ssgproject.content_rule_auditd_write_logs
Ident   CCE-83705-4
Result  pass

Title   Verify Permissions on /etc/audit/auditd.conf
Rule    xccdf_org.ssgproject.content_rule_file_permissions_etc_audit_auditd
Ident   CCE-89284-4
Result  pass
 
 In the example above the report was written to the admin user's home directory.  We need to change the permissions on the report file so we can secure copy (SCP) the file from the virtual server to the host/hypervisor desktop.  Use the following commands in bold.
# ls -l /home/admin
total 5148
-rw-------. 1 root root 5270296 May 23 15:13 rhel98.html

[root@RHEL98 ~]# chown admin:admin /home/admin/rhel98.html 
[root@RHEL98 ~]# ls -l /home/admin
total 5148
-rw-------. 1 admin admin 5270296 May 23 15:13 rhel98.html
[root@RHEL98 ~]# 

 Open a new terminal on the host/hypervisor and SCP the rhel98.html report file from the virtual RHEL9 server.  Use the following commands in bold.
(You will need to know/remember the IP address of the virtual RHEL9 server)
 
$ scp admin@192.168.x.x:rhel98.html .
You are accessing a U.S. Government (USG) Information System (IS) that is 
provided for USG-authorized use only. By using this IS (which includes any 
device attached to this IS), you consent to the following conditions:
-The USG routinely intercepts and monitors communications on this IS for 
purposes including, but not limited to, penetration testing, COMSEC monitoring, 
...
communications and work product are private and confidential. See User 
Agreement for details.
admin@192.168.x.x's password: ************
rhel98.html                                   100% 5147KB 273.0MB/s   00:00  

 Now open the local copy of the rhel98.html report file in a browser on the host/hypervisor system.  Note: that there are still 9 medium and 2 high rules that failed even though we applied the DISA STIG during the server build process. 

 There is also a version of the oscap command that will attempt to automatically
remediate the problems that the scan finds.  This is the modified scan command. 
[root@RHEL98 ~]# oscap xccdf eval --report /home/admin/rhel98.html --profile stig --remediate /usr/share/xml/scap/ssg/content/ssg-rhel9-ds.xml
 
 Repeate the steps above to change permissions and secure copy the new report back
to the host/hypervisor and check the new report to see if there was an improvement. 
(Changing the scp command to preserver the 1st version of the report for comparison.)
 
$ scp admin@192.168.x.x:rhel98.html ./rhel98-remediated.html

 Open the local copy of the rhel98-remediated.html file in a browser on the host/hypervisor system.  Note: we still have 7 medium (cat 2) and 2 high (cat 1) failed rules, even though the Red Hat installation software applied the DISA STIG and we have also used the OpenSCAP "remediate" function.  

 Reboot the virtual Red Hat 9.x server using the following command. (If you want to 
shutdown the server and take a break, substitute '-h' for the '-r' below. )  

$ sudo shutdown -r now
 

CONCLUSION

 Application of the DISA STIG via automated means is not a 100% solution, nor is STIG application a "one and done" process.  New STIGs are released periodically and systems need to be re-checked and re-evaluated against them when they are.  

 The OpenSCAP Evaluation Report is an interactive web page with sections that expand and collapse.  There are explanations and instructions on how to remediate the medium (Cat 2) and high (Cat 1) findings within the report.