fix(kix): keep the backend config so a recreated container stops reinstalling

compose gave up on `dependency failed to start: container kix-backend is unhealthy`,
and the backend's own log names the reason:

    psql -q -h postgres -p 5432 -U kix kix -c 'CREATE EXTENSION ...'   -> succeeds
    /opt/kix/bin/kix.Console.pl Maint::Config::Rebuild --allow-root    -> FATAL:
        password authentication failed for user "kix"

Two calls in a row, one working and one not, with the same database. psql takes its
password from PGPASSWORD; the perl layer takes it from /opt/kix/config/01main, and the
entrypoint's own `[ ! -f /opt/kix/config/01main ]` test reports that file missing on
every start.

/opt/kix/config was on no volume. Every recreated container therefore loses 01main,
re-enters the first-install path, and runs it against a database that is already
installed. The credential rotation between the sync and the async pass is only what
made the container get recreated; any redeploy does this.

Everything else was ruled out from the run rather than assumed: the ALTER USER landed
(changed: true, 22:18:44), the rendered env carried the same value (22:18:57), there is
exactly one postgres container and 192.168.200.2 is its address, and it stayed up and
healthy across the whole window.

Persisting the directory alone would trade one failure for another: the entrypoint runs
`ln -s '/opt/kix/conf.d/*' /opt/kix/config/` on every start, unquoted-glob-style but with
the glob quoted, so it creates a single dangling link named `*` -- and the second start
would find it there. The link points at a path with a literal asterisk and nothing reads
it, so clear_stale_conf_link.yml removes it on every node before the stack comes up.

The password patch declaration follows the friendica pattern and needs 2c4e0e18b to work
at all: its groups are extended-regex, which basic-regex sed rejected outright.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
kevinveenbirkenbachandClaude Opus 5 committed 2026-08-31 15:58:55 +02:00
1 parent 2c4e0e18b1
commit 8986b21270
5 files changed
+43

No files matched your search

+11
View File
@@ -1,4 +1,15 @@
---
kix_config:
type: volume
name: kix_kix_config
nfs:
uid: "110010100"
gid: "110010100"
mode: "0770"
mounts:
- service: backend
target: /opt/kix/config
kix_shared:
type: volume
name: kix_kix_shared
+3
View File
@@ -20,5 +20,8 @@
dest: "{{ KIX_PROXY_NGINX_HOST_PATH }}"
mode: "0644"
- name: "🧹 Clear the stale conf.d link before the backend starts"
ansible.builtin.include_tasks: utils/clear_stale_conf_link.yml
- name: "🔄 Flush handlers so '{{ KIX_PROXY_CONTAINER }}' is up before further config"
meta: flush_handlers
@@ -0,0 +1,21 @@
---
- name: "🔍 Resolve the mountpoint of '{{ KIX_CONFIG_VOLUME }}'"
ansible.builtin.command: "container volume inspect --format {% raw %}'{{.Mountpoint}}'{% endraw %} {{ KIX_CONFIG_VOLUME | quote }}"
register: kix_config_mountpoint
changed_when: false
failed_when: false
delegate_to: "{{ item }}"
loop: "{{ (groups['svc-swarm-node'] | default([])) or [inventory_hostname] }}"
- name: "🧹 Drop the dangling '*' link the entrypoint cannot recreate over"
ansible.builtin.file:
path: "{{ [ mount.stdout | trim, '*' ] | path_join }}"
state: absent
when:
- mount.rc == 0
- (mount.stdout | trim) | length > 0
delegate_to: "{{ mount.item }}"
loop: "{{ kix_config_mountpoint.results }}"
loop_control:
loop_var: mount
label: "{{ mount.item }}"
@@ -0,0 +1,7 @@
---
- name: "🔑 Realign the password KIX persisted in its config"
include_tasks: "{{ lookup('path_absolute', 'roles/sys-svc-rdbms/tasks/utils/patch_persisted_password.yml') }}"
vars:
patch_volume: "kix_kix_config"
patch_config_rel: "01main"
patch_expression: "s|(\\$Self->\\{'?DatabasePw'?\\}\\s*=\\s*')[^']*(';)|\\1@PASSWORD@\\2|"
+1
View File
@@ -6,6 +6,7 @@ swarm_stack_converge_retries: 600
KIX_PROXY_SERVICE: "proxy"
KIX_BACKEND_SERVICE: "backend"
KIX_CONFIG_VOLUME: "{{ lookup('volume', application_id, 'kix_config').name }}"
KIX_FRONTEND_SERVICE: "frontend"
KIX_PROXY_CONTAINER: "{{ lookup('config', application_id, 'services.' ~ KIX_PROXY_SERVICE ~ '.name') }}"