Three service dimensions
A service may be enabled yet stopped, or started without being configured to return at boot. A masked unit adds another restriction: it cannot start while the mask exists. Before removing that restriction, confirm whether it was an intentional operational measure. The example uses state: started and enabled: true for a lab httpd. It does not force masked: false because unmasking should not follow from a hidden assumption. In a handover, describe current state, boot policy and encountered restrictions.
Definition changes and process changes
When a unit file changes, daemon_reload lets systemd reread definitions. It does not by itself restart the process with new options. Distinguish that step from application reload and restart. state: restarted in a regular task interrupts the service on every execution; an appropriate handler limits that action to changes justifying it. Even with a handler, define the window and post-activation functional criterion. An active process does not prove database access or successful reconciliation.
Runtime and persistent firewall state
The exercise keeps firewalld active and adds http to the public zone in both permanent configuration and immediate state. The lab VM must have its test interface associated with that zone. A rule in the wrong zone does not address observed traffic. A permanent-only change may not yet apply at runtime; an immediate-only change may disappear after reload or reboot. Do not use global reload as an automatic response without analyzing other teams’ runtime changes. The module also needs the firewalld Python binding in the interpreter actually used on the node.
Observe from the consumer side
An HTTP request made on the server does not necessarily follow the consumer’s path. After checking listener, zone and rule, run a probe from the lab consumer segment. Specify expected status and content; a packaged welcome page does not represent the intended application. If service responds locally but the client fails, collect evidence by layer: listen address, route, host firewall, external control and protocol. Tie the decision to reopen traffic to the set of criteria rather than one green task.
Execute and prove persistence
Use only a disposable RHEL 10 VM and a prepared test interface. The example installs httpd and opens HTTP in that zone for study; it configures neither HTTPS nor a banking application. Check syntax, execute, record current and permanent state, repeat and measure interruptions. After a controlled reboot, confirm service, rules and the external probe again. This review executed only syntax and module-resolution checks. RHEL practice, external connectivity and persistence remain unproven.
# Exercise for a disposable RHEL 10 VM with active firewalld public zone.
# It starts a packaged httpd service; it does not configure TLS or a banking app.
# Syntax checked only. A separate client probe and reboot test remain required.
- name: Maintain service and firewall state with separate acceptance criteria
hosts: rhel_lab
become: true
gather_facts: true
pre_tasks:
- name: Require the intended lab
ansible.builtin.assert:
that:
- lab_confirmed | default(false) | bool
- ansible_distribution == 'RedHat'
- ansible_distribution_major_version == '10'
- ansible_service_mgr == 'systemd'
tasks:
- name: Install the lab web server and firewall Python binding
ansible.builtin.package:
name: [httpd, firewalld, python3-firewall]
state: present
- name: Keep firewall available now and after boot
ansible.builtin.systemd_service:
name: firewalld.service
state: started
enabled: true
- name: Keep the packaged web service available now and after boot
ansible.builtin.systemd_service:
name: httpd.service
state: started
enabled: true
- name: Configure both current and persistent lab-zone access
ansible.posix.firewalld:
zone: public
service: http
state: enabled
permanent: true
immediate: true
- name: Record unit state without treating it as business acceptance
ansible.builtin.command:
argv: [systemctl, show, httpd.service, --property=ActiveState, --property=UnitFileState]
register: unit_state
changed_when: false
- name: Show the observed unit fields
ansible.builtin.debug:
var: unit_state.stdout_lines
systemd shows active and enabled; the client still gets no response because the rule was placed in another zone.
Common pitfalls
Enabled as running; daemon_reload as restart; permanent rule as runtime; local probe as proof of the client path.
Related topics: LVM, filesystem and persistent mounting · SELinux: mappings and effective state
Accept current state, persistence and consumer access as separate criteria.
Reference: Systemd service module · EX294 current objectives inspected 2026-09-30; RHCE in Ansible framework effective 2026-05-11; booking product version not publicly pinned