Introduction
SELinux (Security-Enhanced Linux) is one of the most effective security mechanisms in Linux systems — and one of the most frequently disabled by administrators because “something stopped working”. That’s a mistake. In this article we explain how SELinux works, why you should leave it enabled, and how to configure it properly without disabling your entire application.
What is SELinux?
SELinux is a Mandatory Access Control (MAC) system built into the Linux kernel. Unlike standard Unix permissions (DAC), SELinux operates at the level of labels and policies — independently of file permissions or ownership.
file: /etc/passwd
SELinux context: system_u:object_r:passwd_file_t:s0
nginx process:
context: system_u:system_r:httpd_t:s0
→ does httpd_t have access to passwd_file_t? NO!
→ nginx cannot read /etc/passwd even as root
SELinux Modes
sestatus
getenforce
| Mode | Behaviour |
|---|---|
| Enforcing | Policies are enforced — violations blocked and logged |
| Permissive | Policies are NOT enforced — logging only |
| Disabled | SELinux disabled — no protection |
Base Configuration
# /etc/selinux/config
SELINUX=enforcing
SELINUXTYPE=targeted
setenforce 0 # permissive (diagnostics)
setenforce 1 # enforcing (production)
Practical Example — nginx with a Non-Standard Directory
Problem
ls -Z /data/www/
# system_u:object_r:default_t:s0 . ← default_t context blocks nginx
Diagnostics
ausearch -m avc -ts recent | grep nginx
ausearch -m avc -ts recent | audit2why
Solution 1 — Change the file context
semanage fcontext -a -t httpd_sys_content_t "/data/www(/.*)?"
restorecon -Rv /data/www/
ls -Z /data/www/
# system_u:object_r:httpd_sys_content_t:s0 index.html
Solution 2 — SELinux booleans
getsebool -a | grep httpd
setsebool -P httpd_enable_homedirs 1
setsebool -P httpd_can_network_connect 1
setsebool -P httpd_can_network_connect_db 1
Non-Standard Ports
semanage port -l | grep http_port_t
# http_port_t tcp 80, 443, 8008, 8080, 8443
semanage port -a -t http_port_t -p tcp 9000
Creating Custom Policy Modules
ausearch -m avc -ts recent > /tmp/avc.log
audit2allow -i /tmp/avc.log -M myapp_policy
cat myapp_policy.te # IMPORTANT — read before applying!
semodule -i myapp_policy.pp
Most Common Issues and Solutions
| Problem | Cause | Solution |
|---|---|---|
| Nginx 403 with correct permissions | Wrong SELinux context | semanage fcontext + restorecon |
| Service can’t connect | Boolean disabled | setsebool -P httpd_can_network_connect 1 |
| Non-standard port blocked | Port has no label | semanage port -a |
What You Should Never Do
# DON'T do this!
setenforce 0
sed -i 's/SELINUX=enforcing/SELINUX=disabled/' /etc/selinux/config
Summary
SELinux is not the administrator’s enemy — it’s an additional layer of protection. Key principles:
- Never disable SELinux — always diagnose the problem
- Use
audit2whyandsealertfor diagnostics - Fix issues via
semanage fcontext, booleans oraudit2allow - Test changes on staging before production
The time invested in learning SELinux pays off at the first attack attempt.