sysadmin · July 1, 2026 · 15 min read

SELinux, part two.
ports, booleans, and audit2allow.

httpd will not bind to port 8080, the app needs outbound DB connections, and a backup denial needs a custom policy module. Three SELinux fixes beyond file contexts.

// what we’re getting into
  1. The ticket
  2. Concept review. The tool for each job.
  3. Permit httpd on port 8080
  4. Allow outbound connections with a boolean
  5. Build a module from denials with audit2allow
  6. Booleans worth knowing
  7. Exam questions
  8. Final checklist: confirm everything works

Yesterday’s 403 turned out to be a file label. Today webadmin is back with three more denials, and none of them are about labels. Compliance wants httpd on port 8080, but the service will not even start, it dies with a bind error. The new app has to reach the database over the network, and httpd is blocked from making outbound connections at all. And the backup account is being refused read access to user homes, with the denial sitting right there in the audit log. Three problems, three different SELinux tools.

That is the whole lesson of part two: SELinux is more than file contexts. A non-standard port needs the port taught to the policy, an outbound connection needs a boolean flipped on, and a denial that fits none of the prebuilt fixes can be compiled into its own small policy module. Reach for the wrong one and you burn twenty minutes. Match the tool to the denial and each fix is two commands.

The ticket

bash
getenforce
sudo dnf install -y policycoreutils-python-utils setroubleshoot-server
which semanage audit2allow

Concept review. The tool for each job.

bash
man semanage-port
man semanage-boolean
man audit2allow
five SELinux fix tools
chcon                       temporary file relabel
semanage fcontext + restorecon   permanent file relabel
semanage port               permit a service on a non-standard port
setsebool -P                toggle a prebuilt policy boolean
audit2allow                 build a custom module from denial logs

Denials land in /var/log/audit/audit.log, and you query them with ausearch -m AVC -ts recent.

Permit httpd on port 8080

Reconfigure httpd to listen on 8080 and it fails to start, because SELinux only lets httpd bind to a known set of ports. Add 8080 to that set with semanage port, open the firewall too, and it starts.

bash
sudo sed -i 's/^Listen 80$/Listen 8080/' /etc/httpd/conf/httpd.conf
sudo systemctl restart httpd
# Job for httpd.service failed. (98)Address already in use: could not bind
sudo ausearch -m AVC -ts recent | tail -3
# avc:  denied  { name_bind } for  comm="httpd" src=8080
#   scontext=...:httpd_t:s0 tcontext=...:unreserved_port_t:s0

sudo semanage port -l | grep http_port_t
# http_port_t   tcp   80, 81, 443, 488, 8008, 8009, 8443, 9000
# no 8080 in that list. that is the whole problem.
sudo semanage port -a -t http_port_t -p tcp 8080
sudo semanage port -l | grep http_port_t
# http_port_t   tcp   8080, 80, 81, 443, 488, 8008, 8009, 8443, 9000

sudo firewall-cmd --permanent --add-port=8080/tcp && sudo firewall-cmd --reload
sudo systemctl restart httpd
systemctl is-active httpd    # active
curl -I http://localhost:8080
note: SELinux blocking and firewall blocking are separate problems. The SELinux port rule lets httpd bind, the firewall rule lets traffic reach it. A non-standard port usually needs both.

Allow outbound connections with a boolean

Many common exceptions already exist as on/off switches called booleans. httpd making outbound network connections is one. The -P flag makes the change persist across reboots, and forgetting it is the classic mistake.

bash
getsebool -a | grep httpd | head -20
getsebool httpd_can_network_connect    # off by default

sudo setsebool -P httpd_can_network_connect on
getsebool httpd_can_network_connect    # on, and persistent because of -P

Build a module from denials with audit2allow

When no file label, port, or boolean fits, you can turn the denials themselves into a policy module. Reproduce the denial, review what audit2allow proposes, then build and load the module. Always read the generated rules before loading, because a blind allow can grant something dangerous.

bash
# reproduce a denial
sudo touch /home/dev1/.test_file
sudo -u svc_auto cat /home/dev1/.test_file 2>&1

# see what would be allowed
sudo ausearch -m AVC -ts recent | audit2allow -a

# build a loadable module (creates backup_homes.te and .pp)
sudo ausearch -m AVC -ts recent | audit2allow -M backup_homes
cat backup_homes.te            # review before loading

sudo semodule -i backup_homes.pp
sudo semodule -l | grep backup_homes
# remove later with: sudo semodule -r backup_homes

Booleans worth knowing

common booleans
httpd_can_network_connect_db   httpd connects to DB ports
httpd_enable_homedirs          httpd serves user home directories
httpd_use_nfs                  httpd serves content from NFS

sudo setsebool -P httpd_can_network_connect_db on
sudo setsebool -P httpd_enable_homedirs on

Exam questions

Write the command first.

Q1. Display all httpd-related SELinux booleans and their state.

Q2. Allow httpd to listen on TCP port 8888, persistent across reboot.

Q3. A custom service is blocked by SELinux. Use the audit denials to build and load a module named mycustom.

Answers.

bash
# A1
getsebool -a | grep httpd
# A2
sudo semanage port -a -t http_port_t -p tcp 8888
sudo semanage port -l | grep http_port_t
# A3
sudo ausearch -m AVC -ts recent | audit2allow -M mycustom
cat mycustom.te    # review first
sudo semodule -i mycustom.pp

Final checklist: confirm everything works

If every check passes, the ticket is done.

bash
# 1. httpd binds to 8080 via the semanage port mapping
sudo semanage port -l | grep http_port_t; systemctl is-active httpd

# 2. httpd_can_network_connect is on and persistent
getsebool httpd_can_network_connect

# 3. custom module built, reviewed, and loaded
sudo semodule -l | grep backup_homes

# 4. all three exam commands written from scratch
# 5. tracker entry checked off

Reply to webadmin: port 8080 added to http_port_t via semanage port, httpd_can_network_connect set on persistently, and a reviewed audit2allow module loaded for the backup home access.

next post
An NFS server and client, exported and mounted