Skip to main content

Command Palette

Search for a command to run...

Installing SELinux and Permanently Disabling It

Updated
6 min read
Y
Hi, I’m Yvette — a Berlin-based platform-oriented engineer transitioning into junior roles in platform engineering, DevOps, cloud operations, developer tooling, and observability. This blog is my technical notebook. I write about what I’m learning and building across platform engineering, developer experience, CI/CD automation, cloud operations, APIs, and observability. I care about clarity, reducing noise, and building systems that make work simpler for both users and developers. I’m currently looking for junior or entry-level opportunities where I can continue growing in these areas while contributing to better developer workflows and reliable infrastructure.

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

1 views

DevOps From Zero

Part 1 of 5

A 100-day journey through real DevOps tasks on KodeCloud #100daysofDevOps— documenting the commands, the reasoning, the mistakes, and the principles behind every decision. No polish, just progress.

Up next

Granting Executable Permissions to a Script for All Users

Part of my #DevOpsFromZero series — documenting real KodeCloud tasks with the commands, the reasoning, the mistakes, and the principles behind every decision. The Task Grant executable permissions