4.4 KiB
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) наproxynetworkdeploy/Dockerfile.build— build-image (node:22-alpine + cron-loop entrypoint)deploy/nginx.conf— static serving с Cache-Controldeploy/auth.toml.example— шаблон Gitea token + board_viewer_reposdeploy/.env.example— шаблон BOARD_VIEWER_USERS с правилом$$escapedeploy/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
- Host: VDS Rusonyx (тот же, где Gitea+traefik). Network
proxy, путь/opt/stacks/board-viewer/— verified via vds-ops inspect of gitea container. - Multi-user basic-auth: схема поддерживает (comma-separated), но MVP — single user.
- Rate-limit: 4 repos × ~2 calls/repo (STATUS.md fetch + commit log per task slug) каждые 5 мин = ~24-100 calls. Token'изированный Gitea не упрётся.
Completed steps
- docker-compose.yml с двумя сервисами и traefik labels
- Dockerfile.build для cron-loop image
- nginx.conf для static serving
- auth.toml.example + .env.example + README.md с полным install path
- .gitignore исключает реальные
auth.tomlи.env - 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+ smokecurl -u user:pass https://board.kzntsv.site/
Notes
Зависит от board-viewer-html-render — нужен артефакт для деплоя (хотя бы placeholder). Можно стартовать параллельно с DNS-записью (она прогревается).