Prosody keeps an account's first password. The image's init registers
focus and jvb only once, so after a credential rotation it prints
"User exists" and keeps the old passwords, while jicofo and the
videobridge start with the new ones. Jicofo then fails with
"SASLError using SCRAM-SHA-1: not-authorized" and no conference can
start.
After compose up the role now deletes and re-registers both accounts
with their current passwords, through the container_address lookup so
it works in compose and swarm.
Found by the full-cycle gate of #1165, whose second pass runs after a
credential rotation.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
The mod_auth_ldap2 override redeclares VirtualHost "meet.jitsi" with
authentication = "ldap2". It was staged whenever LDAP was enabled, also
with SSO, where JITSI_AUTH_TYPE is internal and ENABLE_AUTH is false:
the web client then logs in anonymously, Prosody offers no matching
mechanism, and every conference join fails with
"connfail[no-auth-mech]" and reloads every 17 seconds. The role's own
spec only reaches the prejoin lobby, so it never noticed.
The override is now staged only when JITSI_AUTH_TYPE is ldap, and an
override left by an earlier deploy is removed otherwise.
Found by the new Matrix Jitsi spec against the shared Jitsi (#1165).
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
A handler name was doing two jobs at once: the line an operator reads in the
play output, and the identifier a `notify:` binds to. The two pull in opposite
directions -- the log wants "restart the SSH service, with diagnostics", the
binding wants a token that survives quoting, YAML flow style and a shell
round-trip -- and a name that changes for readability silently changes which
handler runs.
Every handler that a notify reached by name now carries a `listen:` with that
exact wording, so the binding is explicit before anything is renamed. The
topics themselves become identifiers: `compose up` reads `compose-up`,
`Restart NFS ganesha` reads `restart-nfs-ganesha`, 22 of them across both
sides of every notify. Where the topic is assembled at runtime, both branches
moved together: the conditional in sys-service carries two literals, and the
LDAP renderer interpolates `import-{{ folder }}-ldif-files`, which is what
makes those handlers reachable at all.
Freed from the binding, the names take the emoji prefix every other task line
already has.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Add tests/lint/repository/test_task_file_numbering.py: numbered task
files use exactly two leading digits, a numbered *_core.yml must be
00_core.yml, per directory the numbers are unique/consecutive and start
at 01 (00 with a core file), numbered includes appear in ascending
order, and shared helpers live in tasks/utils/ instead of the numbered
chain.
Apply it across every role: rename NN_core.yml to 00_core.yml with a
consecutive down-shift of the siblings, move letter-suffix children into
a subdirectory named after their parent task, relocate helpers included
from more than one place into tasks/utils/, and update every reference
(include_tasks, path_absolute, .ansible-lint-ignore, requirement docs).
Legacy narration comments in the touched files are deleted; the upstream
xwiki.properties reference block opts out via nocheck. The unused
MAILU_IP6_PUBLIC var (only ever named in now-removed comments) is dropped.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Add tests/lint/repository/test_name_emoji_and_length.py: every Ansible task
name and GitHub Actions workflow/job/step name must start with an emoji (first
char not 0-9/A-Za-z) and be <= 80 chars.
- emit emoji names at the source: cli/build/include generator now writes
"🔧 setup <app>" / "🚿 flush handlers after <app>" so generated
tasks/groups/*-roles.yml satisfy the convention too
- convert existing task/step/job/workflow names to emoji-prefixed, choosing a
task-fitting icon per action (📦 install, ✅ ensure, 🔍 probe, 🥾 bootstrap,
🚀 deploy, 🧩 service-module load, ⬇️ checkout, 📂 include-routines, ...)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Swarm rejected the jitsi replicas with 'bind source path does not exist' for the jicofo/jvb/config/transcripts dirs, because 02_manager_ops pre-created only the prosody dirs. Add the remaining meta/volumes.yml bind sources to the dir-creation loop.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Across roles/web-app-*, the typical body shape is:
- include_role: sys-stk-full (or sys-svc-compose) cluster prereqs
- <host-fs writes, container exec, compose exec> stack-host only
Under swarm-mode delegation the second group only makes sense on the
host that holds the compose stack (manager), but the role plays on
every host in groups[<role>] so workers abort on missing paths.
Two workflow sweeps (gate-manager-ops + gate-manager-ops-01core, 58
agents total, discover/plan/adversarial-verify per role) plus three
manual fixes surfaced 27 roles to refactor. Each role keeps
sys-stk-full ungated so worker-side prereqs (sys-svc-container, NFS
client) still bootstrap; the trailing manager-only block either moves
into a new tasks/02_manager_ops.yml included with
when: IS_STACK_HOST | bool (SUB_FILE pattern) or gets the gate
inlined on the one or two trailing tasks (INLINE pattern). In
compose mode IS_STACK_HOST stays true so single-host deploys are
unchanged.
Manual catches the workflow agents missed:
- web-app-fediwall: utils/once/flag.yml lives AT THE END of 01_core,
not at the start; preserved verbatim outside the gate so workers
still flip the run_once_<role> fact.
- web-app-xwiki: a pre-existing block(...) wraps sys-stk-full plus
_flush_config.yml; gated only the _flush_config.yml include so
sys-stk-full keeps running on workers.
- web-app-dashboard: 02_javascript.yml (creates /opt/compose/dashboard/
JS dirs) ran BEFORE sys-stk-full and was ungated; added the gate.
Roles touched (INLINE): akaunting, jenkins, magento, mobilizon
Roles touched (SUB_FILE): baserow, dashboard, decidim, erpnext,
fediwall, friendica, gitea, jitsi, keycloak, listmonk, littlejs,
mailu, matomo, moodle, odoo, openproject, opentalk, pixelfed,
shopware, suitecrm, taiga, xwiki, zammad
Adds the four-container Jitsi Meet stack (web, prosody, jicofo, jvb) with a
3-variant matrix: V1 oauth2-proxy gate + Keycloak LDAP federation, V2
no-auth anonymous, V3 direct prosody mod_auth_ldap2 against svc-db-openldap.
Auth model is oauth2-proxy at the reverse proxy because Jitsi has no
native OIDC adapter — JWT-via-Keycloak would require a custom token
server outside this repo. The role injects a fixed-position
`[data-injected-logout]` button via templates/javascript.js.j2 so the
no-built-in-logout React SPA satisfies the persona contract's
no-direct-URL logout rule. V2/V3 declare PERSONA_BIBER_BLOCKED /
PERSONA_ADMINISTRATOR_BLOCKED because the shared persona helpers only
model the OIDC redirect chain.
Final FULL-matrix `mode=reinstall full_cycle=true` run green across all
three variants (V1: 6/6 pass, V2/V3: 2 pass + 4 blocked skips).
Also lands utils/parse_trace.py — a small zipfile helper used during
the iteration to extract URL traces from playwright .trace bundles.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>