Introduction
This final guided lab brings several RHCSA preparation skills together. You will still receive command guidance, but the steps are closer to an administrator's validation workflow: inspect the system, configure required state, and prove the final result with standard tools.
In this lab, you will create a local operator identity, prepare persistent storage, deploy a small service from that storage, add SELinux and firewall policy, and run a final readiness check.
Inspect the Prepared System
In this step, you will inspect the resources prepared for the final workflow. Start by confirming the block device, service state, and SELinux mode.
The setup permanently preserves SSH and the LabEx browser terminal on 3002/tcp in the public zone. Keep these management rules while changing the application firewall policy.
Move into the project directory.
cd /home/labex/project
Show the prepared partition path. Later commands reuse this path so you do not have to guess which block device belongs to the lab.
cat /home/labex/project/rhcsa-final-part
Inspect the prepared block device. It does not have the final file system yet, so this is your baseline before formatting.
lsblk "$(cat /home/labex/project/rhcsa-final-part)"
Check that the final service has not been configured yet. The || true keeps the lab moving even though the unit is expected to be absent at this point.
systemctl status rhcsa-final-web.service --no-pager || true
Confirm SELinux is enforcing before you begin. Enforcing mode matters because the later SELinux labels are not just informational; they affect whether policy is applied.
getenforce
Create the Operator Identity and Shared Directory
In this step, you will create a local group, a local user, and a setgid shared directory. The commands are written to be safe if you need to rerun them.
Create the group if it does not exist. getent group checks the local name service first, and the || part creates the group only when the lookup fails.
getent group rhcsaops || sudo groupadd rhcsaops
Create the finaladmin user if it does not exist.
id finaladmin >/dev/null 2>&1 || sudo useradd -m -s /bin/bash -G rhcsaops finaladmin
Make sure the user is a member of the operator group. The -aG options append the group membership instead of replacing the user's existing supplemental groups.
sudo usermod -aG rhcsaops finaladmin
id finaladmin
Create a shared directory for operator notes. Mode 2770 gives the group full access and sets the setgid bit, so new files inherit the rhcsaops group.
sudo mkdir -p /srv/rhcsa-final/team
sudo chown root:rhcsaops /srv/rhcsa-final/team
sudo chmod 2770 /srv/rhcsa-final/team
Write a test file as finaladmin.
sudo -u finaladmin bash -c 'echo final validation access > /srv/rhcsa-final/team/finaladmin.txt'
Inspect the directory and file.
sudo stat -c '%a %U:%G %n' /srv/rhcsa-final/team /srv/rhcsa-final/team/finaladmin.txt
Prepare Persistent Storage
In this step, you will create a file system on the prepared partition and mount it persistently by UUID. This mirrors the storage validation pattern used in RHCSA-style tasks.
Store the prepared partition path in a shell variable.
part="$(cat /home/labex/project/rhcsa-final-part)"
Create an ext4 file system with a recognizable label. This is destructive to the prepared practice partition, so it comes only after you confirmed the device path.
sudo mkfs.ext4 -F -L RHCSA_FINAL "$part"
Create the mount point.
sudo mkdir -p /mnt/rhcsa-final
Capture the file system UUID and replace any old fstab line for this mount point. UUIDs are stable identifiers for persistent mounts, and removing older lines prevents duplicate fstab entries.
uuid="$(sudo blkid -s UUID -o value "$part")"
sudo sed -i '/\/mnt\/rhcsa-final/d' /etc/fstab
Add the persistent mount entry.
echo "UUID=$uuid /mnt/rhcsa-final ext4 defaults 0 0" | sudo tee -a /etc/fstab
Mount from fstab and inspect the result. mount -a proves the fstab line works now, while findmnt and df confirm the mount target and available capacity.
sudo mount -a
findmnt /mnt/rhcsa-final
df -h /mnt/rhcsa-final
Deploy and Enable the Final Service
In this step, you will place web content on the mounted file system and create a systemd service that serves it locally on port 18083.
Create the web content directory.
sudo mkdir -p /mnt/rhcsa-final/www
Create the content file.
echo "RHCSA final validation service" | sudo tee /mnt/rhcsa-final/www/index.html >/dev/null
Set permissions so the labex service user can read the content without making it world-writable. The service only needs group read and directory traversal access, not broad write access.
sudo chown -R root:labex /mnt/rhcsa-final/www
sudo chmod 750 /mnt/rhcsa-final/www
sudo chmod 640 /mnt/rhcsa-final/www/index.html
Create the service unit. The service runs from the mounted content directory and binds to localhost on 18083, which makes it easy to validate locally with curl.
sudo tee /etc/systemd/system/rhcsa-final-web.service >/dev/null <<'EOF'
[Unit]
Description=RHCSA final validation web service
After=network.target
[Service]
Type=simple
User=labex
Group=labex
WorkingDirectory=/mnt/rhcsa-final/www
ExecStart=/usr/bin/python3 -m http.server 18083 --bind 127.0.0.1
Restart=on-failure
[Install]
WantedBy=multi-user.target
EOF
Secure the unit file, reload systemd, and enable the service. Unit files under /etc/systemd/system should be root-owned, and daemon-reload makes systemd read the new unit before you enable and restart it.
sudo chown root:root /etc/systemd/system/rhcsa-final-web.service
sudo chmod 644 /etc/systemd/system/rhcsa-final-web.service
sudo systemctl daemon-reload
sudo systemctl enable rhcsa-final-web.service
sudo systemctl restart rhcsa-final-web.service
sleep 1
Test the service.
systemctl is-active rhcsa-final-web.service
curl -s http://127.0.0.1:18083/
Add SELinux and Firewall Policy
In this step, you will make the service policy complete. Add persistent SELinux labels for the content and port, then open the port with firewalld.
Add or update the persistent file context rule. The || pattern makes this safe to rerun: it adds the rule when missing and modifies it when the path already has a custom rule.
sudo semanage fcontext -a -t httpd_sys_content_t '/mnt/rhcsa-final/www(/.*)?' || sudo semanage fcontext -m -t httpd_sys_content_t '/mnt/rhcsa-final/www(/.*)?'
Apply the context rule. restorecon changes the current file labels to match the persistent SELinux rule you just created.
sudo restorecon -Rv /mnt/rhcsa-final/www
Add or update the SELinux HTTP port label. The add-or-modify pattern handles both a fresh system and a rerun where the port label already exists.
sudo semanage port -a -t http_port_t -p tcp 18083 || sudo semanage port -m -t http_port_t -p tcp 18083
Start firewalld and open the service port permanently.
sudo systemctl enable --now firewalld
sudo firewall-cmd --permanent --add-port=18083/tcp
sudo firewall-cmd --reload
Inspect the labels and firewall state. These checks connect the policy work to observable state: file label, allowed HTTP port type, and open firewall port.
ls -Z /mnt/rhcsa-final/www/index.html
sudo semanage port -l | grep '^http_port_t'
sudo firewall-cmd --list-ports
Run the Final Readiness Check
In this step, you will validate the complete system state with the same tools you used throughout the course. This is not a written report; it is an operational check.
Check the local identity and group membership.
id finaladmin
getent group rhcsaops
Check the persistent storage. You are verifying both the live mount and the saved fstab entry, because either one alone is only half of the storage requirement.
findmnt /mnt/rhcsa-final
grep /mnt/rhcsa-final /etc/fstab
Check the service.
systemctl is-enabled rhcsa-final-web.service
systemctl is-active rhcsa-final-web.service
curl -s http://127.0.0.1:18083/
Check SELinux and firewalld. The final state should show enforcing SELinux, the HTTP content label on the service file, and 18083/tcp open in firewalld.
getenforce
ls -Z /mnt/rhcsa-final/www/index.html
sudo firewall-cmd --list-ports
Summary
You completed a final guided readiness workflow by configuring an operator identity, a setgid shared directory, persistent storage, a systemd service, SELinux file and port labels, firewalld exposure, and a command-based final validation.



