Introduction
Security-Enhanced Linux (SELinux) provides a robust mandatory access control (MAC) architecture that confines user programs and system services to the minimum amount of privilege they require. When deploying a web server (like Apache or Nginx) on RHEL, CentOS, or AlmaLinux, administrators often move the web root from the default /var/www/html to a custom directory, such as /srv/mywebsite. Without updating the SELinux contexts, the web server will be explicitly denied access to these files, resulting in a 403 Forbidden error. This guide demonstrates how to properly label custom directories for web hosting.
Prerequisites
You require a Red Hat-based Linux distribution with SELinux in Enforcing mode. You can verify this by running getenforce. You also need root or sudo privileges and the policycoreutils-python-utils package installed to use the semanage command.
The Problem with Custom Directories
If you create a directory like /srv/mywebsite and populate it with HTML files, those files inherit the default SELinux context of the /srv directory, which is usually var_t. The Apache process (httpd_t) is explicitly forbidden from reading var_t files.
To view the current context of your custom directory, use the -Z flag with ls:
ls -ldZ /srv/mywebsite
Step 1: Define the New Context Rule
You must tell SELinux that the new directory and all its contents should be treated as web server content. The correct context type for read-only web content is httpd_sys_content_t.
Use the semanage fcontext command to add a new rule to the SELinux policy database. The regular expression (/.*)? ensures the rule applies to the directory and all subdirectories/files within it:
sudo semanage fcontext -a -t httpd_sys_content_t "/srv/mywebsite(/.*)?"
Note: This command updates the policy, but it does not change the files immediately.
Step 2: Apply the Context to the Files
To apply the newly defined policy to the actual files on the disk, you must run the restorecon command. The -R flag applies it recursively, and the -v flag provides verbose output so you can see the changes happening:
sudo restorecon -Rv /srv/mywebsite
You will see output indicating that the context has been changed from var_t to httpd_sys_content_t.
Step 3: Handling Write Access (Optional)
If your web application (such as WordPress or a Laravel app) needs to upload files or write to a specific directory (like an uploads folder), httpd_sys_content_t is insufficient, as it is read-only.
For directories requiring write access, you must use the httpd_sys_rw_content_t context.
- Define the write context for the specific subfolder:
sudo semanage fcontext -a -t httpd_sys_rw_content_t "/srv/mywebsite/uploads(/.*)?" - Apply the change:
sudo restorecon -Rv /srv/mywebsite/uploads
Step 4: Restart the Web Server
With the correct contexts applied, restart your web server to ensure it reads the files without SELinux interference:
sudo systemctl restart httpd (or nginx)
Your custom directory is now fully functional and secured by SELinux.