Get Rewarded! We will reward you with up to €50 credit on your account for every tutorial that you write and we publish!

Post-Install Repartitioning for CIS Hardening Compliance

profile picture
Author
Charaf Ddine El Omari
Published
2026-07-23
Time to read
9 minutes reading time

Introduction

Linux CIS Benchmarks require /home, /var, /var/tmp, /var/log, and /var/log/audit to reside on separate partitions, each with mount options (nodev, nosuid, noexec) that a shared root filesystem can't apply selectively. This guide walks through resizing that root partition post-install and creating the separate partitions the benchmarks require, without reinstalling the system or losing data.

Warning: Resizing the root partition and creating new filesystems can be risky. While this guide aims to preserve existing data, unexpected issues may result in data loss. Always create and verify a backup before making changes.

Prerequisites

  • A Linux server, e.g. with Hetzner

  • A root partition with sufficient unallocated space available to accommodate the new partitions.

This guide uses:

  • A GPT-partitioned disk.

  • /dev/sda as the disk device, and /dev/sda1 as the root partition, formatted with ext4.

  • ext4 for the five new partitions.

If your setup differs from the above, the corresponding commands throughout this guide must be adjusted accordingly.

This guide omits /tmp and /dev/shm, as tmpfs can be mounted on both. Either can be added to the partitioning plan below if a disk-backed mount is desired instead.

Step 1 - Initial Preparation

  • Determine the target partition distribution before proceeding. The following is provided as an example and is the chosen distribution for this guide:

    Partition Size
    / 10 GiB
    /home 10 GiB
    /var 4 GiB
    /var/tmp 2 GiB
    /var/log 6 GiB
    /var/log/audit 4 GiB

    Run df -h / to check how much disk space is used on your root filesystem.

  • Create the /etc/growroot-disabled file to prevent automatic root partition growth:

    sudo touch /etc/growroot-disabled
  • Take a system snapshot for safety (strongly recommended).

  • Prior to entering rescue mode, record the current system state:

    lsblk
    df -h
    cat /etc/fstab
    lsblk -dno pttype /dev/sda
  • Enter the Rescue System, see guide for dedicated servers or guide for cloud servers.

Do not mount the root partition yet, as it must be resized first. If it is already mounted, unmount it with umount.

Step 2 - Shrink the Root Partition

Before creating new partitions, you must shrink the existing root filesystem and partition. Run lsblk -f to check the filesystem.

e2fsck and resize2fs apply only to the ext2/ext3/ext4 family of filesystems, a different filesystem requires the corresponding resize and check tooling.

First, force a check and repair of the root filesystem:

e2fsck -f -y /dev/sda1

Shrink the ext4 filesystem to a size smaller than the target partition size (8G here) to ensure a safety margin during partition resizing:

resize2fs /dev/sda1 8G

Use parted to shrink the underlying partition to 10GiB:

parted /dev/sda

Inside the parted shell:

(parted) resizepart 1 10GiB
Warning: Shrinking a partition can cause data loss, are you sure you want to continue?
Yes/No? yes
(parted) quit

Expand the filesystem back to fill the newly resized 10GiB partition, and run a final filesystem check:

resize2fs /dev/sda1
e2fsck -f -y /dev/sda1

Step 3 - Create and Format New Partitions

With the root partition resized, create the separate partitions required by CIS benchmarks, using the distribution from Step 1:

The syntax below is specific to GPT partition tables and ext4 partitions. Where a different partition table or filesystem is in use, consult man parted and adapt the commands below accordingly. Run parted /dev/sda print to check which partition table and filesystem is used on your system.

parted -a optimal /dev/sda mkpart home ext4 10GiB 20GiB
parted -a optimal /dev/sda mkpart var ext4 20GiB 24GiB
parted -a optimal /dev/sda mkpart vartmp ext4 24GiB 26GiB
parted -a optimal /dev/sda mkpart varlog ext4 26GiB 32GiB
parted -a optimal /dev/sda mkpart varlogaudit ext4 32GiB 36GiB

Verify the partition layout with lsblk. If the new partitions do not appear immediately, trigger a kernel partition table re-read using partprobe /dev/sda. The numbering must be confirmed against what the subsequent commands expect (sda2-sda6). Where the numbering differs, all following steps must be adjusted accordingly.

Format each new partition with ext4 (substitute if a different filesystem was chosen):

mkfs.ext4 /dev/sda2
mkfs.ext4 /dev/sda3
mkfs.ext4 /dev/sda4
mkfs.ext4 /dev/sda5
mkfs.ext4 /dev/sda6

Step 4 - Data Migration

Create temporary mount points for the old root filesystem and all target partitions:

mkdir -p /mnt/old_root /mnt/new_home /mnt/new_var /mnt/new_vartmp /mnt/new_varlog /mnt/new_varaudit

Mount the original root partition and all target partitions:

mount /dev/sda1 /mnt/old_root
mount /dev/sda2 /mnt/new_home
mount /dev/sda3 /mnt/new_var
mount /dev/sda4 /mnt/new_vartmp
mount /dev/sda5 /mnt/new_varlog
mount /dev/sda6 /mnt/new_varaudit

The CIS benchmarks' example specifies cp -a for this step. rsync -aHAX is used instead, for simpler subdirectory exclusion when splitting /var across multiple destinations below, and, unlike cp -a dir/* dest/, includes hidden files (dotfiles), which glob-based invocations of cp omit by default.

rsync -aHAX /mnt/old_root/home/ /mnt/new_home/
rsync -aHAX /mnt/old_root/var/tmp/ /mnt/new_vartmp/
rsync -aHAX --exclude='tmp/' --exclude='log/' /mnt/old_root/var/ /mnt/new_var/
rsync -aHAX --exclude='audit/' /mnt/old_root/var/log/ /mnt/new_varlog/
[[ -d /mnt/old_root/var/log/audit ]] && rsync -aHAX /mnt/old_root/var/log/audit/ /mnt/new_varaudit/

Verify that all files migrated cleanly:

ls -la /mnt/new_home/
ls -la /mnt/new_var/
ls -la /mnt/new_vartmp/
ls -la /mnt/new_varlog/
ls -la /mnt/new_varaudit/

Step 5 - Cleanup and Directory Preparation

Remove the old /home and /var directories from the root volume to free up space:

rm -Rf /mnt/old_root/home/
rm -Rf /mnt/old_root/var/

Recreate essential mount point directories:

mkdir -p /mnt/old_root/home
mkdir -p /mnt/old_root/var
mkdir -p /mnt/new_var/tmp
mkdir -p /mnt/new_var/log
mkdir -p /mnt/new_varlog/audit

Unmount the new partitions:

umount /mnt/new_home
umount /mnt/new_var
umount /mnt/new_vartmp
umount /mnt/new_varlog
umount /mnt/new_varaudit

Step 6 - Configure /etc/fstab

Retrieve the filesystem UUIDs for the new partitions. Adjust the regex in the command if necessary:

blkid | grep -E "sda[2-6]"

Partitions are referenced by UUID rather than device path, as device names (/dev/sda2, etc.) are not guaranteed to remain stable across reboots or disk changes.

Edit /mnt/old_root/etc/fstab (not the rescue system's /etc/fstab) and append entries with the recommended CIS mount flags (make sure to place the respective filesystem UUIDs). The 2 in the last field enables fsck checks on boot, ordered after the root filesystem. See fstab(5):

UUID=<uuid-sda2> /home          ext4 defaults,rw,nosuid,nodev,relatime        0 2
UUID=<uuid-sda3> /var           ext4 defaults,rw,nosuid,nodev,relatime        0 2
UUID=<uuid-sda4> /var/tmp       ext4 defaults,rw,nosuid,nodev,noexec,relatime 0 2
UUID=<uuid-sda5> /var/log       ext4 defaults,rw,nosuid,nodev,noexec,relatime 0 2
UUID=<uuid-sda6> /var/log/audit ext4 defaults,rw,nosuid,nodev,noexec,relatime 0 2

Run a syntax check against the modified configuration file:

findmnt --verify --fstab --tab-file /mnt/old_root/etc/fstab

Verify that 0 parse errors are returned. Errors or warnings reporting entries such as /var/log/audit as "unreachable" may still appear. These do not indicate a fault, as findmnt evaluates reachability against the rescue environment's filesystem, which does not contain the target system's directories.

Step 7 - Unmount and Reboot

Unmount the old root partition and reboot back into the normal system:

umount /mnt/old_root
reboot

Step 8 - Post-Reboot Verification

Once back inside the main system, verify active mount configurations:

mount | column -t
df -h
lsblk -f

Step 9 - CIS Audits

Verify mount points and flags meet compliance standards:

findmnt -kn /home
findmnt -kn /var
findmnt -kn /var/tmp
findmnt -kn /var/log
findmnt -kn /var/log/audit

Each mount must be confirmed to carry the flags required by the benchmark. For each mount, grep -v applied to the expected flag must return no output:

findmnt -kn /home | grep -v nodev
findmnt -kn /home | grep -v nosuid

findmnt -kn /var | grep -v nodev
findmnt -kn /var | grep -v nosuid

findmnt -kn /var/tmp | grep -v nodev
findmnt -kn /var/tmp | grep -v nosuid
findmnt -kn /var/tmp | grep -v noexec

findmnt -kn /var/log | grep -v nodev
findmnt -kn /var/log | grep -v nosuid
findmnt -kn /var/log | grep -v noexec

findmnt -kn /var/log/audit | grep -v nodev
findmnt -kn /var/log/audit | grep -v nosuid
findmnt -kn /var/log/audit | grep -v noexec

The absence of output for a given check indicates the flag is present and correctly applied. Output indicates a failed check.

Step 10 - Troubleshooting

If your user directory was moved from /home to /var, move it back. Example:

Replace holu with your own username.

sudo find / -maxdepth 3 -type d -name holu 2>/dev/null
sudo ls -la /var/holu

sudo mkdir -p /home/holu
sudo rsync -aHAX /var/holu/ /home/holu/
sudo chown -R holu:holu /home/holu

ls -la /home/holu
sudo rm -rf /var/holu

Conclusion

This procedure results in /home, /var, /var/tmp, /var/log, and /var/log/audit residing on separate partitions with the mount options required by the CIS Benchmarks, verified in Step 9.

License: MIT
Want to contribute?

Get Rewarded: Get up to €50 in credit! Be a part of the community and contribute. Do it for the money. Do it for the bragging rights. And do it to teach others!

Report Issue

Discover our

Dedicated Servers

Get €20/$20 free credit!

Valid until: 31 December 2026 Valid for: 3 months and only for new customers
Configure now
Want to contribute?

Get Rewarded: Get up to €50 credit on your account for every tutorial you write and we publish!

Find out more