How to Install SELinux to Harden Apache Webserver

Security Enhanced Linux or SELinux is responsible for the implementation of mandatory access control mechanisms on major Linux distributions like Fedora, RHEL, and Rocky Linux. These access control mechanisms guarantee increased security on all processes and files within a Linux operating system distribution.

The way SELinux operates can be broken down into three modes:

  • Enforcing: this mode implies that the SELinux policy is fully operational.
  • Permissive: with this mode, no SELinux policy is enforced, however, SELinux prints associated warnings.
  • Disabled: this mode indicates that no SELinux policy is in effect.

When web applications are not deployed from the default Apache directories (log or content), SELinux tends to be troublesome. When you try to run/test such web applications, SELinux will tend to prevent Apache from accessing logs and content not stored in the default Apache directory.

[ You might also like: How to Install SELinux to Harden Nginx Webserver ]

At this point, most users will find SELinux unbearable and do their best to disable it. However, a valid solution to this issue is creating custom SELinux policies for your files and directories. The advantage of this approach is that, if your context settings go missing, running a context restore will get your web app up and running again.

This article guide will address the following SELinux challenges:

  • Web applications should be allowed to execute outside Apache’s default directory (/var/www/html).
  • Apache is being blocked by SELinux when accessing content outside /var/www/html.
  • Web applications read and write access restrictions.
  • Web applications write access restrictions while uploading content from specific directories.

Installing Apache Web Server in Linux

This article requires Apache installed on your Linux operating system distribution. Refer to the following installation guide for different Linux package managers:

$ sudo apt install apache2      [On Debian, Ubuntu and Mint]
$ sudo yum install httpd        [On RHEL/CentOS/Fedora and Rocky Linux/AlmaLinux]
$ sudo apk add apache2          [On Alpine Linux]
$ sudo emerge -a apache         [On Gentoo Linux]
$ sudo pacman -S apache         [On Arch Linux]
$ sudo zypper install apache2   [On OpenSUSE]    

After Apache installation, you can enable, start and verify the status using the following commands.

$ sudo systemctl enable apache2
$ sudo systemctl start apache2
$ sudo systemctl status apache2
OR
$ sudo systemctl enable httpd
$ sudo systemctl start httpd
$ sudo systemctl status httpd

Installing SELinux in Linux

For users under Debian and Ubuntu distributions, or Linux distributions with AppArmor installed, consider uninstalling it first since it is also a Linux kernel implementation just like SELinux. They both function as Linux security modules and would collide/crash the system.

Check on AppArmor status, stop it, uninstall it, and reboot your system.

$ systemctl status apparmor
$ sudo systemctl stop apparmor 
$ sudo apt remove apparmor 
$ sudo reboot  

We can now proceed with the SELinux installation.

For RHEL-based distribution systems:

$ sudo dnf makecache
$ sudo dnf install policycoreutils libselinux-utils libselinux libselinux-devel selinux-policy selinux-policy-devel

For Debian-based distribution systems:

$ sudo apt update 
$ sudo apt install policycoreutils selinux-utils selinux-basics libselinux1 libselinux1-dev

For openSUSE Leap and Tumbleweed Systems:

$ sudo zypper refresh
$ sudo zypper install policycoreutils selinux-tools libselinux-devel libselinux1

Activate SELinux:

$ sudo selinux-activate 
Active SELinux
Active SELinux

For Debian/Ubuntu users, setting SELinux to operate in enforcing mode will prompt the error “failed to load kernel module” during system reboot. We can therefore set it to operate in permissive mode.

$ sudo nano /etc/selinux/config  
Set SELinux Permissive Mode
Set SELinux Permissive Mode

Reboot the machine:

$ sudo reboot

System relabeling should then take precedence:

SELinux Relabeling
SELinux Relabeling

After a successful system reboot, check SELinux Status:

$ sestatus 
Check SELinux Status
Check SELinux Status

Hardening Apache with SELinux

Consider the following directory structure for web application projects:

Apache Website Directory Structure
Apache Website Directory Structure

To use Apache’s context type httpd_sys_content_t (files and directories read-only) on the parent directory and all sub-directories:

$ sudo semanage fcontext -a -t httpd_sys_content_t "/myapps(/.*)?"
Set Apache SELinux Context Type
Set Apache SELinux Context Type

Ignore the minor error associated with user sddm.

To use Apache’s context type httpd_log_t (generate and append log files) on the present logging directory:

$ sudo semanage fcontext -a -t httpd_log_t "/myapps/logs(/.*)?"

To use Apache’s context type httpd_cache_t (for caching) on the present cache directory:

$ sudo semanage fcontext -a -t httpd_cache_t "/myapps/cache(/.*)?"

To use httpd_sys_rw_content_t (files and directories read and write) on uploads directory:

$ sudo semanage fcontext -a -t httpd_sys_rw_content_t "/myapps/app1/html/uploads(/.

To use httpd_sys_rw_content_t (files and directories read and write) on config.php file:

$ sudo semanage fcontext -a -t httpd_sys_rw_content_t "/myapps/app1/html/config.php"

To apply the above-created SELinux policies, we will run:

$ sudo restorecon -Rv /myapps
Apply SELinux Policies
Apply SELinux Policies

Verify that the context types were applied:

$ ls -lZ /myapps
Verify SELinux Context Type
Verify SELinux Context Type

With these configurations, SELinux can secure and harden web applications run by Apache. For a better understanding of existing SELinux policies and default contexts, run:

$ sudo semanage fcontext -l 

Got something to say? Join the discussion.

Have a question or suggestion? Please leave a comment to start the discussion. Please keep in mind that all comments are moderated and your email address will NOT be published.