Installing SELinux and Permanently Disabling It
Part of my #DevOpsFromZero series — documenting real KodeCloud tasks with the commands, the reasoning, the mistakes, and the principles behind every decision.
The Task
Install the required SELinux packages on App Server 1. Permanently disable SELinux. No reboot required now — the final status after tonight's scheduled reboot should be disabled.
Three requirements that seem straightforward. One important distinction hiding inside them.
What Is SELinux?
Before touching the server, it helps to understand what SELinux actually is.
Basic Linux permissions are like a building badge system: your badge says whether you can enter a room, open a cabinet, or change what is inside.
SELinux is the security guard standing behind the badge system saying — "Even if your badge opens this door, are you supposed to be doing this specific thing in this specific place?"
So standard Linux permissions answer: "Does this user have access?"
SELinux adds: "Is this action allowed by policy?"
A user or service may technically have permission to touch a file, but SELinux can still block it if the action does not match the expected security rules. It is not replacing Linux permissions — it is an extra layer of control on top of them.
That is why security teams roll it out during audits. It narrows what processes can do, even when they are running with elevated privileges.
The Infrastructure
| Detail | Value |
|---|---|
| Hostname | stapp01 |
| SSH User | tony |
| OS | CentOS Stream 9 |
ssh tony@stapp01
Confirm the OS First
Before running any package manager command, confirm the Linux distribution. Package managers are not interchangeable — dnf on RHEL/CentOS, apt on Debian/Ubuntu, zypper on SUSE. Assuming the wrong one wastes time and causes errors.
cat /etc/os-release
Output:
NAME="CentOS Stream"
VERSION="9"
ID="centos"
ID_LIKE="rhel fedora"
PRETTY_NAME="CentOS Stream 9"
CentOS Stream 9 is RHEL-based — dnf is the package manager. This follows the engineering principle of knowing your environment before you act — a simple check that eliminates an entire class of assumption-driven mistakes.
Step 1: Check What Is Already Installed
Before installing anything, check what is already on the system:
rpm -qa | grep selinux
rpm -qa | grep policycoreutils
Output:
libselinux-3.6-1.el9.x86_64
libselinux-utils-3.6-1.el9.x86_64
policycoreutils-3.6-2.1.el9.x86_64
Some base libraries were present, but the core policy packages were missing. Confirmed by checking the SELinux config directory:
ls /etc/selinux/
# semanage.conf
The main config file was absent — SELinux policy was not installed.
Step 2: Install the Required Packages
The standard approach is:
sudo dnf search selinux
However, the lab environment returned repo checksum errors:
Errors during downloading metadata for repository 'baseos':
- Downloading successful, but checksum doesn't match.
Error: Failed to download metadata for repo 'baseos'
This is a common issue in lab environments where mirror metadata can be stale. The workaround:
sudo dnf clean all
sudo dnf install -y selinux-policy selinux-policy-targeted --skip-broken
--skip-broken instructs DNF to proceed with what it can resolve, skipping packages blocked by dependency or repo errors. Installation completed successfully.
Step 3: Verify the Config File Exists
ls /etc/selinux/
# config semanage.conf targeted
cat /etc/selinux/config
Output:
SELINUX=enforcing
SELINUXTYPE=targeted
The config file is now present. The current permanent setting is enforcing — SELinux would be active after a reboot. That needs to change.
Step 4: Understand the Two States
This is the most important part of Day 5.
The task said:
"No need to reboot the server"
"Disregard the current status of SELinux via the command line"
"The final status after the reboot should be disabled"
SELinux — like most Linux services — has two distinct states:
| State | What It Is | Where It Lives |
|---|---|---|
| Runtime state | What SELinux is doing right now in memory | Command line (getenforce) |
| Permanent config | What SELinux will do after the next reboot | /etc/selinux/config |
The task only cares about the permanent config. The runtime state is ephemeral — it disappears on reboot. Only the config file survives.
Step 5: Permanently Disable SELinux
Edit the config file directly:
sudo nano /etc/selinux/config
Change:
SELINUX=enforcing
To:
SELINUX=disabled
Save and exit (Ctrl+X, Y, Enter).
Step 6: Verify the Change
grep SELINUX /etc/selinux/config
Output:
# SELINUX= can take one of these three values:
SELINUX=disabled
# SELINUXTYPE= can take one of these three values:
SELINUXTYPE=targeted
The active line shows SELINUX=disabled. Commented lines are documentation — only the uncommented lines are read by the system. Task complete. ✅
Why Not Use setenforce 0?
You can disable SELinux at runtime with:
sudo setenforce 0
But this only changes the runtime state. The moment the server reboots tonight, SELinux would come back up in enforcing mode — because the config file was never changed.
Editing /etc/selinux/config is the only change that persists across reboots.
Key Concepts Recap
| Concept | What It Means |
|---|---|
| SELinux | An extra security layer that enforces policy on top of standard Linux permissions |
enforcing |
SELinux actively blocks policy violations |
permissive |
SELinux logs violations but does not block them |
disabled |
SELinux is fully off |
/etc/selinux/config |
The permanent configuration file — survives reboots |
getenforce |
Shows the current runtime SELinux state |
--skip-broken |
DNF flag to proceed with installation despite repo or dependency errors |
| Runtime state | Ephemeral — exists in memory, lost on reboot |
| Permanent config | Persistent — written to disk, survives reboots |
Closing Thought
Day 1: Specify intent explicitly — defaults will betray you. Day 2: No error doesn't mean correct behaviour — always verify. Day 3: A configuration change is not real until the running service has loaded it. Day 4: Permission problems are layered — test the obvious explanation, then inspect the next layer. Day 5: When a change needs to survive a reboot, only the config file matters. Runtime state is temporary — the file is the source of truth.
Always change the source of truth.
#DevOpsFromZero #100DaysOfDevOps #Linux #SELinux #Security #DevOps #KodeCloud #Beginner
