Files
duty-teller/docs/runbook.md
Nikolay Tatarinov e6bc60b436
Some checks failed
CI / lint-and-test (push) Failing after 23s
chore: update project configuration and documentation
- Added *.egg-info/ to .gitignore to prevent egg metadata from being tracked.
- Updated virtual environment instructions in CONTRIBUTING.md and README.md to use .venv for consistency.
- Revised mkdocs.yml to include a placeholder for the repository URL when publishing.
- Cleaned up pyproject.toml by removing unnecessary pylint configuration.
- Enhanced import-format.md and runbook.md documentation for clarity on user roles and health check endpoints.
2026-02-24 13:30:58 +03:00

4.9 KiB
Raw Permalink Blame History

Runbook (operational guide)

This document covers running the application, checking health, logs, common errors, and database operations.

Starting and stopping

Local

  • Start: From the repository root, with virtualenv activated:
    python main.py
    
    Or after pip install -e .: duty-teller
  • Stop: Ctrl+C

Docker

  • Dev (code mounted; no rebuild needed for code changes):

    docker compose -f docker-compose.dev.yml up --build
    

    Stop: Ctrl+C or docker compose -f docker-compose.dev.yml down.

  • Prod (built image; restarts on failure):

    docker compose -f docker-compose.prod.yml up -d --build
    

    Stop: docker compose -f docker-compose.prod.yml down.

On container start, entrypoint.sh runs Alembic migrations then starts the app as user botuser. Ensure .env (or your orchestrators env) contains BOT_TOKEN and any required variables; see configuration.md.

Health check

  • HTTP: The FastAPI app exposes GET /health, which returns {"status": "ok"} with 200 when the app is up. Use it for readiness checks and in Docker HEALTHCHECK.
  • Alternatively, open the interactive API docs at GET /docs (e.g. http://localhost:8080/docs) or call a lightweight API endpoint with valid auth.

Logs

  • Local: Output goes to stdout/stderr; redirect or use your process managers logging (e.g. systemd, supervisord).
  • Docker: Use docker compose logs -f (with the appropriate compose file) to follow application logs. Adjust log level via Python logging if needed (e.g. environment or code).

Common errors and what to check

"hash_mismatch" (403 from /api/duties or Miniapp)

  • Cause: The server that serves the Mini App (e.g. production host) uses a different BOT_TOKEN than the bot from which users open the Mini App (e.g. test vs production bot). Telegram signs initData with the bot token; if tokens differ, validation fails.
  • Check: Ensure the same BOT_TOKEN is set in .env (or equivalent) on the machine serving /api/duties as the one used by the bot instance whose menu button opens the Miniapp.
  • Cause: When users open the calendar via “Open in browser” or a direct URL, Telegram may not send tgWebAppData (initData). The API requires initData (or MINI_APP_SKIP_AUTH in dev).
  • Action: Users should open the calendar via the bots menu button (e.g. ⋮ → "Calendar") or a Web App inline button so Telegram sends user data.

403 "Open from Telegram" / no initData

  • Cause: Request to /api/duties or /api/calendar-events without valid X-Telegram-Init-Data header. The API returns 403 without initData; the only bypass is MINI_APP_SKIP_AUTH=1 (dev only, insecure).
  • Check: Ensure the Mini App is opened from Telegram (menu or inline button). For local dev without Telegram, use MINI_APP_SKIP_AUTH=1 in .env.

Mini App URL — redirect and broken auth

  • Cause: If the Mini App URL is configured without a trailing slash (e.g. https://your-domain.com/app) and the server redirects /app/app/, the browser can drop the fragment Telegram sends, breaking authorization.
  • Action: Configure the bots menu button / Web App URL with a trailing slash, e.g. https://your-domain.com/app/. See README “Mini App URL”.

User not in allowlist (403)

  • Cause: Miniapp access is determined by roles in the database (see can_access_miniapp_for_telegram_user in the repository). If the user has no role in the DB, the app falls back to ADMIN_USERNAMES and ADMIN_PHONES. A 403 means the user has neither a role granting access nor a match in the admin allowlist.
  • Check: Assign a role with /set_role @username user or admin (admin-only command), or add the user to ADMIN_USERNAMES / their phone to ADMIN_PHONES in configuration.md. Ensure at least one admin exists via env so they can use /set_role.

Database and migrations

  • Default DB path (SQLite): data/duty_teller.db (relative to working directory when using default DATABASE_URL=sqlite:///data/duty_teller.db). In Docker, the entrypoint creates /app/data and runs migrations there.
  • Migrations (Alembic): From the repository root:
    alembic -c pyproject.toml upgrade head
    
    Config: pyproject.toml[tool.alembic]; script location alembic/; metadata and URL from duty_teller.config and duty_teller.db.models.Base.
  • Rollback: Use with care; test in a copy of the DB first. Example to go back one revision:
    alembic -c pyproject.toml downgrade -1
    
    Always backup the database before downgrading.

For full list of env vars (including DATABASE_URL), see configuration.md. For reverse proxy and Mini App URL details, see the main README.