Files
board-viewer/.tasks/board-viewer-cron-deploy.md
vitya e4e1fa1254 task(cron-deploy): code complete; status 🟡 pending user-side deploy
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-22 15:10:18 +03:00

62 lines
4.4 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# board-viewer-cron-deploy
## Goal
Деплой статической HTML-доски на VDS под доменом `board.kzntsv.site`. Periodic regen через systemd timer ~5 мин. Traefik label для роутинга. DNS A-запись. Basic-auth через traefik (не in-app).
**TDD posture:** под carve-out «infrastructure / declarative» из `tdd-criteria`. Acceptance проверяется по факту deploy + curl, не unit-тестами. systemd unit-файлы и traefik labels — декларативные конфиги, не код.
## Key files
- `deploy/docker-compose.yml` — двухсервисный стек (build + web) на `proxy` network
- `deploy/Dockerfile.build` — build-image (node:22-alpine + cron-loop entrypoint)
- `deploy/nginx.conf` — static serving с Cache-Control
- `deploy/auth.toml.example` — шаблон Gitea token + board_viewer_repos
- `deploy/.env.example` — шаблон BOARD_VIEWER_USERS с правилом `$$` escape
- `deploy/README.md` — DNS / image build / bootstrap / smoke / DR steps
**Замечание:** acceptance изначально упоминал systemd timer, но user выбрал docker-compose stack (consistent с существующим VDS pattern Gitea/registry/etc.). Mechanism: `while true; do node cli.ts; sleep 300; done` внутри `board-viewer-build` контейнера. Логи через `docker compose logs`, не journalctl. Эффект тот же — каждые 5 мин regen.
## Acceptance criteria
- DNS `board.kzntsv.site` → VDS IP (Cloudflare / namecheap / wherever DNS живёт).
- Traefik route: `board.kzntsv.site` → static file serving из `/var/www/board-viewer/`.
- Basic-auth на traefik (middleware), креды из `.htpasswd`.
- systemd timer крутится каждые 5 мин, успешно дёргает reader + render, пишет в `/var/www/board-viewer/index.html`.
- Логи systemd видны через `journalctl -u board-viewer.service`.
- Health check: `curl -u user:pass https://board.kzntsv.site/` → HTML с актуальной доской.
- README.md описывает install steps (для disaster-recovery: «как поднять с нуля на новой машине»).
## Decisions log
- 2026-05-22: task создан промоушеном; carve-out из TDD под инфра (declarative configs).
- 2026-05-22: auth = traefik basic-auth, не in-app (фиксировано в дизайне).
- 2026-05-22: deploy-mechanism = docker-compose stack (рекомендация принята); systemd timer заменён на cron-loop внутри build container'а. Гомогенно с existing VDS pattern (Gitea, registry, ntfy).
- 2026-05-22: basicauth.users inline через env_file, `$$` escape для compose interpolation. Не нужно касаться traefik stack'а (mounting htpasswd в traefik потребовало бы изменения соседнего стека).
## Open questions
- [x] Host: VDS Rusonyx (тот же, где Gitea+traefik). Network `proxy`, путь `/opt/stacks/board-viewer/` — verified via vds-ops inspect of gitea container.
- [x] Multi-user basic-auth: схема поддерживает (comma-separated), но MVP — single user.
- [x] Rate-limit: 4 repos × ~2 calls/repo (STATUS.md fetch + commit log per task slug) каждые 5 мин = ~24-100 calls. Token'изированный Gitea не упрётся.
## Completed steps
- [x] docker-compose.yml с двумя сервисами и traefik labels
- [x] Dockerfile.build для cron-loop image
- [x] nginx.conf для static serving
- [x] auth.toml.example + .env.example + README.md с полным install path
- [x] .gitignore исключает реальные `auth.toml` и `.env`
- [x] compose syntax validated via `docker compose config`
## Pending (user-side actions)
- [ ] DNS A-record `board.kzntsv.site` → VDS IP
- [ ] `docker build && docker push` на dev-машине → `registry.kzntsv.site/board-viewer-build:latest`
- [ ] Bootstrap `/opt/stacks/board-viewer/` на VDS + заполнить `auth.toml` и `.env`
- [ ] `docker compose up -d` + smoke `curl -u user:pass https://board.kzntsv.site/`
## Notes
Зависит от `board-viewer-html-render` — нужен артефакт для деплоя (хотя бы placeholder). Можно стартовать параллельно с DNS-записью (она прогревается).