- Reproducing the failure
- Inspecting system logs and AVC denials
- Allowing httpd to bind to a custom TCP port
- Fixing file context labels so httpd can read content
- Verifying the service and content are accessible
1. Attempt to start Apache
Reproduce the failure by starting httpd:Permission denied when attempting to bind to port 9495 — this commonly indicates an SELinux denial on the network port.
2. Inspect SELinux-related messages
Check system logs for SELinux messages (on many distributions either/var/log/messages or journalctl):
9495. setroubleshoot suggests running sealert for the full report.
View the full sealert report (sample ID shown):
ausearch:
name_bind for tcp port 9495.
3. Check current SELinux port labels for httpd
List the SELinux port types and filter for http-related entries:9495 is not listed under http_port_t. SELinux will block httpd from binding to ports that are not labeled for the service by default.
4. Allow httpd to bind to port 9495
Add a port mapping so SELinux permits httpd to bind to your chosen port. Use the type appropriate for your use case;http_port_t is the common choice for general web server ports:
semanage reports the mapping already exists, modify the existing mapping:
403 Forbidden. That indicates a separate SELinux denial — typically a file-label (context) issue preventing httpd from reading the files.
5. Verify HTTP access and file context
Attempt to fetch the index page:/webcontent/html used here):
default_t instead of the expected httpd_sys_content_t. That mismatch prevents httpd from reading the files under the default SELinux policy.
Check the logs for related AVC denials:
6. Relabel files so httpd can read them
To allow httpd to serve files from/webcontent, add a file-context rule mapping that path to httpd_sys_content_t and then apply the labels.
- Add the file-context rule (recursive pattern):
- Apply the new labels with
restorecon:
Quick reference — useful commands
On some systems the
semanage command is provided by the policycoreutils-python-utils or policycoreutils-python package. Install it with your distribution package manager if semanage is not present (for example: dnf install -y policycoreutils-python-utils or yum install -y policycoreutils-python).Be cautious when opening ports or changing file contexts. Only allow ports and contexts that are necessary for your service. If you are unsure, generate an SELinux policy module using
audit2allow and review it before installing with semodule -i.Recap and troubleshooting checklist
- Use
getenforceto confirm SELinux mode (Enforcing vs Permissive). - For port bind failures:
- Inspect
systemctl statusand logs. - Use
ausearch -m AVCandsealertfor detailed SELinux denial messages. - Use
semanage port -lto find the correct SELinux port type and add the port withsemanage port -a -t <type> -p tcp <port>.
- Inspect
- For file-access (403) errors:
- Check file contexts with
ls -Z. - Add a file-context rule with
semanage fcontextand apply it withrestorecon -R.
- Check file contexts with
- For creating temporary or permanent policy exceptions:
- Collect the denial with
ausearchand feed toaudit2allowto create a local module (-M) and install it withsemodule -i.
- Collect the denial with
- Always verify changes by restarting the service and testing access.
Links and references
- SELinux project: https://selinuxproject.org/
- Red Hat SELinux guide: https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/
- semanage man page:
man semanage - audit2allow and ausearch: https://linux.die.net/man/8/audit2allow