Files
duty-teller/docs/runbook.md
Nikolay Tatarinov 9486f7004d
All checks were successful
CI / lint-and-test (push) Successful in 19s
docs: update README and configuration documentation for clarity
- Revised the README to improve clarity in instructions for accessing the calendar miniapp, including changes to the phrasing for consistency.
- Updated the configuration documentation to enhance the description of the `EXTERNAL_CALENDAR_ICS_URL` setting, ensuring users understand its purpose and usage.
- Improved the import format documentation by translating terms to English for better accessibility to a wider audience.
- Enhanced the runbook with clearer instructions regarding access issues when using direct links, emphasizing the importance of using the bot's menu button.
2026-02-20 16:26:47 +03:00

4.9 KiB
Raw 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 serves the API and static webapp. A simple way to verify it is up is to open the interactive API docs: GET /docs (e.g. http://localhost:8080/docs). If that page loads, the server is running.
  • There is no dedicated /health endpoint; use /docs or a lightweight API call (e.g. GET /api/duties?from=...&to=... with valid auth) as needed.

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 / private IP 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 calendar) without valid X-Telegram-Init-Data header. In production, only private IP clients can be allowed without initData (see _is_private_client in api/dependencies.py); behind a reverse proxy, request.client.host is often the proxy (e.g. 127.0.0.1), so the “private IP” bypass may not apply to the real user.
  • Check: Ensure the Mini App is opened from Telegram (menu or inline button). If behind a reverse proxy, see README “Production behind a reverse proxy” (forward real client IP or rely on initData).

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: Telegram users username is not in ALLOWED_USERNAMES or ADMIN_USERNAMES, and (if using phone) their phone (set via /set_phone) is not in ALLOWED_PHONES or ADMIN_PHONES.
  • Check: configuration.md for ALLOWED_USERNAMES, ADMIN_USERNAMES, ALLOWED_PHONES, ADMIN_PHONES. Add the user or ask them to set phone and add it to the allowlist.

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.