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.
3.6 KiB
3.6 KiB
Configuration reference
All configuration is read from the environment (e.g. .env via python-dotenv). Source of truth: duty_teller/config.py and Settings.from_env().
| Variable | Type / format | Default | Description |
|---|---|---|---|
| BOT_TOKEN | string | (empty) | Telegram bot token from @BotFather. Required for the bot to run; if unset, the entry point exits with a clear message. The server that serves the Mini App API must use the same token as the bot; otherwise initData validation returns hash_mismatch. |
| DATABASE_URL | string (SQLAlchemy URL) | sqlite:///data/duty_teller.db |
Database connection URL. Example: sqlite:///data/duty_teller.db. |
| MINI_APP_BASE_URL | string (URL, no trailing slash) | (empty) | Base URL of the miniapp (for documentation and CORS). Trailing slash is stripped. Example: https://your-domain.com/app. |
| HTTP_PORT | integer | 8080 |
Port for the HTTP server (FastAPI + static webapp). |
| ALLOWED_USERNAMES | comma-separated list | (empty) | Telegram usernames allowed to open the calendar miniapp (without @; case-insensitive). If both this and ADMIN_USERNAMES are empty, no one can open the calendar. Example: alice,bob. |
| ADMIN_USERNAMES | comma-separated list | (empty) | Telegram usernames with admin role (access to miniapp + /import_duty_schedule and future admin features). Example: admin1,admin2. |
| ALLOWED_PHONES | comma-separated list | (empty) | Phone numbers allowed to access the miniapp (user sets via /set_phone). Comparison uses digits only (spaces, +, parentheses, dashes ignored). Example: +7 999 123-45-67,89001234567. |
| ADMIN_PHONES | comma-separated list | (empty) | Phone numbers with admin role; same format as ALLOWED_PHONES. |
| MINI_APP_SKIP_AUTH | 1, true, or yes |
(unset) | If set, /api/duties is allowed without Telegram initData (dev only; insecure). |
| INIT_DATA_MAX_AGE_SECONDS | integer | 0 |
Reject Telegram initData older than this many seconds. 0 = disabled. Example: 86400 for 24 hours. |
| CORS_ORIGINS | comma-separated list | * |
Allowed origins for CORS. Leave unset or set to * for allow-all. Example: https://your-domain.com. |
| EXTERNAL_CALENDAR_ICS_URL | string (URL) | (empty) | URL of a public ICS calendar (e.g. holidays). If set, those days are highlighted on the duty grid; users can tap "i" on a cell to see the event summary. Empty = no external calendar. |
| DUTY_DISPLAY_TZ | string (timezone name) | Europe/Moscow |
Timezone for the pinned duty message in groups. Example: Europe/Moscow, UTC. |
| DEFAULT_LANGUAGE | en or ru (normalized) |
en |
Default UI language when the user's Telegram language is unknown. Values starting with ru are normalized to ru, otherwise en. |
Quick setup
- Copy
.env.exampleto.env. - Set
BOT_TOKENto the token from BotFather. - For miniapp access, set
ALLOWED_USERNAMESand/orADMIN_USERNAMES(and optionallyALLOWED_PHONES/ADMIN_PHONES).
For Mini App URL and production deployment notes (reverse proxy, initData), see the README Setup and Docker sections.
Production: HTTPS
In production the application must be served over HTTPS (e.g. behind a reverse proxy such as nginx or Caddy with TLS). Without HTTPS, the Telegram Mini App initData and the calendar subscription token are sent in the clear; an attacker on the same network could capture them and gain access to the calendar or impersonate the user. Deploy the HTTP server behind a proxy that terminates TLS and forwards requests to the app.