core.service
Manage OS services: activity and boot autostart.
core.service manages two independent axes of a service: activity (running / stopped / restarted) and autostart at boot (enabled). The backend is chosen from the host's init system. running and enabled are idempotent; restarted is deliberately non-idempotent — the restart always runs. Requires root.
Requirements
- Rootrequired
- Side
soul-side - Collection
soulstack.services - Category
services
run_as_rootexec_subprocessAuto from host facts (os.init_system); when absent, runtime detection: systemd → openrc → sysv. If none is found, the step fails.
States
core.service.running — The service is active. The optional enabled controls autostart in the same step.
The service was inactive and got started, or enabled was set and autostart had to change.
The service is already active and autostart is in the required state.
Parameters
| Param | Type | Required / default | Description |
|---|---|---|---|
name | string | required | Service/unit name. |
enabled | bool | optional | true → also enable, false → disable, omitted → leave autostart alone. |
daemon_reload | stringauto | always | never | optional · auto | systemctl daemon-reload before start (systemd): auto = on NeedDaemonReload, always = unconditionally, never = opt-out. openrc/sysv — no-op (ADR-015). |
Example — running + enabled in one step
- name: Ensure node_exporter is running and enabled at boot module: core.service.running params: name: node_exporter enabled: trueOutput
| Field | Type | Description |
|---|---|---|
name | string | |
active | true | |
enabled | bool (if set) |
core.service.stopped — The service is stopped.
It was active and got stopped.
The service is already stopped.
Parameters
| Param | Type | Required / default | Description |
|---|---|---|---|
name | string | required | Service/unit name. |
Example — Stop a service before maintenance
- name: Stop nginx before maintenance module: core.service.stopped params: name: nginxOutput
| Field | Type | Description |
|---|---|---|
name | string | |
active | false |
core.service.restarted — Unconditional restart.
Always: the restart is requested explicitly, there is deliberately no idempotency here.
Never — the restart runs every time.
Parameters
| Param | Type | Required / default | Description |
|---|---|---|---|
name | string | required | Service/unit name. |
daemon_reload | stringauto | always | never | optional · auto | systemctl daemon-reload before restart (systemd): auto = on NeedDaemonReload, always = unconditionally, never = opt-out. openrc/sysv — no-op (ADR-015). |
Example — restarted on onchanges with a forced daemon-reload
- name: Restart redis after drop-in change (force daemon-reload) module: core.service.restarted onchanges: [redis_hardening_dropin] params: name: redis-server daemon_reload: alwaysOutput
| Field | Type | Description |
|---|---|---|
name | string | |
active | true |
core.service.enabled — Autostart at boot (a separate axis from activity).
Autostart was off and got turned on.
Autostart is already on.
Parameters
| Param | Type | Required / default | Description |
|---|---|---|---|
name | string | required | Service/unit name. |
daemon_reload | stringauto | always | never | optional · auto | systemctl daemon-reload before enable (systemd): auto = on NeedDaemonReload, always = unconditionally, never = opt-out. openrc/sysv — no-op (ADR-015). |
Example — Enable autostart without starting immediately
- name: Enable node_exporter at boot module: core.service.enabled params: name: node_exporterOutput
| Field | Type | Description |
|---|---|---|
name | string | |
enabled | true |
Reference
Supported init systems
| Init | How it is chosen |
|---|---|
| systemd | from the os.init_system fact, otherwise runtime detection (first) |
| openrc | same (second) |
| sysv | same (third) |
daemon_reload — re-reading unit files
systemd keeps unit definitions in memory. After a unit file changes on disk (for example, a drop-in rendered by core.file), systemctl restart silently restarts the service with the old definition until a daemon-reload is done. core.service does it itself.
| Value | Behavior (systemd) |
|---|---|
| auto (default) | Reload only on a real mismatch: the module checks NeedDaemonReload and re-reads unit files only if it is yes. |
| always | daemon-reload unconditionally before the action. |
| never | Explicit opt-out — no reload is done. |
Notes
- restarted is deliberately non-idempotent: changed=true always, the restart is requested explicitly.
- On non-systemd init (openrc / sysv) daemon_reload is a no-op at any value; whether a real reload happened is shown by reloaded: true in the output.
- Requires root.
Security & defaults
- stopped and restarted cause real downtime: name must come from the Destiny author — stopping the wrong unit is a denial of service.
- enabled locks in the unit's execution at every boot — control the source of the unit file as an executable artifact.
- enabled is orthogonal to activity: enable does not start the service, disable does not stop it. To guarantee a service is not running you need stopped.