Plan: W3+W4 — Pełne CI/CD i deployment compliance (bms-1)
Tracking issue: #3171 (closed 2026-07-09 — see reconciliation below, several gaps outlived the closure)
Powiązane: #3172 (artnet elimination), #3178 (monitoring reorg)
Architektura: docs/pinbox24-w3-w4-architecture-spec.md
Ostatnia aktualizacja: 2026-07-11
Tracker post-sesji 2026-07-08: #3425
Status update — 2026-07-11 reconciliation
Issue #3171 was closed 2026-07-09, but that closure only covered Fazy 0/1/2 as originally scoped.
A 2026-07-09 W3 cascading-outage incident (see docs/incidents/2026-07-09-w3-cascading-outage-postmortem.md)
and subsequent sessions did substantial additional work not reflected in the phases below. Reconciled
against live repo/issue state 2026-07-11:
Confirmed DONE (verified against current code/issues, not just assumed from the phase table):
- Faza 1 (mailgun + s3-v2 GitLab CI) — done 2026-07-09, as the doc already states.
- Faza 2 (secrets-sync full W3+W4+backends) — done, but in a different shape than originally
proposed: instead of one
sync-bms-1job extension, three separate jobs now handle it (sync-pinbox24-w3,sync-pinbox24-w4,sync-pinbox24-backendsin.github/workflows/secrets-sync.yml). Blocker #3400 (MAILGUN_AUTH_TOKEN parens breaking SSH heredoc) fixed via PR #3462, merged 2026-07-08. - #3407 (WSDL missing in v42-prod, GUS API ENOENT) — closed 2026-07-09.
- Gap 1 (wkhtml-v42-prod DNS
EAI_AGAIN) — resolved via dual-network isolation (#3193, #3228, MR !783), not a DNS fix per se. The Prometheus health-check follow-up was never done — see #3739. - Gap 10 (v42-notify-prod SOPS coverage) — confirmed zero gaps, 2026-07-08.
- New work this session (2026-07-09/11), not in the original plan at all:
- GitLab CI “autoheal” added to both W3 (
p24-v-3.2) and W4 (p24-back-ts) — re-derivesbackend-environment.env/s3-environment.envfrom the bms-1 SOPS cache before deploy scripts run, so a GitLab git-clean no longer wipes untracked env files (root cause of the 2026-07-09 incident). MRs !68/!788. v32-prod-reso/v32-prod-socketsidecars brought under secrets-sync (files-only, no force-recreate — see open question below) — PR #3694.bms1-dr-plan.mdrewritten with a full W3+W4 container/secrets inventory and off-host encrypted config backup (PR #3662, #3672).mailgun-pipeline-exportershipped and deployed to bms-1 — advances Faza 5 (monitoring) for the mailgun/W4 pipeline specifically (issue #3688, PR #3705, #3724).s3-v2-v42-prodfully compose-managed + health-checked;v42-notify-prod/pdf-gen-v42-prod/git-deploy-v42-prodadded to secrets-sync (2026-07-11, #3704).
- GitLab CI “autoheal” added to both W3 (
Corrected — was reported done, actually is NOT:
- Issue #3542 (“W4 bms-1 — clean CI/CD run: docker-compose to GitLab + Phase 3A/B deploy scripts”)
was believed closed by PR #3558 in an earlier session. This was wrong — PR #3558 only closed
the issue’s five body verification goals (Wasabi/Redis/Mailgun/Mezmo checks); the issue title’s
actual scope (committing
docker-compose-w3.yml/docker-compose-w4.ymlto git, Faza 3A/3B deploy script cleanup) was never done. #3542 has been re-scoped (see issue comment 2026-07-11) and re-queued rather than left believed-complete.
Decisions made 2026-07-11 (resolving open D#/Gap items below):
- D5 (git-deploy-v42-prod keep/remove): audit first, before deciding — see #3734.
- D6 (WebSocket restart strategy): Option A — nightly-only restart window (20:00–06:00 UTC), not nginx-upstream rolling. Document in the runbook once Faza 3C lands.
- Gap 8 (persistent-patches bake-in vs volume-mount for W4): volume-mount, same pattern as W3.
- reso/socket no-force-recreate policy (PR #3694): not yet finalized — user wants an actual code/usage analysis of what the WebSocket functionality does before accepting “never restart” as permanent policy, rather than assuming it. See #3740.
Follow-up issues filed 2026-07-11 (all queued to the remote worker, Triage milestone):
- #3542 (re-scoped) — docker-compose-w3/w4.yml to git + deploy script cleanup + Gap 5 (redis-v42
depends_on/healthcheck) folded in - #3733 — rebuild v41-prod from source into ECR (untagged-image SPOF)
- #3734 — audit git-deploy-v42-prod (D5)
- #3735 — audit pdf-gen-v42-prod identity (D7/Gap 6)
- #3736 — audit W3 frontend for the same untagged-image risk as v41-prod (D9/Gap 12)
- #3737 — bring
GOOGLE_APPLICATION_CREDENTIALSunder SOPS management (Gap 7) - #3738 — fix + re-enable
w3_app_mongodb_password/w4_app_mongodb_passwordrotation (rotate-schedule.yml, dormant since 2026-07-05 despite #2639’s closure) + dedicatedw3_appMongoDB user for v42-prod’s mongojs connection (replacing RS0 admin credentials) - #3739 — wkhtml-v42-prod Prometheus health check (Faza 5 follow-up to the Gap 1 fix)
- #3740 — analyze v32-prod-socket WebSocket usage before finalizing the reso/socket sync policy
- #3741 — Faza 0 remainder: W3
MAILGUN_PASSWORDgap + remove 11 dead PayU/Przelewy24 keys - #3742 — Gap 11: resolve dead-credential verdict for Jabber/Twilio/OneSignal/ConvertAPI
Still genuinely blocked / not yet actionable:
- Faza 3C (W4) — git-tracked artifact + runbook DONE (PR #3771). Applying it live to
pinbox24/p24-back-ts(push branch + open MR) is blocked:GITLAB_ADMIN_PATlost visibility into thepinbox24GitLab group (404 on the group itself, empty membership list) — see #3775. The same #3775 blocker applies to applying Faza 3D (W3,p24-v-3.2) live; note Faza 3D’s git-tracked artifact is already merged (PR #3782) and its GitLab MR !70 was opened before this visibility regression — see the Faza 3D update below. - Gap 11 provider-dashboard checks may need human action (dashboard login access) — flagged in #3742.
Update 2026-07-11 (#3769) — Faza 3D done, pending MR review:
docker-compose.yml + .gitlab-ci.yml in the pinbox24/p24-v-3.2 GitLab repo reconciled against
docs/bms-1/docker-compose-w3.yml (source of truth): added prod-v-3-net network + restart: unless-stopped + the 6 persistent-patch bind mounts to the backend (v32-prod) service —
volume-mounted, not baked into the image, per the Gap 8 decision. v32-prod-reso/v32-prod-socket
are not defined in this GitLab-tracked compose file, so they are untouched here. #3740 is now
resolved (closed 2026-07-11): its verdict is a nightly-window (20:00–06:00 UTC) force-recreate
for those two sidecars — already encoded as the deploy:v32-prod-reso-socket:nightly job in the
merged docs/bms-1/gitlab-ci-w3.yml (PR #3782). The live implementation of that policy on
bms-1 is tracked separately in #3804 (gated on MR !70 landing first). GitLab MR:
pinbox24/p24-v-3.2!70 — open, awaiting
human review/merge (not merged by the agent, per process).
Cel — Definicja “compliant platform”
Platforma W3+W4 jest zgodna ze standardami gdy:
- SOPS = jedyne źródło prawdy — zero hardcoded credentials w deploy scripts
- secrets-sync.yml = jedyny mechanizm dostarczania — rotacja klucza → automatycznie do kontenera
- CI/CD = jedyna ścieżka wdrożenia kodu — wszystkie poprawki baked w obrazie przez GitLab CI, zero bind-montów dla kodu aplikacji
- Narażone klucze zrotowane — wszystkie credentials widoczne przed naprawą
- Docker-compose w git — zero konfiguracji istniejącej tylko w pamięci działających kontenerów
- Monitoring — PM2 restart alerting, endpoint health w Prometheus
Stan wejściowy (weryfikacja 2026-07-07)
Kontenery W4 (bms-1: 94.23.26.113)
| Container | Image | SOPS coverage | Status |
|---|---|---|---|
v42-prod | ECR v42-prod:merged-20260706-0512 | pinbox24-w4.env.sops — kompletny (65 kluczy) | ✅ działa, PM2 fork |
v42-notify-prod | ECR | pinbox24-w4.env.sops | ✅ zweryfikowane 2026-07-08 — zero gaps |
s3-v42-prod | ECR v4-s3 | pinbox24-w4.env.sops | ✅ działa |
s3-v2-v42-prod | ECR s3-v2 | pinbox24-backends.env.sops | Phase 1 |
mailgun-prod | local/ECR | pinbox24-backends.env.sops | Phase 1 |
redis-v42 | redis:7-alpine | statyczny — brak SOPS | ✅ local Redis, W4-only |
wkhtml-v42-prod | ECR wkhtmltopdf | brak SOPS | ⚠️ DNS EAI_AGAIN — diagnoza w toku |
pdf-gen-v42-prod | local | nieznany | ❓ niezidentyfikowany — audyt wymagany |
git-deploy-v42-prod | local | nieznany | ❓ deploy trigger — zastąpić CI/CD? |
v41-prod | untagged local (still running as-is; not cut over) | brak | ✅ backup 2026-07-08 → Wasabi tar.gz; ✅ 2026-07-11 (#3733) GitLab CI build→ECR pipeline restored + running digest protected in ECR (v41-prod:pre-ci-fix-running-20260711) — see docs/playbooks/v41-prod-ecr-rebuild.md |
Kontenery W3 (bms-1)
| Container | Image | SOPS coverage | Status |
|---|---|---|---|
v32-prod + 3 warianty (socket, reso) | ECR v32-prod | pinbox24-w3.env.sops — kompletny | ✅ |
s3-v32-prod + 3 warianty | ECR old-s3 | pinbox24-w3.env.sops | ✅ (MAILGUN_PASSWORD gap zamknięty — #3778) |
cron-v32-prod + 2 warianty | local | statyczne env — brak SOPS needed | ✅ |
Fazy (plan zaakceptowany w #3171)
Prerequisite: PR #3163 (merge → main)
Fix nginx round-robin (VIRTUAL_HOST na s3-v42-prod) + PM2 fork mode. Wymagany przed wszystkim.
Prerequisite: #3172 zakończone przed Phase 3
#3172 usuwa referencje artnet.pl z deploy scripts. Phase 3 (#3171) czyści te same scripts — muszą się nie nakładać. Kolejność: #3172 → merge → #3171 Phase 3.
Faza 0 — SOPS gaps (secret-manager, parallel z Fazą 1)
| Akcja | SOPS file | Klucze |
|---|---|---|
Dodaj MAILGUN_MONGODB_URL, MAILGUN_AUTH_TOKEN | pinbox24-backends.env.sops | z mailgun-environment.env na bms-1 |
| Dodaj brakujące W4 keys (PM2, Wasabi, MAILGUN_PASSWORD dla s3) | pinbox24-w4.env.sops | z s3-environment.env na bms-1 |
| Usuń 11 PayU/Przelewy24 kluczy (wyłączone) | pinbox24-w4.env.sops | D4: PAYU_, przelewy24 |
✅ MAILGUN_PASSWORD gap W3 — zamknięty (#3778) | pinbox24-w3.env.sops | Klucz jest w SOPS + dostarczany do s3-environment.env na bms-1. Uwaga: s3-v32-prod czyta mailgun creds z hardcoded config/default.js (obraz old-s3), nie z env — patrz nota niżej. MAILGUN_USER_NAME niepotrzebny (owner potwierdził). Hardening allowlistu → PR #4497. |
Zweryfikuj v42-notify-prod env — dodaj do SOPS jeśli brakuje | pinbox24-w4.env.sops | docker inspect v42-notify-prod |
Nota — W3
s3-v32-prodmailgun (#3778, zamknięte): kontener (obrazold-s3, bibliotekanode-config) czytaconfig.get('mailgun.username'|'.password')z hardcoded/app/config/default.js. Brakcustom-environment-variables.js, więc żadenMAILGUN_*zs3-environment.envnie jest mapowany do configu —MAILGUN_PASSWORD/MAILGUN_USER_NAMEw env są czytane 0 razy. Wniosek: dodawanieMAILGUN_USER_NAMEdo SOPS/sync byłoby no-op (owner potwierdził — nie dodane). SyncMAILGUN_PASSWORD(obecnie namain) pozostaje jako hygiene; hardening allowlistu → PR #4497. Osobny follow-up (sys-security):default.jshardcode’uje prod credentials w obrazieold-s3.
Faza 1 — mailgun + s3-v2 CI/CD (GitLab) ✅ DONE 2026-07-09
Zrealizowane (sesja 73):
pinbox24/p24-ms-mailgun(master):.gitlab-ci.yml— runnermailgun-bms1-autodeploy(tag dodany do runner ID 53991640, shell executor na bms-1). Build+deploy SUCCESS. Kontenermailgun-v42-proddziała z obrazumailgun-v42-prod:591bc43f(lokalnie zbudowany). Minimalne env (13 kluczy) przezprintf→/tmp/mailgun-deploy-${CI_PIPELINE_ID}.env. Stary ECR pipeline zastąpiony.pinbox24/pinbox24-ms-s3-v2(feature/scanque):.gitlab-ci.yml— runners3-v2-bms1-autodeploy(tag dodany do runner ID 53991639). Build SUCCESS (77s). Deploywhen: manual— czeka na Fazę 0 (brakuje s3-v2 credentials wpinbox24-backends.env.sops). Stary artnet.pl private registry pipeline zastąpiony. 5 persistent patches bind-mounted wdocker run.- bms-1 env permissions: hotfix
0640 root:gitlab-runnerzastosowany ręcznie + PR #3507 merged do main (commit8a616eb3). - bash
source→grep|cut: specjalne znaki wMAILGUN_AUTH_TOKENi innych kluczach łamiąsource. Nowe CI używagrep "^KEY=" file | head -1 | cut -d= -f2-dla wyciągania wartości.
Co pozostaje z Fazy 1:
- Faza 0: dodaj s3-v2 SOPS credentials → zmień s3-v2 CI deploy
when: manual→when: on_success - Usuń/zaktualizuj
sync-mailgun-environment.envstep w secrets-sync.yml (PR #3369) — teraz obsolete bo CI zarządza kontenerem bezpośrednio; sprawdź czy/root/mailgun-prod/istnieje na bms-1
Faza 2 — secrets-sync pełny W3+W4 (sync-bms-1)
BLOKER FAZY 2 — #3400:
sync-pinbox24-backendsfailuje boMAILGUN_AUTH_TOKENzawiera nawiasy()łamiące SSH heredoc arg passing. Job musi przejść zanim Faza 2 może być zakończona. Fix: quote lub base64-encode wartość przed SSH. Tracker: #3400 → #3425.
Rozszerzenie sync-bms-1 w secrets-sync.yml (target bms1-all) — deploy wszystkich SOPS plików na bms-1:
pinbox24-w3.env.sops→/opt/p24-infra/bms-1/pinbox24-w3.envpinbox24-w4.env.sops→/opt/p24-infra/bms-1/pinbox24-w4.envpinbox24-backends.env.sops→/opt/p24-infra/bms-1/pinbox24-backends.env
UWAGA: W połączeniu z PR-D (#3178 Track B) — jeden PR dla wszystkich secrets-sync.yml zmian.
Faza 3A — Deploy scripts W4 cleanup
Usuń hardcoded credentials z /root/builds/7N4sbbrB/0/pinbox24/p24-back-ts/ scripts.
Commituj docker-compose W4 do repo (docs/bms-1/docker-compose-w4.yml).
Usuń git-deploy-v42-prod jeśli zdecydujemy zastąpić CI/CD (patrz P1 gap #4).
Faza 3B — Deploy scripts W3 cleanup
Usuń hardcoded credentials z /home/gitlab-runner/builds/eZQeLfuJe/0/pinbox24/p24-v-3.2/ scripts
(autorytatywny, GitLab-runner; /root/builds/pn3C9eHo/... NIE jest katalogiem serwującym prod, ale
NIE jest porzucony — audyt on-server 2026-08-01 wykazał, że to aktywne źródło mountów W3-staging,
więc NIE usuwać go w całości — #4985, patrz docs/w3-w4-stack-operations.md §3).
Commituj docker-compose W3 do repo.
Faza 3C — Image CI/CD W4 (GitLab)
GitLab CI pipeline dla v42-prod:
- Build nowego obrazu — patches zostają volume-mounted, NIE baked in (Gap 8 decyzja 2026-07-11,
odwraca wcześniejsze “baked persistent patches” założenie — patrz
docker-compose-w4.yml) depends_on: redis-v42w compose — startup ordering- WebSocket graceful restart strategy (patrz P1 gap #6 / D6)
wkhtml-v42-prod— jeśli DNS fix gotowy, dodać health check (poza zakresem — #3739)
Status (2026-07-11):
- ✅ DONE — git-tracked artifact + runbook merged via PR #3771 (issue #3768):
docs/bms-1/gitlab-ci-w4.yml(proposed.gitlab-ci.yml, honors Gap 5/Gap 8/D6) +docs/playbooks/w4-gitlab-ci-image-pipeline.md(apply/rollback runbook). This was landed as a p24-infra-tracked source of truth first, same pattern asdocker-compose-w4.yml(#3542). - 🚧 BLOCKED — applying the artifact to the live
pinbox24/p24-back-tsGitLab repo (push branch + open MR, per the runbook’s single-file-PUT procedure) is blocked:GITLAB_ADMIN_PATcurrently has zero visibility into thepinbox24GitLab group (GET /groups/pinbox24→404, membership list empty), a regression from the reachable state recorded indocs/pinbox24/gitlab-repo-locations.md(2026-07-09). Token identity itself is valid (GET /user→200asradieu). Tracked in #3775 — needs a human to check/restore GitLab group membership (or reissue the PAT) before the MR can be opened.
Faza 3D — Image CI/CD W3 (GitLab) ✅ MR OPEN 2026-07-11 (#3769)
GitLab CI pipeline dla v32-prod. Rollback: jeśli pipeline fail po 4+ latach → zostaw na obecnym obrazie, dokumentuj jako tech-debt.
Wykonane (2026-07-11, issue #3769): docker-compose.yml w repo pinbox24/p24-v-3.2
zweryfikowany i wyrównany z docs/bms-1/docker-compose-w3.yml (source of truth) —
brakowało prod-v-3-net (parytet z reso/socket, #2826), restart: unless-stopped, oraz 6
volume-mountów persistent patches na v32-prod (zgodnie z decyzją Gap 8 — bind-mount, nie
bake do obrazu). .gitlab-ci.yml dostał komentarz dokumentujący scope + rollback policy
(bez automatycznego retry — zgodnie z wytyczną planu). v32-prod-reso/v32-prod-socket
poza scope tego compose file (nie są w nim zdefiniowane). #3740 zamknięte (2026-07-11):
werdykt to nocne okno force-recreate (20:00–06:00 UTC) — już zakodowane jako job
deploy:v32-prod-reso-socket:nightly w zmergowanym docs/bms-1/gitlab-ci-w3.yml (PR #3782).
Wdrożenie tej polityki na żywo na bms-1 śledzone osobno w #3804 (gated na merge MR !70).
MR: pinbox24/p24-v-3.2!70 —
otwarty, czeka na review/merge człowieka.
Faza 4 — Rotacje credentials
MAILGUN, JWT, Redis, Wasabi. Po weryfikacji Fazy 3.
Dodatkowe — w3_app MongoDB user (2026-07-08):
V42_v3MongoUrl (mongojs legacy w v42-prod) używa RS0 admin credentials — każda rotacja MONGODB_RS0_ADMIN_PASSWORD wymaga ręcznej aktualizacji (wystąpiło w PR #3359 jako hotfix po PR #3241). W Fazie 4:
- sys-admin: stwórz usera
w3_appna RS0 primary (bms-2) z dostępem tylko do kolekcji W3 - secret-manager: zaktualizuj
V42_v3MongoUrlwpinbox24-w4.env.sops— podmień admin credentials naw3_app - secrets-sync → restart v42-prod → potwierdź mongojs connected z dedykowanym userem Tracker: #3425
Faza 5 — Monitoring + SOPS minimalizacja
PM2 restart alerting (Prometheus). Endpoint health checks. Wkhtml health check.
Separacja W3/W4 — Analiza izolacji (2026-07-08)
Aktualny stan Docker (bms-1)
| Wymiar | Separacja | Stan | Wymagana akcja |
|---|---|---|---|
| Sieci Docker | W3 = prod-v-3-net, W4 = test-net | ⚠️ Częściowa — v32-prod NIE jest na prod-v-3-net (#2826) | Fix Faza 3B |
| Kontenery W4 | v42-prod, v42-notify-prod, s3-v42-prod, s3-v2-v42-prod, mailgun-prod, redis-v42, wkhtml-v42-prod, pdf-gen-v42-prod | ✅ Osobne — bez overlap z W3 | — |
| Kontenery W3 | v32-prod + socket/reso warianty, s3-v32-prod + warianty, cron-* | ✅ Osobne | — |
| Wspólne | nginx-proxy (nginx-proxy kontener, port 80/443) | ⚠️ Shared reverse proxy — świadome współdzielenie, nie ryzyko | Dokumentować |
Decyzja D10: mailgun-prod obsługuje tylko W4 (URL hardcoded v42-prod:3000). Nie ma shared mailgun między W3 i W4 — separacja kompletna dla mailguna.
Aktualny stan SOPS (separacja credentials)
| SOPS file | Zakres | Stan | Problem |
|---|---|---|---|
pinbox24-w4.env.sops | TYLKO W4 backend + s3 | ✅ Dedykowany | — |
pinbox24-w3.env.sops | TYLKO W3 backend + s3 | ✅ Dedykowany | ✅ MAILGUN_PASSWORD gap zamknięty (#3778) |
pinbox24-backends.env.sops | mailgun + s3-v2 (W4-only) | ⚠️ Nazwa sugeruje “oba”, ale zawiera tylko W4 | Rename lub dokumentować |
pinbox24-w4.env.sops ↔ pinbox24-w3.env.sops | MongoDB URI | ✅ Osobne usery (w4_app, w3_app — w3_app tbd) | V42_v3MongoUrl używa admin (Faza 4) |
Wniosek: SOPS separacja jest dobra strukturalnie. Główny problem: klucze współdzielą admin credentials zamiast dedykowanych userów per-stack.
Wymagana akcja — Faza 0: weryfikacja pełnej izolacji
Przed Fazą 2 (full secrets-sync) zweryfikować:
- Żaden klucz W3 nie jest w
pinbox24-w4.env.sopsi odwrotnie - MongoDB: W3 i W4 używają osobnych userów MongoDB (w3_app, w4_app) — nie admin
- Wasabi: W3 i W4 mają osobne IAM keys (lub shared? — audit potrzebny)
- Mailgun: API key W3 i W4 — ten sam? (różny subdomain? audit #3271)
Pre-Deployment Checklist — Weryfikacja całego środowiska W3/W4
Policy (2026-07-08): przed każdym deployem (Faza 3C/3D i dalej) wymagana pełna weryfikacja.
1. Health check wszystkich mikroserwisów
# W4 — sprawdź czy WSZYSTKIE kontenery działają
docker ps --format "table {{.Names}}\t{{.Status}}" | grep -E "v42|mailgun|wkhtml|pdf-gen|redis"
# W3 — sprawdź czy WSZYSTKIE kontenery działają
docker ps --format "table {{.Names}}\t{{.Status}}" | grep -E "v32|cron"
# Endpoint check
curl -s -o /dev/null -w "%{http_code}" https://api.w4.pinbox24.com/api/i18n/langs # 200
curl -s -o /dev/null -w "%{http_code}" https://api.w3.pinbox24.com/api/i18n/langs # 2002. MongoDB connectivity per-stack
# W4: mongoose connected, mongojs connected — sprawdź logi
docker logs v42-prod --since 2m | grep -i "mongoose\|mongojs\|connected\|auth"
# W3: mongoose connected
docker logs v32-prod --since 2m | grep -i "mongoose\|connected\|auth"3. Każdy mikroserwis = własne hasło (pre-deploy audit)
Przed deployem Fazy 3C/4 zweryfikować że każdy kontener ma własny dedykowany zestaw credentials, nie współdzielony admin:
| Mikroserwis | Expected user | Actual user | Status |
|---|---|---|---|
v42-prod mongoose | w4_app | V42_NEW_MONGODB_URI user | Verify |
v42-prod mongojs | w3_app (target) | RS0 admin obecnie | ⚠️ Fix w Fazie 4 |
s3-v42-prod | Wasabi W4 IAM user | V42_S3_WASABI_* | Audit Faza 0 |
mailgun-prod | Mailgun API key | MAILGUN_AUTH_TOKEN | Audit #3271 |
v32-prod mongoose | w3_app (target) | V32_NEW_MONGODB_URI user | Verify |
s3-v32-prod | Wasabi W3 IAM user | DB_URI user | Audit Faza 0 |
4. Rotacja haseł przy deploymencie (policy decyzja)
Pytanie: Czy rotować wszystkie hasła W3/W4 przy każdym deployu Fazy 3C/3D?
Analiza:
- Za rotacją: hardcoded credentials mogły być kompromitowane przed naprawą; “clean slate” po migracji do CI/CD
- Przeciw rotacji przy deploymencie: rotacja powinna być osobnym, przetestowanym krokiem; deploy + rotacja naraz = dwa możliwe punkty awarii
- Rekomendacja: Rotacja jako osobna Faza 4, nie wbudowana w deploy. Kolejność:
- Faza 3C/3D: deploy z istniejącymi credentials (testuj że środowisko działa)
- Faza 4: rotacja per-mikroserwis z weryfikacją po każdej rotacji
Wyjątek — rotacja OBOWIĄZKOWA przy deploymencie: jeśli credentials były widoczne w plaintext w logach CI/CD lub plikach na serwerze (issues #3216, #3333, #3428) → te konkretne klucze rotować w ramach Fazy 3A/3B, nie czekać na Fazę 4.
Zidentyfikowane luki (gap analysis 2026-07-07)
P0 — Blokujące Phase 3+ (muszą być rozwiązane PRZED fazami 3-5)
Gap 1: wkhtml-v42-prod DNS resolution failure
Problem: Error: getaddrinfo EAI_AGAIN wkhtml-v42-prod — v42-prod nie może rozwiązać nazwy PDF service.
Diagnoza: W toku (inna sesja).
Akcja przed Phase 3C:
- Zidentyfikować root cause (container down / wrong network / Docker DNS cache)
- Fix: upewnić się że
wkhtml-v42-prodjest natest-net(ta sama sieć co v42-prod) - Dodać
wkhtml-v42-proddo docker-compose W4 zrestart: unless-stopped - Health check
/healthzlub similar → Prometheus alert jeśli down
Gap 2: v41-prod untagged image — [DONE ✅ 2026-07-11, issue #3733]
Problem: Angular W4 frontend działa na lokalnym untagged image (v41-prod). Jeśli bms-1 się restartuje, image znika → W4 frontend niedostępny permanent.
Krok 1 (2026-07-08):
# Na bms-1:
docker save v41-prod | gzip > /tmp/v41-prod-backup-$(date +%Y%m%d).tar.gz
# Upload do Wasabi p24-infra bucket:
aws s3 cp /tmp/v41-prod-backup-*.tar.gz s3://p24-infra/backups/v41-prod/ --endpoint-url https://s3.eu-central-1.wasabisys.comKrok 2 (2026-07-11, #3733) — reproducible build path: Source zlokalizowany w GitLab
pinbox24/pinbox24-version-4 (Angular, .gitlab-ci.yml już istniał z pełnym
build → push-to-ECR → deploy pipeline — dokładnie ten sam wzorzec co v42-prod). Runner
tagi (autodeploy, prod-deploy-p24) wskazywały na stare, offline runnery — żywy runner
bms-1-autodeploy (id 54112450, te same tagi, już używany dla p24-back-ts/v42-prod) został
dopisany do projektu v41. Deploy joby przełączone na when: manual żeby zielony pipeline nie
podmieniał automatycznie działającego kontenera. Zweryfikowano też, że obraz aktualnie
uruchomiony na bms-1 (digest sha256:6ad6ea86...) już istniał w ECR (untagged, z ostatniego
udanego pipeline’u 2025-04-12) — otagowany teraz jako v41-prod:pre-ci-fix-running-20260711
dla jednoznacznego punktu odniesienia. Pełna procedura + cutover: docs/playbooks/v41-prod-ecr-rebuild.md.
Aktualizacja 2026-08-02 (#3733 infra-task worker): MR pinbox24/pinbox24-version-4!409
(ten sam when: manual gate dla gałęzi development/staging, co był już na master) został
scalony — obie gałęzie mają teraz spójny build→push-to-ECR + manual-deploy pipeline. Zielony
pipeline master (2669817220) potwierdzony: front-end-build + docker-image-build = success,
prod-front-end-deploy = manual (nie uruchomiony). Reproducible build path jest w pełni
przywrócony na obu gałęziach.
Nadal otwarte: secrets-sync.yml nie zarządza tym kontenerem (frontend nie ma runtime
secrets, więc priorytet niższy niż dla backendów); live cutover na nowy ECR image jest
świadomie odłożony jako human-action follow-up (deployuje NOWSZY bundle niż aktualnie
działający — wymaga side-by-side weryfikacji + go/no-go człowieka; procedura w
docs/playbooks/v41-prod-ecr-rebuild.md).
Gap 3: Docker-compose files nie w git
Problem: Konfiguracja wszystkich kontenerów istnieje tylko w pamięci działających procesów. Restart bms-1 = utrata stanu. Akcja w Phase 3A/3B:
docker inspectwszystkich kontenerów → wygeneruj docker-compose- Commit do
docs/bms-1/docker-compose-w3.ymlidocs/bms-1/docker-compose-w4.yml - Podstawa dla Phase 3C/3D (GitLab CI musi wiedzieć jak startować)
P1 — Ważne (adresować w Phase 3C/3D)
Gap 4: git-deploy-v42-prod — co to jest?
Problem: Container “git-based deploy trigger” — niejasna rola. W CI/CD świecie może być zbędny lub stanowić security risk (wykonuje git pull bez uwierzytelnienia?). Akcja: Audyt przed Phase 3C. Jeśli zastąpiony przez GitLab CI → wyłączyć. Jeśli aktywnie używany → udokumentować.
Gap 5: redis-v42 startup ordering
Problem: Jeśli bms-1 rebootuje i redis-v42 startuje PO v42-prod, RabbitMQ consumer crashuje przy inicjalizacji.
Akcja w Phase 3C docker-compose:
services:
v42-prod:
depends_on:
redis-v42:
condition: service_healthy
redis-v42:
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 5s
retries: 5Gap 6: pdf-gen-v42-prod — niezidentyfikowany kontener
Problem: Container istnieje na bms-1 ale nie ma go w mapie env vars ani SOPS coverage. Niejasna relacja z wkhtml-v42-prod.
Akcja: docker inspect pdf-gen-v42-prod + sprawdź logi → określ czy duplikat wkhtml, wrapper, czy osobna funkcja.
Gap 7: GOOGLE_APPLICATION_CREDENTIALS — zarządzanie JSON credentials
Problem: v42-prod potrzebuje pliku JSON z Google Service Account credentials. Ścieżka jest env varem, ale sam plik musi być na serwerze. Nie ma go w SOPS (binary file). Akcja w Phase 3C:
- Zidentyfikować obecną lokalizację pliku na bms-1
- Decyzja: volume mount (keep) vs. baked in image (nie, secrets w obrazie = złe) vs. secret store
- Rekomendacja: volume mount z
/opt/p24-infra/bms-1/google-credentials.json→ deploy przez secrets-sync analogicznie
Gap 8: Persistent patches — bake in image vs. volume
Problem: uploadAwsS3.helper.js i gus-api-regon-wsdl/ są volume-mounted jako persistent patches. W CI/CD świecie powinny być w obrazie.
Akcja w Phase 3C:
- Porównaj patch content z ECR image source
- Jeśli różnice są małe i dobrze zrozumiane → bake into image w GitLab CI
- Jeśli patches są zbyt ryzykowne do rederywacji → zostaw volume mount, dokumentuj
Update 2026-07-08 — WSDL brakuje w node_modules (#3407):
@pobidowski/gus-api-regon/dist/wsdl/UslugaBIRzewnPubl-ver11-test.wsdl missing w kontenerze v42-prod — PM2 ENOENT errors. Root cause: paczka npm nie zawiera WSDL w buildzie (nie: volume-mount problem). Niezależne od gap 8 strategii, ale musi być naprawione w Phase 3C (postinstall skrypt lub fork paczki). Tracker: #3407 → #3425.
Gap 9: Zero-downtime WebSocket restart
Problem: Socket.IO połączenia droppują przy restart v42-prod (docker-compose up -d). Klienci dostają transport close.
Opcje:
- Opcja A (prosta): Restart w godzinach nocnych (20:00-06:00) — akceptowalne dla 7 klientów W4
- Opcja B (lepsza): nginx upstream z 2 instancjami — jedno musi być alive, rolling deploy
- Opcja C (idealna): Socket.IO sticky sessions + nginx upstream health — wymaga refactoru Rekomendacja dla Phase 3C: Opcja A — nocne deploye. Dokumentować w runbooku.
Gap 10: v42-notify-prod — brak w mapie SOPS ✅ DONE 2026-07-08
Problem: Kontener notification microservice nie ma zweryfikowanych env vars ani coverage w SOPS.
Wynik audytu 2026-07-08: Zero gaps. Wszystkie env vars v42-notify-prod pokryte w pinbox24-w4.env.sops. Mikroservice Discord webhook — credentials przekazywane w request body, brak własnych SOPS kluczy do dodania.
P2 — Do weryfikacji (niskie ryzyko)
Gap 11: Dead credentials w SOPS
Aktywność do sprawdzenia przed Phase 4 (rotacje):
- Jabber/XMPP (
jabber_HOST,jabber_JID,jabber_PASSWORD) — #3449: INCONCLUSIVE, nie martwe. Najsilniejszy sygnał kodu z czterech — dedykowanyjabber.helper.js+ zadanie w kolejce (messaging_jabber.js) + 5 modułów XMPP. Zero logów w oknie 14–40h (za krótkie, po force-recreate #3060). Pozostaje w Tier 3 (manual). - Twilio (
twilioAccountSid,twilioAuthToken) — #3449: INCONCLUSIVE, nie martwe.twilioService.js+ pełny SDK w 3 wariantach backendu. Pozostaje w Tier 3. - OneSignal (
onesignal_APP_ID,onesignal_APP_AUTH_KEY) — #3449: INCONCLUSIVE, nie martwe. Dedykowany controller+helper + SDK. Pozostaje w Tier 3. - Mailgun (
V32_MAILGUN_API_KEY) — #3449: LIVE consumer w rodzinies3-v32-prod(mailgun-js +src/tmpStorage/mailgun/); nieobecny tylko wv32-prod. Nie usuwać. Follow-up: potwierdzić domenę/konto (dashboard Mailgun EU → secret-manager); rozstrzyga D8/D10. - ConvertAPI (
CONVERT_API) — używane? Alternatywa dla wkhtml? (poza zakresem #3449 — nadal do sprawdzenia)
#3449 usunięcia zero — żaden z 4 integracji nie dał czystego dowodu “martwe”; wszystkie zachowane w Tier 3 (manual) i wypisane w docs/sops-templates/pinbox24-w3.keys z notatką + follow-up. Realny werdykt live/dead wymaga: (a) sprawdzenia dashboardów providerów (secret-manager), lub (b) ponownego audytu logów po 72h+ stabilnego uptime (infra-task/sys-admin). Dopiero po tym: Jeśli nieaktywne → usunąć z SOPS (dead credentials = attack surface reduction).
Gap 12: W3 frontend — brak w planie
Angular frontend W3 — status nieznany. Czy jest lokalny untagged image jak v41-prod? Audyt wymagany.
Zaktualizowana kolejność wykonania
[DONE ✅ 2026-07-08]
Gap 2: v41-prod image → Wasabi: s3://p24-infra/backups/docker-images/v41-prod-backup-20260708.tar.gz
Gap 10: v42-notify-prod env audit → zero gaps, SOPS kompletny
mongojs hotfix: V42_v3MongoUrl zaktualizowany (PR #3359) — hasło zsynchronizowane z MONGODB_RS0_ADMIN_PASSWORD
[PR-A]
Merge PR #3163 → main (nginx fix + PM2 fork)
[RÓWNOLEGLE po PR-A]
#3172: artnet.pl elimination + dane migration
Gap 1: wkhtml DNS fix (inna sesja diagnozuje)
Gap 6: pdf-gen-v42-prod audit
#3400: MAILGUN_AUTH_TOKEN parens fix w secrets-sync.yml ← BLOKER FAZY 2, dispatch równolegle
[PR-B, po PR-A]
Faza 0: SOPS gaps (secret-manager)
[PR-C]
Faza 1: mailgun + s3-v2 GitLab CI
[PR-D — COMBINED z #3178, po #3400 DONE]
secrets-sync.yml: sync-bms-1 extension + Track B jobs
[PR-E — po PR-D, po #3172 DONE]
Faza 3A: W4 deploy scripts cleanup
→ Gap 3: docker-compose W4 do git
→ Gap 4: git-deploy-v42-prod decyzja
Faza 3B: W3 deploy scripts cleanup
→ Gap 3: docker-compose W3 do git
[PR-F]
Faza 3C: W4 image CI/CD
→ Gap 5: redis-v42 depends_on
→ Gap 7: GOOGLE_APPLICATION_CREDENTIALS → volume managed
→ Gap 8: persistent patches strategy
→ Gap 9: nocne-deploy policy (WebSocket)
+ Gap 1: wkhtml health check (jeśli fix gotowy)
[PR-G]
Faza 3D: W3 image CI/CD
[PR-H]
Faza 4: Credential rotations (po P2 Gap 11 audit)
+ w3_app MongoDB user → podmiana admin w V42_v3MongoUrl (patrz §Faza 4 powyżej)
+ #3407 WSDL fix → postinstall lub fork @pobidowski/gus-api-regon
[PR-I]
Faza 5: PM2 monitoring + Prometheus health checks
[PR-L (Track B #3178)]
Phase 2 service accounts
Playbooki do napisania (po wykonaniu)
docs/playbooks/pinbox24-wkhtml-troubleshooting.md— po diagnozie wkhtml DNSdocs/playbooks/bms-1-deployment-runbook.md— pełny runbook deploy W3+W4docs/playbooks/pinbox24-cicd-rollback.md— procedura rollback dla każdej fazy
Decyzje wymagające odpowiedzi przed Phase 3
| D# | Pytanie | Kto decyduje | Deadline |
|---|---|---|---|
| D5 | git-deploy-v42-prod — wyłączyć czy zachować? | Developer / audyt kodu | Przed Phase 3A |
| D6 | WebSocket restart — Opcja A (nocne) czy B (nginx upstream)? | Właściciel produktu | Przed Phase 3C |
| D7 | pdf-gen-v42-prod — co to jest i czy potrzebne? | Audyt logi + kod | Przed Phase 3C |
| D8 | Jabber/Twilio/OneSignal/Mailgun — aktywne? | #3449: bms-1 read-only audit INCONCLUSIVE (wszystkie wired, log-window za krótkie); Mailgun ma live consumer w s3-v32-prod. Zero usunięć, wszystkie w Tier 3. Ostateczny werdykt: dashboardy providerów (secret-manager) lub re-audyt logów po 72h+ (infra-task) | Przed Phase 4 |
| D9 | W3 frontend — lokalny untagged image jak v41-prod? | Audyt bms-1 | Przed Phase 3D |