fix(sys-stk-backend): let a dedicated postgres be realigned behind the wrapper

Discourse#1 of run 33414875521 failed on a rebuild that could not log in:

    PostgreSQL Database directory appears to contain a database; Skipping initialization
    FATAL:  password authentication failed for user "discourse"

Eight lines in the sidecar's log, all of that one class and nothing else. The
volume carried a cluster from an earlier run, so docker-entrypoint-initdb.d was
skipped and the role kept its pre-rotation password; the job log shows the launcher
being handed 8ilTTI... in the first pass and hgBFXE... in the second, exactly one
rotation apart.

The realignment for that exists and never ran. sys-stk-backend includes
sys-svc-compose with compose_handlers_flush hardcoded to false -- deliberately, so
the SSO-proxy sidecar can be rendered before anything flushes -- and then flushes
itself without the post-deploy step that up.yml pairs with its own flush. Counting
the rendered task names across the job: post_deploy ran for svc-net-tor and
svc-prx-openresty, both of which include sys-svc-compose directly, and for nobody
else. Discourse's two invocations both report
`false_condition: compose_handlers_flush | bool`.

Only the realignment is added back, not all of post_deploy. A first attempt included
the whole file and would have armed a 120s database-health wait and a swarm
convergence wait for the roles that reach compose through this wrapper; 46 roles set
compose_handlers_flush: true. The realignment itself is gated on compose + local +
postgres, which is 21 roles with a dedicated engine.

The task moves to sys-svc-rdbms/tasks/utils/, next to patch_persisted_password.yml.
Both halves of the same rotation work now live in the database role: one rewrites what
the application persisted, the other what the engine kept. sys-stk-backend calls it
after its flush because that is the only point where both facts hold -- the database
is this role's, and the stack is up. sys-svc-rdbms cannot call it itself: it runs
before sys-svc-compose and only notifies compose-up, so no container exists yet.
MariaDB needs none of this, because --init-file realigns it declaratively at start;
postgres has no equivalent for a cluster that already exists.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
kevinveenbirkenbachandClaude Opus 5 committed 2026-08-31 22:18:50 +02:00
1 parent c0b3ac9462
commit 536b12e174
3 files changed
+25 -14

No files matched your search

+8
View File
@@ -62,3 +62,11 @@
- name: "🚿 flush compose and SSO proxy"
meta: flush_handlers
when: compose_handlers_flush | bool
- name: "🔑 For '{{ application_id }}': realign a dedicated postgres"
include_tasks:
file: "{{ lookup('path_absolute', 'roles/sys-svc-rdbms/tasks/utils/realign_dedicated_db.yml') }}"
apply:
delegate_to: "{{ STACK_HOST }}"
run_once: true
when: compose_handlers_flush | bool
@@ -13,20 +13,8 @@
- (compose_mode_force | default('') or DEPLOYMENT_MODE) == 'compose'
- lookup('database', application_id, 'enabled') | bool
- name: "🔑 Realign the password a dedicated postgres kept from its initdb"
ansible.builtin.script: > # nocheck: container-address-quote script evals the fragment itself
{{ lookup('path_absolute', 'roles/svc-db-postgres/files/shell/set_postgres_superuser_password.sh') }}
{{ lookup('database', application_id, 'container') | quote }}
{{ lookup('database', application_id, 'password') | quote }}
{{ lookup('database', application_id, 'username') | quote }}
register: _app_db_realign
no_log: "{{ MASK_CREDENTIALS_IN_LOGS | bool }}"
changed_when: _app_db_realign.stdout is search('\\[CHANGED\\]')
failed_when: _app_db_realign.rc != 0 or _app_db_realign.stdout is search('\\[FAIL\\]')
when:
- (compose_mode_force | default('') or DEPLOYMENT_MODE) == 'compose'
- lookup('database', application_id, 'local') | bool
- lookup('database', application_id, 'type') == 'postgres'
- name: "🔑 For '{{ application_id }}': realign a dedicated postgres"
ansible.builtin.include_tasks: "{{ lookup('path_absolute', 'roles/sys-svc-rdbms/tasks/utils/realign_dedicated_db.yml') }}"
- name: "⏳ Wait until swarm tasks of '{{ application_id | get_entity_name }}' are running"
ansible.builtin.script: "{{ lookup('path_absolute', 'roles/sys-svc-compose/files/shell/swarm/stack_ready.sh') }}"
@@ -0,0 +1,15 @@
---
- name: "🔑 Realign the password a dedicated postgres kept from its initdb"
ansible.builtin.script: > # nocheck: container-address-quote script evals the fragment itself
{{ lookup('path_absolute', 'roles/svc-db-postgres/files/shell/set_postgres_superuser_password.sh') }}
{{ lookup('database', application_id, 'container') | quote }}
{{ lookup('database', application_id, 'password') | quote }}
{{ lookup('database', application_id, 'username') | quote }}
register: _app_db_realign
no_log: "{{ MASK_CREDENTIALS_IN_LOGS | bool }}"
changed_when: _app_db_realign.stdout is search('\\[CHANGED\\]')
failed_when: _app_db_realign.rc != 0 or _app_db_realign.stdout is search('\\[FAIL\\]')
when:
- (compose_mode_force | default('') or DEPLOYMENT_MODE) == 'compose'
- lookup('database', application_id, 'local') | bool
- lookup('database', application_id, 'type') == 'postgres'