Mastering SELinux in Production: A Complete Security Configuration Guide

This comprehensive guide walks you through SELinux fundamentals, core concepts, mode differences, security contexts, real‑world configuration examples for web and database services, boolean management, troubleshooting techniques, performance tuning, and enterprise‑grade best practices to turn SELinux into a reliable production‑level security guardian.

Ops Community
Ops Community
Ops Community
Mastering SELinux in Production: A Complete Security Configuration Guide

SELinux Production Guide: From Basics to Mastery

Have you ever been woken up at 3 am by an alert because a simple service failed to start, only to discover SELinux was the culprit? This article will change your perception of SELinux.

Introduction: Why Disabling SELinux Is a Mistake

In the ops community there is a "rule of thumb": when encountering permission issues, the first step is setenforce 0. This is like driving without a seatbelt—convenient but dangerously insecure.

Real‑world case : In 2023 an internet company disabled SELinux, leading to an unauthorised Redis access exploit, ransomware encryption of the database, and losses exceeding 5 million CNY. If SELinux had been enabled, the attack would have been blocked even with configuration flaws.

This article uses practical cases to teach you how to configure SELinux correctly so it becomes a security guardian rather than a stumbling block.

1. SELinux Core Concepts Overview

1.1 What Is SELinux?

SELinux (Security‑Enhanced Linux) is a Mandatory Access Control (MAC) mechanism. Unlike traditional Discretionary Access Control (DAC), SELinux assigns a "security label" to every process and file, acting like a pass that must match before access is granted.

1.2 Comparison of Three Modes

# View current mode
getenforce

# Temporarily change mode
setenforce 0   # Permissive
setenforce 1   # Enforcing

Enforcing : Enforces all SELinux policies – recommended for production – ★★★★★

Permissive : Logs violations without blocking – useful for debugging – ★★★☆☆

Disabled : Completely turns off SELinux – strongly not recommended – ★☆☆☆☆

Practical Tip: Permanently Change SELinux Mode

# Edit configuration file
vim /etc/selinux/config

# Change SELINUX parameter
SELINUX=enforcing   # or permissive, disabled

# Reboot to apply
reboot

2. Security Contexts – The Core Mechanism

2.1 Understanding Security Contexts

Every file and process has a security context in the form user:role:type:level.

# View file context
ls -Z /var/www/html/
# Example output:
# -rw-r--r--. root root unconfined_u:object_r:httpd_sys_content_t:s0 index.html

# View process context
ps auxZ | grep httpd
# Example output:
# system_u:system_r:httpd_t:s0   apache   12345   /usr/sbin/httpd

2.2 Detailed Breakdown

user : SELinux user (e.g., system_u, unconfined_u)

role : Defines the domain a user can access (e.g., system_r, object_r)

type : Most important part; defines the access control rules

level : MLS/MCS security level, usually s0

3. Practical Cases: Web Server SELinux Configuration

Scenario 1 – Nginx Cannot Access Custom Directory

Problem : Files placed in /data/www cause Nginx to return 403 Forbidden.

Investigation Steps :

# Check SELinux logs
ausearch -m AVC -ts recent

# View directory context
ls -Zd /data/www
# drwxr-xr-x. root root unconfined_u:object_r:default_t:s0 /data/www

# Compare with default web directory
ls -Zd /var/www/html
# drwxr-xr-x. root root system_u:object_r:httpd_sys_content_t:s0 /var/www/html

Solution :

# Temporary fix – change file context
chcon -R -t httpd_sys_content_t /data/www

# Permanent fix – add rule and restore context
semanage fcontext -a -t httpd_sys_content_t "/data/www(/.*)?"
restorecon -Rv /data/www

# Verify
ls -Zd /data/www

Scenario 2 – PHP Upload Directory

Problem : PHP cannot write to /var/www/html/uploads.

# Set writable context
semanage fcontext -a -t httpd_sys_rw_content_t "/var/www/html/uploads(/.*)?"
restorecon -Rv /var/www/html/uploads

# If execution permission is needed (e.g., thumbnail generation)
setsebool -P httpd_execmem on

Scenario 3 – Custom Port Configuration

Problem : Nginx fails to listen on port 8080.

# List allowed HTTP ports
semanage port -l | grep http_port_t

# Add custom port
semanage port -a -t http_port_t -p tcp 8080

# Verify
semanage port -l | grep 8080

4. Database Service SELinux Configuration

MySQL/MariaDB Custom Data Directory

# Stop service
systemctl stop mariadb

# Move data
rsync -av /var/lib/mysql/ /data/mysql/

# Set correct context
semanage fcontext -a -t mysqld_db_t "/data/mysql(/.*)?"
restorecon -Rv /data/mysql

# Update configuration file
vim /etc/my.cnf.d/mariadb-server.cnf
# Change datadir=/data/mysql

# Start service
systemctl start mariadb

5. Advanced Techniques: SELinux Boolean Management

5.1 View and Set Booleans

# List all booleans
getsebool -a

# Filter for httpd
getsebool -a | grep httpd

# Common httpd booleans
setsebool -P httpd_can_network_connect on   # Allow network connections
setsebool -P httpd_can_sendmail on          # Allow sending mail
setsebool -P httpd_enable_cgi on           # Allow CGI execution
setsebool -P httpd_read_user_content on    # Allow reading user content

5.2 Useful Boolean Table

httpd_can_network_connect_db : Allows web servers to connect to databases – used by WordPress, Drupal

httpd_use_nfs : Allows access to NFS – for shared storage environments

ftpd_full_access : Grants FTP full access – for FTP servers

samba_export_all_rw : Gives Samba read/write to all files – for file‑sharing services

6. Troubleshooting: SELinux Debugging Tips

6.1 Use audit2why to Analyse Issues

# Install troubleshooting tool
yum install -y setroubleshoot-server

# Analyse recent AVC denials
ausearch -m AVC -ts recent | audit2why

# Example output (truncated)
# type=AVC msg=audit(1234567890.123:456): avc:  denied  { write } for pid=1234 comm="httpd" name="upload" ...
# Cause: Missing type enforcement (TE) allow rule.
# Solution: Use audit2allow to generate a loadable module.

6.2 Generate Custom Policy Module

# Collect denial logs
grep httpd /var/log/audit/audit.log | audit2allow -M my_httpd

# View generated policy
cat my_httpd.te

# Install the module
semodule -i my_httpd.pp

# Verify installation
semodule -l | grep my_httpd

6.3 Temporary Debug Mode

# Set a specific domain to permissive
semanage permissive -a httpd_t

# After debugging, revert
semanage permissive -d httpd_t

# List all permissive domains
semanage permissive -l

7. Performance Optimisation: Minimising SELinux Overhead

7.1 Optimise Policy Loading

# Disable unnecessary modules
semodule -d unnecessary_module

# Measure module load time
time semodule -l

# Recommendations:
# 1. Load only required policy modules
# 2. Regularly clean temporary policies
# 3. Use the "targeted" policy instead of "strict"

7.2 Monitor SELinux Performance Impact

# View AVC cache statistics
cat /sys/fs/selinux/avc/cache_stats

# Trace SELinux‑related syscalls for a process
strace -e trace=file -p $(pgrep httpd) 2>&1 | grep -i selinux

8. Enterprise‑Grade Best Practices

8.1 Pre‑deployment Checklist

Test‑environment validation : Run in Permissive mode for a week before production.

Collect violation logs : Analyse all AVC denial records.

Define policy templates : Create standardised configurations for each service.

8.2 Production Deployment Checklist (Script)

#!/bin/bash
# SELinux production readiness check

echo "=== SELinux Pre‑deployment Check ==="

# 1. Check current mode
current_mode=$(getenforce)
echo "Current mode: $current_mode"

# 2. Verify contexts of critical services
services=("httpd" "mysqld" "sshd")
for svc in "${services[@]}"; do
  echo "Checking $svc service..."
  ps auxZ | grep $svc | head -1
done

# 3. Verify contexts of critical directories
critical_dirs=("/var/www" "/var/lib/mysql" "/etc/ssh")
for dir in "${critical_dirs[@]}"; do
  echo "Checking $dir directory..."
  ls -Zd $dir 2>/dev/null
done

# 4. Check important booleans
echo "=== Important Boolean States ==="
getsebool httpd_can_network_connect
getsebool httpd_can_network_connect_db
getsebool allow_ftpd_full_access

# 5. List custom policy modules
echo "=== Custom Policy Modules ==="
semodule -l | grep -v "^[[:space:]]*#"

8.3 Emergency Response Process

Rapid localisation : ausearch -m AVC -ts recent Temporary mitigation : Set the affected domain to permissive.

Root‑cause analysis : Use audit2why to identify the reason.

Permanent fix : Adjust the security context or create a custom policy module.

Verification : Confirm the service works and switch back to Enforcing.

Conclusion: SELinux Is a Friend, Not an Enemy

After studying this guide you should be comfortable with SELinux core concepts, configuration techniques, troubleshooting methods, and enterprise‑level hardening practices. Remember:

Never disable SELinux in production.

Use semanage fcontext for permanent context changes.

Leverage audit2why and audit2allow to resolve denials.

Regularly audit and optimise SELinux policies.

SELinux acts like a fuse for your system—normally invisible, but it can save you in critical moments. Proper configuration not only boosts security but also earns you points during security audits.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

troubleshootingLinux securitySELinuxpolicy managementSystem Hardening
Ops Community
Written by

Ops Community

A leading IT operations community where professionals share and grow together.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.