Wait for the Nextcloud unit to leave activating before checking is-active

The first real run of this play stopped at "Verify Nextcloud is running":

    fatal: [emily]: FAILED! => {"cmd": ["systemctl", "--user", "is-active",
    "nextcloud.service"], "rc": 3, "stdout": "activating"}

Nothing was wrong with the container. `systemctl start` returns while the unit
is still `activating` -- the start job completes before conmon has signalled
readiness -- and `is-active` exits 3 for that state, so checking once reports a
healthy start as a failure. Every other app role here checks is-active only
after a wait that already tolerates startup (postgres waits on pg_isready,
valkey on valkey-cli ping, bitwarden on its healthcheck); Nextcloud is the one
where the check comes first, because its readiness gates are the expensive ones.

The wait retries only through the transition. A unit that is `failed` or
`inactive` is not going to become `active` by waiting, so that fails immediately
with the state in the message rather than five minutes later. What genuinely
needs patience -- the entrypoint rsyncing code and running `occ upgrade` before
Apache answers -- is the readiness gate that follows, which already has the
richer rescue.
This commit is contained in:
tanshu committed 2026-10-16 11:29:34 +05:30
1 parent 09c964f34b
commit 8be7ba212b
1 file changed
+18 -1
+18 -1
View File
@@ -90,9 +90,26 @@
# Quadlet honours [Install] WantedBy= when it generates the unit, so # Quadlet honours [Install] WantedBy= when it generates the unit, so
# `systemctl --user enable` is neither needed nor possible on a generated unit. # `systemctl --user enable` is neither needed nor possible on a generated unit.
- name: Verify Nextcloud is running #
# This waits rather than checking once. `systemctl start` returns while the unit
# is still `activating`: the start job is done before conmon has signalled
# readiness, and `is-active` exits 3 for `activating` — so a single check reports
# a healthy start as a failure. That is exactly what happened on this play's
# first real run, which stopped here with `stdout: "activating"`.
#
# It retries only through that transition. A unit that is `failed` or `inactive`
# is not going to become `active` by waiting, so it fails immediately with the
# state in the message instead of five minutes later. The case that genuinely
# needs patience — the app answering yet — is the readiness gate below, which has
# the richer rescue.
- name: Wait for the Nextcloud unit to become active
ansible.builtin.command: "systemctl --user is-active {{ unit_name }}" ansible.builtin.command: "systemctl --user is-active {{ unit_name }}"
register: nextcloud_active register: nextcloud_active
until: >-
nextcloud_active.stdout == 'active'
or nextcloud_active.stdout not in ['activating', 'reloading']
retries: 60
delay: 5
changed_when: false changed_when: false
failed_when: nextcloud_active.stdout != 'active' failed_when: nextcloud_active.stdout != 'active'