Production-oriented Django + Aiogram Telegram bot template with Docker, Celery, PostgreSQL, Redis, and Nginx.
- Telegram bot with two modes:
Pollingfor local development andWebhookfor production - Django web app and admin panel
- Background jobs with Celery + Celery Beat
- PostgreSQL for data storage
- Redis for Celery broker/result backend and bot FSM storage
- Production Nginx reverse proxy with security headers, gzip, and websocket support
- CI checks (lint, migrations, Django checks, tests)
web: Django applicationbot: Aiogram bot runner (python manage.py run_bot)celery_worker: background task workercelery_beat: scheduler for periodic tasksdb: PostgreSQLredis: Redisnginx(production only): reverse proxy in front ofweb
Docker Compose project name is fixed to djangogram in both development and production.
- Docker
- Docker Compose v2
- Git
- Telegram bot token from BotFather
- Clone the repository:
git clone git@github.com:ummataliyev/djangogram.git
cd djangogram- Create env files:
cp docker/development/.env-example docker/development/.env
cp docker/production/.env-example docker/production/.env- Edit
docker/development/.env:
- Set
BOT_TOKEN - Set a strong
SECRET_KEY - Keep
IS_POLLING=Truefor local development
Important:
- If any value contains
$, escape it as$$in.envfiles. - Example:
abc$123must beabc$$123
- Start the development stack:
make dev-up- Check service status/logs:
make dev-status
make dev-logs- Show all commands:
make help- Development:
make dev-up
make dev-down
make dev-restart
make dev-migrate
make dev-superuser- Production:
make prod-build
make prod-up
make prod-down
make prod-logs- On bot container startup, the project sends:
Hi, Bot is Running! - This message is sent only to users already saved in the
userstable. - If no users exist yet, no startup messages are sent.
Set these in docker/production/.env:
DEBUG=FalseALLOWED_HOSTS=your-domain.comCSRF_TRUSTED_ORIGINS=https://your-domain.comWEBHOOK_BASE_URL=https://your-domain.comTELEGRAM_WEBHOOK_SECRET=<long-random-secret>IS_POLLING=False
Then start:
make prod-upIf you want webhook mode locally:
- Set
IS_POLLING=False - Set
USE_NGROK=True - Provide valid public HTTPS URL settings for Telegram webhook delivery
Run inside Docker (recommended):
docker compose -f docker/development/docker-compose.yml run --rm web python manage.py testRun local checks:
python manage.py makemigrations --check --dry-run
python manage.py check
python manage.py test-
WARN[0000] The "x" variable is not set: you likely have unescaped$in.env. Replace$with$$. -
Webhook tests return
301: this happens whenDEBUG=Falseand requests are HTTP. Use HTTPS requests in tests (secure=True), which is already applied in this repository. -
Bot started but no startup message received: startup message is only sent to existing saved users. Send
/startto the bot first to create your user record.