Skip to main content
To fix an SELinux “permission denied” error on AlmaLinux or Rocky Linux, find the denial with sudo ausearch -m AVC,USER_AVC -ts recent, then fix its cause: relabel files with sudo semanage fcontext -a -t httpd_sys_content_t "/srv/www(/.*)?" and sudo restorecon -R -v /srv/www, turn on a boolean such as sudo setsebool -P httpd_can_network_connect on, or allow a port with sudo semanage port -a. Keep SELinux enforcing. SELinux (Security-Enhanced Linux) gives every process and file a label and only allows the combinations its policy permits. Even if an attacker takes over your web server, SELinux stops it reading files that are not labelled for the web server. The catch: when you put files in an unusual folder or use a non-standard port, SELinux blocks it until you tell it that this is intended.

Before you start

  • You need root or a sudo user. Root users can leave out sudo.
  • Install the tools used on this page:
policycoreutils-python-utils provides semanage and audit2allow. setroubleshoot-server provides sealert, which explains denials in plain text.

How to check if SELinux is on

The output is Enforcing, Permissive or Disabled. sestatus shows more detail, including the mode set in /etc/selinux/config.

How to find out what SELinux blocked

1

Search the audit log

-ts recent shows the last 10 minutes. A denial looks like this:
Here nginx (httpd_t) was denied reading a file labelled user_home_t, because the file was created in a home folder.
2

Get a suggested fix

sealert lists each denial with one or more suggested commands. Prefer a label or boolean fix over a custom policy module.

How to fix the three most common SELinux problems

Files in the wrong place or with the wrong label

Web files outside /var/www, or files moved with mv from a home folder, keep the wrong label. Set the correct label for the folder permanently and apply it:
If the web app must write to a folder (for example uploads), use httpd_sys_rw_content_t for that folder only. Check labels with ls -Z /srv/www.

A service needs to make network connections

nginx or Apache as a reverse proxy, or PHP connecting to a remote database, needs a boolean (an on/off switch in the policy):
-P keeps the change after a reboot. For database connections only, httpd_can_network_connect_db is narrower. List booleans for a service with sudo getsebool -a | grep httpd.

A service uses a non-standard port

SELinux only lets a service bind to ports labelled for it. Add your port to the right type:
Check existing assignments with sudo semanage port -l | grep -E "http_port_t|ssh_port_t". If the port already belongs to another type, use -m instead of -a.

How to use permissive mode to test

If you are not sure SELinux is the cause, switch to permissive mode temporarily:
Test again. If the problem is still there, SELinux is not the cause. Either way, switch back straight away:
setenforce lasts until the next reboot. Red Hat advises against disabling SELinux except in specific cases (Red Hat SELinux documentation).
Do not set SELINUX=disabled to make an error go away. It removes a layer of protection for every service on the server. Turning it back on later needs a full relabel of the file system at the next boot, which can take a long time on a large disk.

How to check it worked

Repeat the action that failed, then search again:
<no matches> means SELinux blocked nothing in the last 10 minutes.

When should I use audit2allow?

Only after you ruled out labels, booleans and ports. audit2allow builds a custom policy module from logged denials, which can allow more than you intend. Red Hat recommends checking for labelling and configuration problems first (Red Hat SELinux troubleshooting).

Frequently asked questions

Why does nginx return 403 Forbidden on AlmaLinux when file permissions are correct?

Usually the files have the wrong SELinux label. Run ls -Z on the web root and relabel with semanage fcontext and restorecon as above.

Why does nginx return 502 Bad Gateway as a reverse proxy?

SELinux blocks nginx from connecting to the backend. Run sudo setsebool -P httpd_can_network_connect on. See also fix 502 Bad Gateway in nginx.

SSH fails to start after I changed the port. Why?

The new port is not labelled ssh_port_t. Run sudo semanage port -a -t ssh_port_t -p tcp 2222 with your port, then restart sshd. See change the SSH port.

Does Ubuntu use SELinux?

No. Ubuntu and Debian use AppArmor by default. This page applies to Red Hat based distributions.

VPS and dedicated server guides

Every guide in this section.

Set up firewalld

Firewall for AlmaLinux and Rocky.

Change the SSH port

Needs an SELinux port label.

Set up nginx as a reverse proxy

Needs a boolean on AlmaLinux.

Read logs with journalctl

Find service errors.

Security checklist

Harden the rest of your server.

Checked against the official Red Hat Enterprise Linux 9 SELinux documentation on 4 November 2026, which applies to AlmaLinux and Rocky Linux. Commands can differ on other distributions or releases.

Need Extra Help?

If you encounter any issues, our support team is ready to assist:

Save on Your Hosting

Ready to upgrade your hosting? Use code KB20 at checkout for 20% off your first order!

Last Updated: November 2026