Complete Guide to SELinux Booleans on RHEL 9

SELinux booleans are switches that let you toggle specific policy rules on or off without writing, compiling, or loading a custom policy module. They exist because the SELinux policy authors recognized that some access patterns are legitimate in some environments but not in others. Instead of forcing every admin to write custom modules for common variations, they built toggles into the policy itself.

On RHEL 9 and compatible distributions like CentOS Stream 9, AlmaLinux 9, and Rocky Linux 9, the targeted policy includes hundreds of booleans. This guide covers the commands you need to manage them and the specific booleans you are most likely to encounter.

Listing All Booleans

The getsebool -a command lists every boolean and its current state:

[root@rhel9 ~]# getsebool -a
abrt_anon_write --> off
abrt_handle_event --> off
abrt_upload_watch_anon_write --> on
antivirus_can_scan_system --> off
...

On a default RHEL 9 install, there are over 300 booleans. Piping through grep is the practical way to find what you need:

[root@rhel9 ~]# getsebool -a | grep httpd
httpd_can_connect_ftp --> off
httpd_can_connect_ldap --> off
httpd_can_network_connect --> off
httpd_can_network_connect_db --> off
httpd_can_sendmail --> off
httpd_enable_cgi --> on
httpd_enable_homedirs --> off
httpd_read_user_content --> off
httpd_use_nfs --> off
...

Checking a Specific Boolean

To check one boolean by name:

[root@rhel9 ~]# getsebool httpd_can_network_connect
httpd_can_network_connect --> off

For a detailed description of what the boolean controls, use semanage boolean -l:

[root@rhel9 ~]# semanage boolean -l | grep httpd_can_network_connect
httpd_can_network_connect (off , off) Allow httpd to can network connect

The two values in parentheses are (current state, default state). If they differ, someone changed the boolean at runtime without making it persistent.

Setting a Boolean

Use setsebool to change a boolean at runtime:

[root@rhel9 ~]# setsebool httpd_can_network_connect on

This change takes effect immediately but does not survive a reboot. To make it persistent, add the -P flag:

[root@rhel9 ~]# setsebool -P httpd_can_network_connect on

The -P flag writes the value to the policy store on disk, so it persists across reboots. This is almost always what you want in production. The command may take a few seconds because it recompiles the policy module.

Essential httpd Booleans

If you run Apache or Nginx on RHEL 9, these are the booleans you will encounter most often:

BooleanDefaultPurpose
httpd_can_network_connectoffAllow httpd to make outbound TCP connections to any port. Required for reverse proxy setups where Apache connects to a backend application server.
httpd_can_network_connect_dboffAllow httpd to connect to database ports (MySQL, PostgreSQL, etc.). Needed when a PHP or Python web app connects directly to a database.
httpd_enable_homedirsoffAllow httpd to read user home directories. Used for the classic ~user/public_html feature.
httpd_can_sendmailoffAllow httpd to send email. Required for web apps that send mail via sendmail or a local SMTP relay.
httpd_use_nfsoffAllow httpd to serve files from NFS mounts. Without this, Apache gets permission denied on any NFS-mounted document root.
httpd_enable_cgionAllow httpd to execute CGI scripts. Enabled by default, but you can disable it to harden a server that does not need CGI.

Common Booleans for Other Services

Samba:

NFS:

SSH and login:

Practical Example: Reverse Proxy to Node.js

You have Apache configured as a reverse proxy to a Node.js application running on port 3000. After enabling the proxy config and restarting httpd, the proxy returns 503 errors. The audit log shows:

type=AVC msg=audit(...): avc: denied { name_connect } for pid=2345
comm="httpd" dest=3000 scontext=system_u:system_r:httpd_t:s0
tcontext=system_u:object_r:unreserved_port_t:s0 tclass=tcp_socket

The name_connect denial tells you httpd tried to establish an outbound TCP connection and was blocked. The fix:

[root@rhel9 ~]# setsebool -P httpd_can_network_connect on

One command, persistent across reboots, and the proxy works. No custom policy module needed.

Booleans vs Custom Policy Modules

Booleans are the first thing to check when you hit an SELinux denial. They cover the most common variations in how services are deployed. Only write a custom policy module when no existing boolean addresses your specific use case. The order of operations should be:

  1. Check for file context issues (wrong labels) - fix with restorecon
  2. Check for a relevant boolean - fix with setsebool -P
  3. If neither works, analyze the AVC denial and create a custom module with audit2allow

Most SELinux problems on RHEL 9 are solved at step 1 or step 2. Custom modules are rarely needed unless you are running non-standard software.