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

4.4 KiB
Raw Blame History

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

  • 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 + smoke curl -u user:pass https://board.kzntsv.site/

Notes

Зависит от board-viewer-html-render — нужен артефакт для деплоя (хотя бы placeholder). Можно стартовать параллельно с DNS-записью (она прогревается).