mirror of
https://gitverse.ru/kpa39l/xmpp-server-prosody.git
synced 2026-09-29 09:45:02 +00:00
Initial commit: Hermes skill xmpp-server-prosody
This commit is contained in:
@@ -0,0 +1,79 @@
|
||||
# Production migration 0.11.9 → 13.0 (verified 2026-08-30, chat.nixg.ru / /opt/icq)
|
||||
|
||||
Live migration of the production XMPP server from Prosody 0.11.9 to 13.0
|
||||
(image `gitea.nixg.ru/hermes/icq-prosody:13.0`). Complements the parallel-stand
|
||||
recipe (`prosody-13-parallel-stand.md`) with the PROD-only steps and two
|
||||
regressions that only surface with real bridges/users.
|
||||
|
||||
## Steps
|
||||
1. **Backup first**: `cd /opt/icq && tar czf backups/pre-migration-13-$(date +%Y%m%d_%H%M%S).tar.gz config data certs modules webchat`
|
||||
2. **Swap image** in docker-compose.yml: `prosody/prosody:latest` → `gitea.nixg.ru/hermes/icq-prosody:13.0`
|
||||
(also remove obsolete top-level `version: "3.9"` — Compose v2 warns).
|
||||
3. `docker compose up -d prosody` then `docker exec icq-prosody prosodyctl check config`.
|
||||
|
||||
## Config changes 0.11.9 → 13.0 (prod)
|
||||
1. `component_ports = { 5347 }` — **REMOVED** in 13.0 (listener hardcoded on 5347; delete the line).
|
||||
The module-less `Component "telegram.nixg.ru"` block already raises the listener.
|
||||
2. **`"pubsub"` out of `modules_enabled`** on the VirtualHost → must be a separate
|
||||
`Component "pubsub.<domain>" "pubsub"`. Without this, startup fails:
|
||||
`Error initializing module 'pubsub' on '<host>': Pubsub should be loaded as a component`.
|
||||
3. **HTTP Upload regression — Slidge gets "No upload slot"**:
|
||||
- Symptom: slidge logs floods of `No upload slot in this IQ: <iq xmlns="jabber:client" id="0" />`
|
||||
(~180 / 10 min on a busy bridge). Attachments (images/videos) silently fail.
|
||||
- Cause: the 13.0-era community mod_http_upload only hands out slots to
|
||||
`origin.type == "c2s"` **or** JIDs in `http_upload_access`. A Slidge external
|
||||
component requests slots as a component → denied → empty result IQ.
|
||||
- Fix, inside the upload component block:
|
||||
```lua
|
||||
Component "upload.<domain>" "http_upload"
|
||||
http_upload_access = { "telegram.<domain>" }
|
||||
```
|
||||
- After fix: 0 errors. (`docker logs icq-slidgram --since 2m | grep -c "No upload slot"` = 0.)
|
||||
4. `cross_domain_websocket` is deprecated in 13.0 but STILL read by mod_websocket → keep it.
|
||||
(New mechanism is `http_cors_override`; no need to migrate yet.)
|
||||
5. Single global `log` block (13.0 tolerates only one).
|
||||
|
||||
## Post-migration verification (no client password needed)
|
||||
- `prosodyctl check config` → All checks passed.
|
||||
|
||||
## WebSocket SASL regression after 13.0: "no-auth-mech" / blank spinner
|
||||
|
||||
**Symptom:** Converse.js on https://chat.nixg.ru shows the login form for a split
|
||||
second, then an infinite white spinner. Browser devtools on the WS frame shows
|
||||
`<failure><no-auth-mech/></failure>` or the server offers NO SASL mechanisms.
|
||||
Prosody logs flood every ~1s with:
|
||||
`warn No stream features to offer on insecure session. Check encryption and security settings.`
|
||||
|
||||
**Cause:** TLS is terminated at the edge (Caddy → nginx → Prosody over plain HTTP
|
||||
:5280), so the WebSocket session arrives at Prosody as *insecure*. In 13.0
|
||||
mod_websocket only offers SASL on secure sessions; insecure → empty `<stream:features>`
|
||||
→ client cannot authenticate and reconnects forever. (On 0.11.x this silently worked.)
|
||||
|
||||
**Fix:** in the GLOBAL config section (before VirtualHost), set
|
||||
```lua
|
||||
consider_websocket_secure = true
|
||||
```
|
||||
This is mod_websocket's own option (`module:get_option_boolean("consider_websocket_secure")`,
|
||||
mod_websocket.lua:35, 286 — `session.secure = consider_websocket_secure or request.secure or session.secure`).
|
||||
- `trusted_proxies` does NOT fix this — it only affects IP/logging, not session secure-ness.
|
||||
- Do NOT set `c2s_require_encryption = false` — that would allow plaintext passwords on
|
||||
the external 5222 port. The webchat path is already TLS all the way to the browser.
|
||||
|
||||
**Verify:** after restart, prosody.log shows
|
||||
`Authenticated as user@nixg.ru [prosody:operator]` for WS logins and the
|
||||
`No stream features...` warnings stop. Headless check:
|
||||
`chromium --headless --no-sandbox --disable-gpu --virtual-time-budget=20000 --dump-dom https://chat.nixg.ru/ | grep -c converse-login-form` → 1.
|
||||
- Component auth: `grep "External component successfully authenticated" prosody.log` (timestamp after restart).
|
||||
- mod_privilege XEP-0356 live: `grep "privilege" prosody.log | grep "Archiving stanza"` — slidge-carbon-*
|
||||
stanza entries prove privileged message/roster delivery works on prod.
|
||||
- WebSocket path: raw handshake to the webchat port → `101 Switching Protocols` confirms nginx → Prosody 13.0.
|
||||
- SASL logic: slixmpp/raw connect with a WRONG password → `AUTH FAILED` proves the auth chain works.
|
||||
(Do not connect a second component with the same JID as the live bridge — Prosody logs
|
||||
`Second component attempted to connect, denying connection`; that is normal, not an error.)
|
||||
|
||||
## Gotchas
|
||||
- `docker exec icq-prosody sh -c 'ss/netstat...'` may show nothing if net-tools absent — rely on
|
||||
`prosody.log` ("Servers started", "Certificates loaded") and external handshakes instead.
|
||||
- Test-stand teardown for "stop until next update" (NOT delete):
|
||||
`docker stop icq-prosody-test && docker update --restart=no icq-prosody-test`.
|
||||
- Prod was re-verified healthy after: prosody/slidgram/webchat all Up, 0 upload errors.
|
||||
Reference in New Issue
Block a user