SELinux adds a second permission layer on AlmaLinux, Rocky Linux and other Red Hat-family systems: even if file permissions allow something, the process must also be allowed by policy. It contains damage when a web app is compromised. Most problems are a wrong label or a switch that is off, and both are quick to fix.
Before you start
- An AlmaLinux or Rocky Linux VPS with sudo access. Ubuntu and Debian use AppArmor instead (see SELinux and AppArmor hardening).
- Install the helper tools:
sudo dnf install policycoreutils-python-utils setroubleshoot-server.
Check the SELinux mode
getenforce
sestatus- Enforcing: policy is applied (recommended).
- Permissive: denials are only logged; useful for testing.
- Disabled: off.
Switch temporarily with sudo setenforce 0 (permissive) or 1 (enforcing). The permanent setting is SELINUX= in /etc/selinux/config.
Warning: Disabling SELinux to make an error go away removes a real protection. Use permissive mode briefly to confirm SELinux is the cause, then fix the label or boolean and switch back.
Find out what was denied
sudo ausearch -m avc -ts recent
sudo sealert -a /var/log/audit/audit.logsealert explains each denial in plain English and usually suggests the exact fix command.
Fix file contexts with restorecon
Files carry labels; see them with ls -Z. Files moved (not copied) from a home folder keep the wrong label. Reset them:
sudo restorecon -Rv /var/www/htmlFor a custom web root, register it once and apply:
sudo semanage fcontext -a -t httpd_sys_content_t "/srv/site(/.*)?"
sudo restorecon -Rv /srv/siteFolders the web app must write to (uploads, cache) need httpd_sys_rw_content_t instead.
Turn on booleans
Booleans are on/off switches for common needs:
getsebool -a | grep httpd
sudo setsebool -P httpd_can_network_connect on
sudo setsebool -P httpd_can_network_connect_db onThe first lets the web server make outbound connections (APIs, reverse proxies); the second lets it reach a remote database. -P makes it permanent.
Allow a service on a custom port
sudo semanage port -a -t http_port_t -p tcp 8081
sudo semanage port -l | grep http_port_tChanging the SSH port works the same way with ssh_port_t; follow change the SSH port safely for the full procedure, including firewall rules.
Troubleshooting
- 403 Forbidden on a new site with correct chmod: wrong context; run
restorecon. - Nginx 502 to a backend: enable
httpd_can_network_connect. - Service cannot bind to its port: add the port with
semanage port.
