How to Configure SELinux (Security-Enhanced Linux) Contexts for Custom Web Directories

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.

  1. Define the write context for the specific subfolder:
    sudo semanage fcontext -a -t httpd_sys_rw_content_t "/srv/mywebsite/uploads(/.*)?"
  2. 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.

Get the best tech tips delivered straight to your inbox.

Join thousands of readers mastering Apple, Google, Microsoft, and Linux.