Investigate the denial
A fictional httpd service must read static content from /srv/dr-status. The file has mode 0644, but requests receive 403 and an associated AVC denial exists. Unix mode does not describe the entire decision: process domain, object type and SELinux policy also matter. Confirm process identity and traversed directories before attributing the whole failure to one layer. Do not turn the symptom into a request to disable SELinux or grant everyone write access. The objective is to permit the required operation while retaining control over unnecessary operations.
Map and apply
The example targets a disposable RHEL 10 VM with SELinux enforcing. sefcontext maintains the persistent association between /srv/dr-status(/.*)? and httpd_sys_content_t. The pattern covers the directory and descendants rather than all of /srv. That choice represents static read content rather than an upload area. A later task applies restorecon to existing objects. These are separate actions: a correct rule can coexist with incorrectly labelled files. chcon changes object labels but does not replace the persistent rule used by future reconciliation.
The handler that misses drift
Imagine the rule is already correct and an operator changed index.html’s label. If restorecon runs only as a handler notified by sefcontext changed, the next execution may not repair that drift. The example invokes reconciliation after creating content even without a rule change. The command may run on every pass without every pass needing label changes. The stdout-based changed_when is only a reporting convention in this example; acceptance must compare effective context and access behavior. Avoid making the functional decision depend on localized terminal text.
Accept with policy active
Inspect the local rule, compare expected and observed context, and test reading through the httpd process while SELinux remains enforcing. A request working only in permissive is diagnostic evidence rather than control acceptance. If content needs writing, separate the writable area and assess the appropriate type instead of applying a broad label to the entire tree. A new denial does not justify automatically generating permissive policy from the whole audit log; first look for incorrect paths, labels, ports and configuration.
Example limits
Syntax was validated with community.general 10.7.6, but this review performed no RHEL relabel or access test. The playbook creates content and mapping; it does not configure httpd DocumentRoot, VirtualHost, TLS or listeners. Prepare that integration separately on the VM and retain enforcing policy during tests. After another reconciliation and reboot, repeat the read and confirm the persistent association remains valid.
# Exercise for a disposable enforcing RHEL 10 VM.
# Syntax checked only; actual labels and httpd access remain unverified.
- name: Maintain a narrow read-only web content label
hosts: rhel_lab
become: true
gather_facts: true
pre_tasks:
- name: Require the intended lab and enforcing policy
ansible.builtin.assert:
that:
- lab_confirmed | default(false) | bool
- ansible_distribution == 'RedHat'
- ansible_distribution_major_version == '10'
- ansible_selinux.status == 'enabled'
- ansible_selinux.mode == 'enforcing'
tasks:
- name: Install the policy management dependency
ansible.builtin.package:
name: policycoreutils-python-utils
state: present
- name: Create the dedicated content directory
ansible.builtin.file:
path: /srv/dr-status
state: directory
owner: root
group: root
mode: '0755'
- name: Maintain the persistent path-to-type mapping
community.general.sefcontext:
target: '/srv/dr-status(/.*)?'
setype: httpd_sys_content_t
state: present
- name: Install synthetic read-only content
ansible.builtin.copy:
content: "DR synthetic status page\n"
dest: /srv/dr-status/index.html
owner: root
group: root
mode: '0644'
- name: Reconcile labels on existing files even if mapping did not change
ansible.builtin.command:
argv: [restorecon, -Rv, /srv/dr-status]
register: relabel
changed_when: relabel.stdout | length > 0
The rule is unchanged but the label is wrong; object reconciliation is still needed.
Common pitfalls
Confusing rule with label; relying only on notification; permissive as acceptance; Unix permissions as the whole explanation.
Related topics: LVM, filesystem and persistent mounting · Services, firewall and external validation
Verify persistent rule, effective label and authorized operation with policy active.
Reference: SELinux path mapping module · EX294 current objectives inspected 2026-09-30; RHCE in Ansible framework effective 2026-05-11; booking product version not publicly pinned