
If you want to Configure SELinux on Fedora 44, the first thing to know is that SELinux is not the enemy. It is a security layer that blocks unsafe access, logs the denial, and helps you fix the real problem instead of hiding it. In a Fedora 44 setup, that usually means a service, file label, port label, or boolean needs adjustment, not that SELinux should be turned off.
This guide shows you how to configure SELinux on Fedora 44 setup the right way, using a practical Linux server tutorial style. You will learn how to check status, read denials, change modes safely, label files and ports, and use booleans or custom policy only when needed. The goal is simple: keep SELinux enforcing and keep your system working.
I am writing this from the perspective of a sysadmin who has spent years fixing real production issues, not just repeating documentation. That means every step below explains both what to run and why it matters, so you can use the same process on a server, VM, or lab machine.
Prerequisites
- Fedora 44 installed and booted.
- sudo access or root access.
- A terminal session on the machine you want to configure.
- These tools available or installable:
policycoreutils,policycoreutils-python-utils,setools-console, andsetroubleshoot-server.
Step 1: Check the current SELinux state
Confirm enforcement mode
Run this first:
getenforce
This shows whether SELinux is enforcing, permissive, or disabled. You want to know the current state before changing anything because it tells you whether the system is actively blocking policy violations.
Expected output:
Enforcing
Get the full status
Use this command next:
sestatus
It gives more detail than getenforce, including the policy type, loaded policy, and whether SELinux is enabled in the kernel. That matters because two systems can both say “enabled” but still behave differently if one is permissive.
Expected output usually includes lines like these:
SELinux status: enabled
Current mode: enforcing
Policy from config file: targeted
Check your shell context
Run:
id -Z
This shows the SELinux context of your current shell. It matters because a normal admin shell often runs in an unconfined context, so it may not trigger the same denial that a service would hit.
Step 2: Understand SELinux labels
Know what the label means
SELinux does not just look at users and file permissions. It also checks labels, and those labels decide whether one process may access one object. Fedora Docs describes this as answering whether a subject may do an action to an object, which is the core idea behind SELinux.
A label often looks like this:
system_u:system_r:httpd_t:s0
For most Fedora setups, the type field is the key part you work with. That is why httpd_t, sshd_t, var_t, or httpd_sys_content_t matter so much during troubleshooting.
View file labels
Use:
ls -Z /var/www
This shows the SELinux type attached to each file or directory. If a web file has the wrong label, Apache or Nginx may fail even when Unix permissions look fine.
Why this matters: SELinux blocks based on type compatibility, so the label must match the service that needs access. A file in the wrong context is one of the most common reasons a service works in one folder and fails in another.
Step 3: Install the troubleshooting tools
Install what you need
Run:
sudo dnf install -y policycoreutils-python-utils setools-console setroubleshoot-server
This gives you tools like semanage, sesearch, and sealert, which are essential for real SELinux work. You can read raw audit logs without them, but those logs are much harder to interpret fast.
Why this matters: semanage lets you make persistent changes to file contexts, ports, and booleans. Without it, many fixes would only be temporary or awkward to maintain.
Verify the tools
Check that the commands exist:
semanage --help | head
sealert -h
You do not need to memorize every option now. The point is to make sure the troubleshooting toolkit is ready before you hit a denial.
Step 4: Read SELinux denial messages
Search the audit log
When something fails, look in the audit log first:
sudo ausearch -m AVC -ts recent
This shows recent SELinux denials. It helps you find the exact process, file, port, or action that was blocked.
Why this matters: guessing the fix is how people create bad policy. The audit log tells you what SELinux actually stopped, which is the only safe starting point.
Use the friendly report
Run:
sudo sealert -a /var/log/audit/audit.log
This turns low-level AVC records into a readable explanation. It often points you toward the right fix, such as a file label problem, a missing boolean, or a port mismatch.
Expected output example:
SELinux is preventing httpd from name_connect access on the tcp_socket port 8080.
That kind of message already tells you where to look next. It saves time and prevents random changes.
Step 5: Change SELinux mode safely
Use permissive mode for testing
If you need to test a problem quickly, use:
sudo setenforce 0
This moves SELinux into permissive mode. The system logs denials but does not block them, which helps you confirm whether SELinux is the cause of the failure.
Why this matters: permissive mode is for diagnosis, not for leaving a server exposed. It helps you collect evidence without breaking service while you troubleshoot.
Return to enforcing mode
When you are done testing, switch back:
sudo setenforce 1
This restores normal protection immediately. You should use enforcing mode in production because that is the state Fedora expects for real security.
Make the mode permanent
Edit the config file:
sudo nano /etc/selinux/config
Set:
SELINUX=enforcing
This controls the default mode after reboot. It matters because runtime changes vanish after restart, but config changes persist.
Step 6: Fix file label problems with semanage fcontext
Add a permanent file context rule
If your app serves files from a custom path, label them correctly:
sudo semanage fcontext -a -t httpd_sys_content_t "/srv/web/myapp(/.*)?"
This tells SELinux that the whole directory tree should use the web content type. It is better than chcon because the rule survives relabels and reboots.
Why this matters: Apache and Nginx need the right content label to read files outside the default web root. A path like /srv/web/myapp is not automatically trusted just because permissions are open.
Apply the label
Run:
sudo restorecon -Rv /srv/web/myapp
This applies the saved SELinux policy to existing files. The command is important because semanage fcontext adds the rule, but restorecon actually updates the files on disk.
Expected output example:
Relabeled /srv/web/myapp/index.html from system_u:object_r:var_t:s0 to system_u:object_r:httpd_sys_content_t:s0
That is the kind of fix that solves many web server denials cleanly.
Step 7: Fix port label problems with semanage port
Check allowed ports
If a service listens on a custom port, check the policy first:
sudo semanage port -l | grep http_port_t
This shows which TCP and UDP ports SELinux already allows for the service type. It matters because opening a port in firewalld does not override SELinux.
Add a new allowed port
If your service must use a non-default port, add it like this:
sudo semanage port -a -t http_port_t -p tcp 8888
This tells SELinux that TCP port 8888 should be treated like an HTTP port. Use this when the application is correct but the port is outside the default policy range.
Why this matters: a server can pass the firewall and still fail at the SELinux layer. The kernel checks SELinux port types before it allows the bind operation.
Verify the new rule
Check it with:
sudo semanage port -l | grep 8888
You should see the port tied to the correct type. If you do not, the service may still fail to start or bind correctly.
Step 8: Use SELinux booleans for supported exceptions
Find the right boolean
Run:
getsebool -a | grep httpd
This lists HTTPD-related booleans. Booleans are the cleanest fix when SELinux already has a supported switch for the behavior you need.
Enable a boolean permanently
Example:
sudo setsebool -P httpd_can_network_connect on
The -P flag makes the change persistent. Without it, the setting resets after reboot, which creates a confusing “it worked yesterday” problem.
Why this matters: booleans are often safer than writing a custom policy. They usually represent behavior the SELinux maintainers already reviewed and intended to allow when needed.
Check the result
Run:
getsebool httpd_can_network_connect
Expected output:
httpd_can_network_connect --> on
If it still shows off, the service may continue to fail even though you thought the fix was complete.
Step 9: Use audit2allow only when needed
Generate a local policy module
If file contexts, ports, and booleans do not solve the issue, you can generate a policy module:
sudo ausearch -m AVC -ts recent | audit2allow -M myapp_local
This creates a module from the recent denials. It is powerful, but it should be your last resort because it can allow more than you intended.
Review the policy first
Open the generated file:
cat myapp_local.te
Read it carefully before installing. This step matters because an automatically generated policy may be broader than the real need, and broad policy weakens the point of SELinux.
Install the module
If the rule is safe, load it:
sudo semodule -i myapp_local.pp
This adds the new policy to the system. You can remove it later with sudo semodule -r myapp_local if you no longer need it.
Troubleshooting
Error 1: Service works only after setenforce 0
This usually means SELinux is blocking a real access problem, not causing a false alarm. Check the audit log, then fix the file label, port type, or boolean instead of leaving the machine permissive.
Error 2: restorecon did not fix the issue
That often means the label rule was never added with semanage fcontext, or the rule path pattern was too narrow. Confirm the rule with semanage fcontext -l | grep /srv/web/myapp and then run restorecon again.
Error 3: The port is open but the service still cannot bind
This usually means firewalld is fine, but SELinux still does not allow that port type. Check semanage port -l, then add the correct SELinux port label if needed.
Error 4: Boolean changes disappear after reboot
That happens when you forget the -P flag with setsebool. Reapply the boolean with -P, then verify the value after reboot so you know it persists.
Error 5: audit2allow created something too broad
This means you generated a policy module from denials without reviewing the .te file carefully. Remove the module with semodule -r, then solve the issue with a narrower fix if possible.