All checks were successful
CI / lint-and-test (push) Successful in 19s
- 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.
4.9 KiB
4.9 KiB
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:
Or after
python main.pypip 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 --buildStop:
Ctrl+Cordocker compose -f docker-compose.dev.yml down. -
Prod (built image; restarts on failure):
docker compose -f docker-compose.prod.yml up -d --buildStop:
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 orchestrator’s 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
/healthendpoint; use/docsor 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 manager’s logging (e.g. systemd, supervisord).
- Docker: Use
docker compose logs -f(with the appropriate compose file) to follow application logs. Adjust log level via Pythonloggingif 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_TOKENthan 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_TOKENis set in.env(or equivalent) on the machine serving/api/dutiesas the one used by the bot instance whose menu button opens the Miniapp.
Miniapp "Open in browser" or direct link — access denied
- Cause: When users open the calendar via “Open in browser” or a direct URL, Telegram may not send
tgWebAppData(initData). The API requires initData (orMINI_APP_SKIP_AUTH/ private IP in dev). - Action: Users should open the calendar via the bot’s 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 validX-Telegram-Init-Dataheader. In production, only private IP clients can be allowed without initData (see_is_private_clientinapi/dependencies.py); behind a reverse proxy,request.client.hostis 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 bot’s 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 user’s username is not in
ALLOWED_USERNAMESorADMIN_USERNAMES, and (if using phone) their phone (set via/set_phone) is not inALLOWED_PHONESorADMIN_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 defaultDATABASE_URL=sqlite:///data/duty_teller.db). In Docker, the entrypoint creates/app/dataand runs migrations there. - Migrations (Alembic): From the repository root:
Config:
alembic -c pyproject.toml upgrade headpyproject.toml→[tool.alembic]; script locationalembic/; metadata and URL fromduty_teller.configandduty_teller.db.models.Base. - Rollback: Use with care; test in a copy of the DB first. Example to go back one revision:
Always backup the database before downgrading.
alembic -c pyproject.toml downgrade -1
For full list of env vars (including DATABASE_URL), see configuration.md. For reverse proxy and Mini App URL details, see the main README.