Files
computer-playbook/roles/web-app-joomla/tasks/utils/patch/db_credentials.yml
kevinveenbirkenbachandClaude Opus 5 32f2798209 fix(joomla): realign the persisted DB password through the shared hook
Joomla keeps its DB credential in configuration.php on its own volume. CI rotates
credentials between the two passes, so in pass 2 the file holds a password MariaDB
no longer accepts. Job 99670614260 of run 33445831564:

  mariadb_mariadb.log   1058 x Access denied for user 'joomla'@'192.168.201.7' (using password: YES)
                        negative control on the same file: 'wordpress' -> 0
  joomla_joomla.1.*.log "resuming normal operations" 02:36:53, then the access log's
                        first line is "GET / HTTP/1.1" 500 216982, every ~5s

The role's own repair cannot reach that state. tasks/main.yml:21-26 flushes handlers
before including 02_manager_ops.yml, which is the only path to 05_patch.yml: the
converge gate wants a working configuration.php, and the repair wants the gate to
clear.

sys-svc-rdbms already runs a hook on the correct side of that gate, and it already
runs for joomla in both passes -- it skipped for exactly one reason (log line 103788):

    false_condition: _app_persisted_credentials is exists

main.yml:29-33 opts a role in by the existence of
roles/<app>/tasks/utils/patch/db_credentials.yml. friendica, kix, matomo, moodle and
nextcloud have one. This adds the sixth.

The expression was checked against the real line read out of the running volume, not
against a sample -- `public $password = '...';` with a leading tab. sed -E with it
returns that one line and leaves dbprefix, secret and smtppass untouched; smtppass in
particular would have been caught without the `public $` anchor. The shared script
cannot silently no-op either: patch_persisted_password.sh:47 prints
"FAILED: no line in configuration.php matches the patch expression" and exits 1.

Verified by deploy, pass 2:

    TASK [sys-svc-rdbms : 🔑 Realign the persisted database password wherever joomla_data lives]
      changed: true
      stdout: PATCHED

An earlier attempt moved the reconcile into the container entrypoint instead. It also
went green, and it was still the wrong mechanism: run against the image, that route
wipes the whole DB block when the credential resolves empty (database.py:104 returns
"password": "" for the no-database branch as a legitimate result) while php -l calls
the file clean; a password containing $0 or a trailing backslash writes a parse error
and still reports "changed" with rc 0; and a lost env var makes exec /entrypoint.sh
unreachable, so the container never starts again. Six files became one, and the path
now runs once per deploy instead of on every boot of every replica.
${PATCH_PASSWORD:?} in the shared script fires on empty as well as unset.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-01 11:49:51 +02:00

8 lines
350 B
YAML

---
- name: "🔑 Realign the password Joomla persisted in its config"
include_tasks: "{{ lookup('path_absolute', 'roles/sys-svc-rdbms/tasks/utils/patch_persisted_password.yml') }}"
vars:
patch_volume: "joomla_data"
patch_config_rel: "configuration.php"
patch_expression: "s|(public \\$password\\s*=\\s*')[^']*(';)|\\1@PASSWORD@\\2|"