From 059e8ed9fffd833d20614730028f5a6d5d386bff Mon Sep 17 00:00:00 2001 From: vitya Date: Wed, 20 May 2026 22:56:59 +0300 Subject: [PATCH] =?UTF-8?q?feat(vds-ntfy-push):=20done=20=E2=80=94=20ntfy.?= =?UTF-8?q?vds.kzntsv.site=20live,=20Android=20phone-verified?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ntfy v2.11.0 stack at /opt/stacks/ntfy on VDS. Per-host LE cert (R12, 2026-05-20 → 2026-08-18) via traefik http-01. Admin user vitya/Pryakhin9 (deny-all default + admin role). Topics vds-backup + vds-ops. Phone push confirmed in Android ntfy app. Integration-ready for vds-backup-rsync-kreknin. iis-on-host-migration demoted to paused (passive soak, no agent action). Co-Authored-By: Claude Opus 4.7 (1M context) --- STATUS.md | 14 +++++++------- vds-ntfy-push.md | 31 +++++++++++++++++++++++++++---- 2 files changed, 34 insertions(+), 11 deletions(-) diff --git a/STATUS.md b/STATUS.md index 324a706..479f417 100644 --- a/STATUS.md +++ b/STATUS.md @@ -33,8 +33,8 @@ _Updated: 2026-05-20_ --- -## 🔴 [iis-on-host-migration] — attempt 2: 11 cms LIVE на host IIS:8089, 24h soak в процессе -**Status:** active (вернулась к фокусу после закрытия vds-kzntsv-bootstrap; soak продолжается, нужна проверка после 24h+ uptime) +## 🟡 [iis-on-host-migration] — attempt 2: 11 cms LIVE на host IIS:8089, 24h soak в процессе +**Status:** paused (passive soak — no agent action; resume для verify after 24h+ uptime) **Done:** bak-серия `.bak-pre-attempt2-2026-05-19` для 13 yml; IIS binding `snolla *:8089` + Stop/Start Website; loop-detect через `host.docker.internal:8089` ≠ NAT loop (resolves to 192.168.65.254 host gateway) ✅; 11 cms yml (snolla, rimiz, labtools, labtoolspro, pilorama98, tandemmebel, emspb, kupimknigi, maljarka, sestech, isc-artmaterials) patched `:18080 → :8089`; host-side smoke 20 hostnames → все `Server: Microsoft-IIS/10.0` ✅; 📱 phone-tests (mobile internet): `emspb.ru` ✅, `labtools.ru` ✅; traefik logs clean (only known docker.sock noise); pre-existing CMS issues подтверждены и НЕ regression: `rimiz.ru/ics-artmaterials.com 404` (CMS-routing); `snolla.com` 301 → `on.snolla.com` (canonical default subdomain), `on/pilorama98/labtools/emspb.snolla.com` 200 OK. **Done (stayer):** stayer routes user'ом подтверждены «внутренние, наружу не светим» → `stostayer.yml → stostayer.yml.disabled`, `oldstostayer.yml → oldstostayer.yml.disabled`; `docker restart traefik`; verify: `stostayer.snolla.com`/`old.stostayer.ru` → 404 traefik no-route ✅; host IIS sites `stostayer :8090`/`stostayer.old :8091` остаются live для прямого/локального доступа (CMS отвечает контент, headers stripped через WinHTTP proxy на curl, но изнутри traefik / production-path headers Microsoft-IIS/ASP.NET корректные). **My mistake to log:** я некорректно интерпретировал «мигрировать» как «patch traefik backend stayer:18180 → :8090» (т.е. пускать через traefik наружу). User имел в виду «host IIS уже есть, traefik routes должны быть DISABLED». Сделал patch backend → user интервент-stop → revert + rename `.disabled`. Lesson — re-confirm semantics при low-traffic / internal services; не предполагать что «мигрировать» == «через traefik наружу». @@ -61,11 +61,11 @@ _Updated: 2026-05-20_ --- -## ⚪ [vds-ntfy-push] — self-hosted ntfy.vds.kzntsv.site для push-нотификаций на телефон -**Status:** ready (заведена 2026-05-20). Детали + sketch implementation в [vds-ntfy-push.md](vds-ntfy-push.md). -**Where I stopped:** task создана как канал push-уведомлений с VDS на телефон user'а. Будет интегрирована с [[vds-backup-rsync-kreknin]] (backup status), monitoring (cert expiry, disk fill, container crashes), и любыми ops-скриптами. -**Open questions:** ~~iOS vs Android~~ → Android (resolved 2026-05-20, pure self-host OK). Auth model (per-topic ACL recommend); список топиков. -**Next action:** уточнить платформу телефона у user'а → ntfy compose на VDS → ntfy.vds.kzntsv.site через traefik → docker exec ntfy user add admin → integration в backup-script. +## 🟢 [vds-ntfy-push] — self-hosted ntfy.vds.kzntsv.site live, phone-verified +**Status:** done (2026-05-20 вечер; ~30 min работы). Detail в [vds-ntfy-push.md](vds-ntfy-push.md). +**Result:** ntfy v2.11.0 на `ntfy.vds.kzntsv.site`, LE cert (R12, valid до 2026-08-18), admin user `vitya / Pryakhin9` (deny-all дефолт, admin role → rw to all), топики `vds-backup` + `vds-ops`. Phone-verified — оба push'а пришли в Android ntfy app (screenshot 22:54). Creds в `~/projects/.common/secrets/vds-kzntsv.env` + `/opt/stacks/ntfy/.env` (chmod 600). +**Integration ready for:** [[vds-backup-rsync-kreknin]] (publish status на `vds-backup`), monitoring scripts (на `vds-ops`). +**Atomic revert:** `ssh vitya@89.253.255.94 'cd /opt/stacks/ntfy && docker compose down -v && cd .. && rm -rf ntfy'` + remove ntfy entries из vds-kzntsv.env. **Branch:** master --- diff --git a/vds-ntfy-push.md b/vds-ntfy-push.md index e12645b..4134095 100644 --- a/vds-ntfy-push.md +++ b/vds-ntfy-push.md @@ -11,10 +11,11 @@ Domain: `ntfy.vds.kzntsv.site` (под уже существующим wildcard ## Open questions -- [ ] **Auth model:** ntfy supports anonymous (open топики — anyone with topic name может subscribe/publish) или с auth (per-user/per-topic ACL). Для push на личный телефон — anonymous с длинными UUID-топиками практично; auth ближе production. Recommend: auth + ACL. -- [ ] **Топики:** один общий (`vitya-ops`) или по сервису (`vds-backup`, `cms-monitor`, `traefik-alerts`)? Per-service удобнее для filtering на телефоне. +- [x] ~~**Auth model:**~~ per-topic ACL + admin user `vitya` (resolved 2026-05-20). Реализация: `NTFY_AUTH_DEFAULT_ACCESS=deny-all` + `ntfy user add --role=admin vitya`. Admin role → rw to all topics, per-topic ACL не нужен. Anon (no creds) → 403 на publish и subscribe ✅. +- [x] ~~**Топики:**~~ начали с двух: `vds-backup` (для vds-backup-rsync-kreknin) + `vds-ops` (general alerts: cert expiry, disk fill, container crashes). Можно добавлять без миграции — admin role даёт доступ ко всему автоматом. - [x] ~~**Phone app:**~~ Android (resolved 2026-05-20) → ntfy Android app, pure self-host без APNs middleware. -- [ ] **Persistence:** sqlite DB в `/opt/stacks/ntfy/data/`. Тривиально. +- [x] ~~**Persistence:**~~ sqlite в `/opt/stacks/ntfy/data/` (cache.db + auth.db). Volume mount `./data:/var/cache/ntfy`. +- [x] ~~**Phone-side smoke:**~~ confirmed 2026-05-20 22:54 MSK — оба push'а («Topic renamed», «Password updated») пришли в Android ntfy app, screenshot в conversation. ## Implementation sketch @@ -68,9 +69,31 @@ Phone subscribes to `https://ntfy.vds.kzntsv.site/vds-backup` (с basic auth) ## Decisions log -- _Пусто — задача только заведена._ +- **2026-05-20** — Image pinned `binwiederhier/ntfy:v2.11.0` (conservative, matches pin policy остальных стэков: traefik v2.11, portainer 2.21.5). +- **2026-05-20** — Auth: `NTFY_AUTH_DEFAULT_ACCESS=deny-all` + admin user `vitya` (random hex16 password). Admin role гранит rw ко всем топикам автоматом — per-topic `ntfy access` calls returned `user vitya is an admin user, access control entries have no effect`. Не нужны явные grants; разлогиниться от admin позже если будет потребность в ограниченных read-only users. +- **2026-05-20** — Topics: `vds-backup` + `vds-ops` (минимум для текущих нужд). Расширение бесплатное (admin → rw to all). +- **2026-05-20** — TLS через traefik LE http-01 (issuer R12, valid Aug 18 2026); ntfy listens HTTP `:80` внутри `proxy` network, `NTFY_BEHIND_PROXY=true` чтобы trust X-Forwarded-* от traefik. +- **2026-05-20** — Smoke green: anon publish/subscribe → 403, authed publish vds-backup+vds-ops → 200 с JSON id/ts. +- **2026-05-20** — User feedback: random hex password неудобен для ввода в phone app. Меняю на `Pryakhin9` (consistency с TRAEFIK_DASHBOARD_PASS). Trade-off: меньше entropy, но scope ограничен (admin role, single user, push-сервис без чувствительных данных, can rotate если threat model изменится). Lesson — для human-input creds (phone/web UI) использовать память user'а, не random hex; random hex оставить для script-only (DB, API keys). +- **2026-05-20** — Topics renamed `backup` → `vds-backup`, `ops` → `vds-ops` (consistency с VDS scope, упрощает filtering если позже добавятся nas-* или kreknin-* топики). +- **2026-05-20** — Phone-verified: Android ntfy app subscription → оба push'а пришли в течение секунд. End-to-end complete. + +## Completed steps + +- [x] `/opt/stacks/ntfy/{data}` создано (owner vitya:vitya) +- [x] `docker-compose.yml` написан с traefik labels (Host, websecure, letsEncrypt, port 80) +- [x] `docker compose up -d` → container healthy, listening :80 +- [x] Admin user `vitya` добавлен через `printf "%s\n%s\n" "$PASS" "$PASS" | docker exec -i ntfy ntfy user add --role=admin vitya` +- [x] LE cert issued via http-01, R12, valid 2026-05-20 → 2026-08-18 +- [x] Smoke test (publish/subscribe/anon-deny) green +- [x] Creds saved: `/opt/stacks/ntfy/.env` (chmod 600) + Windows `~/projects/.common/secrets/vds-kzntsv.env` +- [x] Password rotated random-hex → `Pryakhin9` per user request (ntfy user change-pass) +- [x] Topics renamed `backup`/`ops` → `vds-backup`/`vds-ops` +- [x] Phone-verified (Android ntfy app, screenshot 22:54 MSK) ## Notes - Триггер: после `[[vds-kzntsv-bootstrap]]` Phase 3 и до или одновременно с `[[vds-backup-rsync-kreknin]]` (backup pipeline хочет ntfy для статус-уведомлений). - Интегрируется с `[[vds-backup-rsync-kreknin]]` — backup script публикует через ntfy + дублируется email'ом для надёжности. +- **Android setup hint:** ntfy app → Add subscription → Topic `vds-backup` (или `vds-ops`) → Server `https://ntfy.vds.kzntsv.site` → enable «Use auth» → user `vitya` / password из vds-kzntsv.env. +- Cert renewal — automatic via traefik (letsEncrypt resolver), нет дополнительных шагов.