🛡️
VPS

SELinux (Security-Enhanced Linux) is an additional security layer that operates above the traditional Linux Discretionary Access Control (DAC) system. Most VPS administrators disable SELinux entirely because they don't understand how it works, but when implemented correctly, SELinux is a powerful Linux-level protection mechanism that significantly reduces risk from unauthorized access. This guide teaches you how to properly configure SELinux on CentOS Stream, Rocky Linux, or AlmaLinux, troubleshoot denial errors when they occur, and use audit2allow to create targeted policies instead of disabling SELinux entirely.

In short: SELinux is a security layer that works above standard Linux permissions. It has three modes: Enforcing (actively blocks violations, most secure), Permissive (logs violations only), and Disabled (completely off). To prevent application breakage while maintaining security, examine audit logs and use audit2allow to create policies that grant only necessary permissions. Never just disable SELinux.

What is SELinux and How Does It Differ from Standard Linux Permissions

Traditional Linux uses Discretionary Access Control (DAC), which bases access solely on user and group ownership. For example, if the file /var/www/html/index.php is owned by root, the Apache process running as user www-data cannot read it. However, if Apache is compromised, an attacker gains all permissions that www-data has, including access to any files www-data can reach. This is where the limitation of traditional permission model becomes clear.

SELinux adds a second layer called Mandatory Access Control (MAC), which operates independently from DAC permissions. Instead of restricting access based only on user/group membership, SELinux assigns a "role" and "context" to each process and file. For example, Apache might run with context "httpd_t" and web files might have context "httpd_sys_content_t". The SELinux kernel will only allow httpd_t to read files labeled httpd_sys_content_t, regardless of what other permissions www-data has. Even if Apache contains a vulnerability and is compromised, the attacker cannot access files that SELinux policy forbids.

Tip: Think of SELinux as a "server-level firewall" or additional checkpoint. Standard DAC permissions are like "authentication" (proving who you are), but SELinux is an "authorization layer" (verifying you should actually be allowed to do this according to system policy).

The Three Modes of SELinux

SELinux operates in three distinct modes.

Check Current SELinux Status

Before making any changes, check the current SELinux status on your VPS using getenforce

getenforce

This command returns a single line: Enforcing, Permissive, or Disabled. For more detailed information, use sestatus

sestatus

The output shows the current mode, active policy, file context information, and more. For even greater detail, add the -v flag

sestatus -v

Change SELinux Mode

To temporarily change SELinux mode (until next reboot), use setenforce

setenforce 0

The above sets SELinux to Permissive mode (0 = Permissive, 1 = Enforcing). This change is temporary only. To make the change persistent, edit /etc/selinux/config as root

sudo nano /etc/selinux/config

Find the line starting with SELINUX= and set your desired value

SELINUX=enforcing

Valid values are enforcing, permissive, or disabled. If you change from disabled to either enforcing or permissive, you must reboot because the system needs to relabel all files.

Warning: When changing SELinux from disabled to enforcing or permissive, the system must relabel every file (scanning all files to assign correct contexts). This process can take several hours depending on data volume. During relabeling in enforcing mode, some services may become blocked or crash. Plan this change carefully.

Understanding SELinux Contexts

A SELinux context has the format user:role:type:level. The most important part for normal operations is the type (the classification). A typical context for web files looks like

httpd_sys_content_t

The context for the Apache process itself

httpd_t

To see what context a file has, use ls with the -Z flag

ls -Z /var/www/html/index.php

To see the context of running processes

ps auxZ | grep httpd

The output displays the context assigned to each running process.

Common SELinux Commands

chcon - Change File Context

To change the context of a file or directory, use chcon (change context)

chcon -t httpd_sys_rw_content_t /var/www/html/uploads/

The -t flag means change the type only. The above command changes the type of the uploads directory to httpd_sys_rw_content_t, allowing Apache to read and write files there.

To change context recursively for a directory and all files inside it, add the -R flag

chcon -Rt httpd_sys_rw_content_t /var/www/html/uploads/

restorecon - Restore Default Context

If you change context incorrectly or need to restore files to their policy-defined defaults, use restorecon

restorecon -v /var/www/html/

This command reads what contexts should be according to SELinux policy, then adjusts files to match. The -v flag shows verbose output (which files were changed).

To recursively update contexts for a directory and all contents

restorecon -Rv /var/www/html/

semanage - Manage Policy and Contexts

semanage is the primary tool for managing SELinux policy. A common use case is permanently defining the context for a directory

semanage fcontext -a -t httpd_sys_rw_content_t "/var/www/html/uploads(/.*)?"

This tells SELinux that /var/www/html/uploads and all files and directories inside should have context httpd_sys_rw_content_t permanently. After setting this, run restorecon to apply it to existing files

restorecon -Rv /var/www/html/uploads/

SELinux Booleans

SELinux includes settings called booleans that control specific aspects of policy behavior. An important example is httpd_can_network_connect, which allows Apache to make outbound network connections (necessary for applications that connect to external databases, APIs, or services).

To see all available booleans and their current state

getsebool -a

To enable a specific boolean

setsebool -P httpd_can_network_connect on

The -P flag makes the change persistent across reboots. Without -P, the setting is lost after reboot.

Real-World Scenario: Apache Cannot Connect to Database

Suppose you set up a new Rocky Linux VPS, install Apache, and run a PHP web application that connects to MySQL on a different server. If SELinux is set to Enforcing, you might get "Connection refused" or timeout errors when the application tries to reach the database, even though firewall rules and Linux permissions are correct.

To verify SELinux is the cause, temporarily change to Permissive mode to log violations without blocking them

sudo setenforce 0

Then access the web application again and trigger database operations. If it works now and displays data from the database, SELinux is definitely the cause of the problem.

Using Audit Logs to Find the Issue

When SELinux denies an action, it logs details to /var/log/audit/audit.log. To see recent denial entries

tail -30 /var/log/audit/audit.log | grep denied

A denial line looks something like

type=AVC msg=audit(1625126789.123:456): avc: denied { connect } for pid=1234 comm="apache" saddr=192.168.1.1 sport=12345 daddr=10.0.0.2 dport=3306

This shows Apache (PID 1234) tried to create a network connection to 10.0.0.2:3306 (MySQL) but SELinux blocked it. For easier reading, use ausearch

ausearch -m AVC -ts recent | head -30

The -m AVC flag searches for AVC message types, and -ts recent finds only recent events.

Using audit2allow to Create Policy

Instead of disabling SELinux entirely, use audit2allow to generate policy that grants necessary permissions. First, install required packages

sudo yum install -y audit policycoreutils-python-utils

Then generate a policy module by reading audit log denials

sudo audit2allow -a -M myapp

The -a flag means process all unhandled denials in the audit log, and -M creates a module named myapp. This generates myapp.pp (policy package) and myapp.te (type enforcement file).

Before loading the policy, review the myapp.te file to see what permissions audit2allow generated

cat myapp.te

If the output looks reasonable and not overly broad, load the policy

sudo semodule -i myapp.pp

Once the policy is loaded, switch SELinux back to Enforcing mode

sudo setenforce 1

Test the web application again. It should now work without errors. If additional denials appear, repeat the audit2allow process.

Tip: If audit2allow generates overly permissive policy (allowing everything), don't load it. Delete the generated files, keep SELinux in Permissive a bit longer, then try audit2allow again with narrower conditions or create the policy manually to be more specific.

Secure SELinux Configuration Approach

Proper SELinux configuration means not just disabling it, but following a methodical troubleshooting workflow

  1. Set SELinux to Permissive mode temporarily to log violations without enforcing
  2. Run your application and test all functionality thoroughly—test reading, writing, network connections, and any other operations your app performs
  3. Review the audit log for SELinux denials related to your application
  4. Use audit2allow to generate policy allowing only necessary actions
  5. Review the generated .te file to ensure it permits only required operations
  6. Load the policy module using semodule -i
  7. Switch SELinux back to Enforcing mode
  8. Test your application again thoroughly to ensure all features work

By following this workflow, you create SELinux policy tailored to your specific application needs, providing real security benefits while avoiding the pitfall of completely disabling the system.

Summary

SELinux is a powerful Linux-level security mechanism that is often misunderstood. Many administrators completely disable it rather than learning to use it properly. By breaking it down into manageable steps, understanding modes, contexts, audit logs, and the audit2allow workflow, you can confidently configure SELinux on your VPS and add a genuine layer of defense that modern applications require.

Frequently Asked Questions

Does SELinux slow down the server significantly?

SELinux overhead is typically minimal—usually 1-5% performance impact due to additional context checks. If your VPS is suffering severe CPU performance issues, the problem likely lies elsewhere. In most cases, SELinux impact is negligible.

I disabled SELinux to fix problems earlier. Should I re-enable it?

If SELinux is Disabled, you can switch to Permissive immediately without rebooting. To use Enforcing mode requires a reboot because the system must relabel all files, which can take many hours on large systems. If setting up a new VPS, start with Permissive mode from the beginning.

What if audit2allow creates a policy that allows everything—is that secure?

audit2allow generates the minimum permissions needed based on observed denials. If you properly test your application in Permissive mode for several days, audit2allow will generate sufficient policy. Always review the generated .te file before loading to ensure it's appropriately scoped.

Can I remove or undo a SELinux policy I applied incorrectly?

Yes, use semodule -l to list loaded modules, then semodule -r myapp to remove a module. If you need to reset file contexts, use restorecon -R to restore them to policy defaults. Changes take effect immediately without a reboot.

Start Your AsiaGB VPS Today

AsiaGB VPS runs on SSD storage across every plan, with Thailand or Singapore datacenter options and full root access from day one — starting at 500 THB/month (Linux), backed by a Thai support team.

See VPS Plans

View all affordable VPS Thailand plans →