You install a web server on Fedora, point it at a directory in your home folder, and the browser returns a 403 Forbidden error. You check the Apache logs and see nothing wrong. You check firewall-cmd and the port is open. The real blocker is sitting in the kernel, watching every file access and silently dropping the request. SELinux is doing exactly what it was designed to do. You do not need to disable it. You just need to flip a switch.
What is actually happening
SELinux does not rely on traditional Unix permissions alone. It tracks the identity of every process and the label of every file. When a process tries to read a file, the kernel checks a massive policy database to see if that specific process type is allowed to access that specific file type. The policy ships with strict defaults. A web server process is not allowed to read user home directories by default. A database client is not allowed to make outbound network connections by default. These defaults prevent a compromised service from wandering around your system.
Booleans are pre-defined toggles inside that policy. They act like circuit breakers. When you flip a boolean, you are not rewriting the policy. You are telling the kernel to bypass a specific, narrow restriction that the policy authors anticipated you might need. Think of it like a building security system. The main doors are locked. The security guard has a master key for the emergency exit. You are asking the guard to unlock that specific exit, not tearing down the entire fence.
The SELinux policy is compiled into a binary module that the kernel loads at boot. Booleans are embedded in that module as conditional statements. The kernel evaluates them on every access check. Flipping a boolean changes the evaluation path without requiring a policy recompile or a system reboot. This design keeps the security boundary intact while giving you surgical control over service behavior.
Read the policy description before you toggle anything. Guessing breaks the security model.
How to find the right boolean
You cannot guess which boolean you need. The policy contains hundreds of toggles. You must start with the denial message. When SELinux blocks an action, it writes an AVC denial to the audit log. The message looks like this:
type=AVC msg=audit(1715423891.123:456): avc: denied { read } for pid=1234 comm="httpd" name="index.html" dev="sda1" ino=56789 scontext=system_u:system_r:httpd_t:s0 tcontext=unconfined_u:object_r:user_home_t:s0 tclass=file permissive=0
Copy that exact line into your terminal. The scontext shows the process identity. The tcontext shows the file identity. The denied { read } shows the blocked action. You can search for the boolean that covers this exact combination using the sealert tool. It translates raw audit logs into plain English instructions.
sudo dnf install setroubleshoot-server # installs sealert and the SELinux troubleshooting daemon
sudo sealert -a /var/log/audit/audit.log # parses recent denials and suggests exact fixes
The output will point you to a specific boolean like httpd_enable_homedirs. It will also show you the exact command to run. Do not skip the description step. Every boolean has a documented scope.
semanage boolean -l | grep httpd_enable_homedirs # shows current state and policy description
The description tells you exactly what files and processes are affected. If the description mentions network access or database connections, verify that matches your use case. Fedora ships with setroubleshoot enabled by default. The daemon watches the audit log in real time and writes human-readable summaries to journalctl -t setroubleshoot. Run that command first. Read the actual error before guessing.
Listing and filtering booleans
The policy ships with a fixed set of booleans. You can query the entire list, but the output is long. Filter it by service name or keyword. The getsebool command reads the running kernel policy. It does not read configuration files.
getsebool -a | grep httpd # filters the active boolean list for web server related toggles
The output shows the boolean name and its current state. on means the kernel is currently allowing the behavior. off means the restriction is active. You can also query a single boolean directly.
getsebool httpd_can_network_connect # returns the exact runtime state of one toggle
This command is fast and reliable. Use it to audit your system after a deployment. Do not rely on memory or old documentation. Policy names change between Fedora releases.
Query the kernel directly. Trust the output, not the wiki.
Setting a boolean temporarily
Always test a boolean change before making it permanent. A misconfigured toggle can break a service or expose a directory you intended to keep private. Run the change without the persistence flag. The kernel applies it immediately. The change survives running processes but vanishes on reboot.
sudo setsebool httpd_enable_homedirs on # applies the toggle to the running kernel policy
Restart your service and test the behavior. If the web server suddenly serves the files correctly, the boolean is correct. If the service crashes or the browser still shows a 403, the denial was caused by something else. Reboot the machine to clear the temporary toggle. The system returns to its original state.
Temporary toggles are stored in kernel memory. They do not touch the disk. This makes them safe for staging environments and troubleshooting sessions. Use them to validate your hypothesis before committing to production.
Test in isolation. Reboot to reset.
Making the change permanent
Once you confirm the boolean solves the problem, write it to disk. The persistent configuration lives in /etc/selinux/. The setsebool command reads that directory on boot and applies the toggles before most services start.
sudo setsebool -P httpd_enable_homedirs on # writes the toggle to /etc/selinux/ for boot persistence
The -P flag stands for persistent. It does not change the running policy. It only updates the configuration file that the boot process reads. If you already ran the temporary command, the running policy is already correct. The -P flag ensures it stays that way after a power cycle.
The persistent file is a simple key-value store. You can view it directly if you need to audit changes.
cat /etc/selinux/targeted/active/booleans # shows the exact persistent state written by setsebool
Do not edit this file by hand. The setsebool command handles formatting and validation. Manual edits cause boot failures when the policy loader encounters invalid syntax. Trust the package manager. Manual file edits drift, snapshots stay.
Verify it worked
Do not assume the command succeeded. SELinux configuration drift happens when users edit files manually or run commands as the wrong user. Query the current state directly from the kernel.
getsebool httpd_enable_homedirs # queries the running policy for the exact boolean state
The output returns httpd_enable_homedirs --> on. If it returns off, the persistent flag did not apply correctly or a boot script overwrote it. Check /etc/selinux/targeted/booleans for syntax errors. Verify that your service is actually running under the expected SELinux domain. Some third-party packages run processes in unconfined_t by mistake. Booleans only affect labeled domains.
Run a test request against the service. Check the audit log one more time to confirm the denial is gone.
sudo ausearch -m avc -ts recent # shows only AVC denials from the last few minutes
An empty output means the kernel is no longer blocking the action. The toggle is working.
Verify with the kernel. Do not guess.
Common pitfalls and what the error looks like
The most common mistake is enabling a boolean that sounds right but covers a different process type. SELinux separates services by domain. httpd_t is the web server domain. nginx_t is the nginx domain. A boolean named httpd_can_network_connect does not affect nginx. You must match the boolean name to the actual service running.
Another pitfall is ignoring the direction of the connection. Network booleans are split into inbound and outbound. httpd_can_network_connect allows the web server to reach external databases or APIs. It does not allow external clients to reach the web server. Inbound traffic is controlled by firewalld and SELinux port labels. Confusing the two leads to services that appear to work locally but fail in production.
You will also see denials that sealert cannot resolve with a boolean. Some actions require custom policy modules or file relabeling. If sealert suggests restorecon or semanage fcontext, you are dealing with a file label issue, not a boolean issue. Run the suggested command. Do not force a boolean when the file context is wrong.
SELinux denials also appear when you move files between directories. The file keeps its old label. The new directory expects a different label. The kernel blocks the access. This is not a boolean problem. It is a context mismatch. Run restorecon -Rv /path/to/directory to fix it.
Match the tool to the symptom. Do not hammer with booleans.
When to use booleans vs alternatives
SELinux offers several ways to adjust policy. Pick the tool that matches your threat model.
Use booleans when you need to flip a pre-approved policy switch for a specific service behavior. Use restorecon when files have incorrect security labels after a manual move or copy operation. Use semanage fcontext when you need to add a permanent label rule for a custom directory path. Use audit2allow when you are writing a custom policy module for an application that ships without SELinux support. Use setenforce 0 only when you are actively debugging a broken system and need to confirm SELinux is the blocker. Stay in enforcing mode for production.
Pick the narrowest tool. Leave the rest locked.