Skip to main content
This guide covers production deployment options for your Telegram support bot, including systemd service setup, Docker deployment, monitoring, and backup strategies.

Prerequisites

Before deploying to production, ensure you have:
  • A Linux server with Python 3.8+ installed
  • Your bot token from @BotFather
  • A Telegram supergroup with topics enabled
  • Required permissions configured for your bot

Systemd service deployment

Install dependencies

First, set up a virtual environment and install the required packages:
python3 -m venv venv
source venv/bin/activate
pip install -r requirements.txt
Your bot requires these dependencies:
requirements.txt
aiogram==3.13.1
aiosqlite==0.20.0
python-dotenv==1.0.1

Configure environment variables

Create a .env file with your bot configuration:
.env
BOT_TOKEN=123456:ABCDEF_your_token_here
# Supergroup chat id (usually starts with -100...)
OPERATOR_GROUP_ID=-1001234567890
# Path to SQLite DB file
DB_PATH=./support_bot.sqlite3
LOG_LEVEL=INFO
# Store messages history in SQLite (set to 0 to disable)
LOG_MESSAGES=1
The OPERATOR_GROUP_ID must be a supergroup ID (starts with -100). Regular groups and channels are not supported.

Create systemd service

Create a systemd service file to manage your bot as a system service:
/etc/systemd/system/telegram-support-bot.service
[Unit]
Description=Telegram Support Bot
After=network.target

[Service]
Type=simple
User=telegram-bot
WorkingDirectory=/opt/telegram-support-bot
EnvironmentFile=/opt/telegram-support-bot/.env
ExecStart=/opt/telegram-support-bot/venv/bin/python -m support_bot.main
Restart=always
RestartSec=10

# Security hardening
NoNewPrivileges=true
PrivateTmp=true
ProtectSystem=strict
ProtectHome=true
ReadWritePaths=/opt/telegram-support-bot

[Install]
WantedBy=multi-user.target
1

Create service user

Create a dedicated user for running the bot:
sudo useradd -r -s /bin/false telegram-bot
sudo mkdir -p /opt/telegram-support-bot
sudo chown telegram-bot:telegram-bot /opt/telegram-support-bot
2

Copy files

Copy your bot files to the deployment directory:
sudo cp -r support_bot /opt/telegram-support-bot/
sudo cp .env /opt/telegram-support-bot/
sudo cp requirements.txt /opt/telegram-support-bot/
sudo chown -R telegram-bot:telegram-bot /opt/telegram-support-bot
3

Enable and start service

Enable the service to start on boot and start it:
sudo systemctl daemon-reload
sudo systemctl enable telegram-support-bot
sudo systemctl start telegram-support-bot
4

Verify status

Check that the service is running:
sudo systemctl status telegram-support-bot

Docker deployment

For containerized deployment, create a Dockerfile based on the bot’s requirements:
Dockerfile
FROM python:3.11-slim

WORKDIR /app

# Install dependencies
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

# Copy application code
COPY support_bot /app/support_bot

# Create volume mount point for database
VOLUME /app/data

# Run as non-root user
RUN useradd -m -u 1000 botuser && chown -R botuser:botuser /app
USER botuser

CMD ["python", "-m", "support_bot.main"]

Build and run with Docker

1

Build the image

docker build -t telegram-support-bot .
2

Run the container

docker run -d \
  --name support-bot \
  --restart unless-stopped \
  -v $(pwd)/data:/app/data \
  -e BOT_TOKEN="123456:ABCDEF_your_token_here" \
  -e OPERATOR_GROUP_ID="-1001234567890" \
  -e DB_PATH="/app/data/support_bot.sqlite3" \
  -e LOG_LEVEL="INFO" \
  -e LOG_MESSAGES="1" \
  telegram-support-bot

Docker Compose

Alternatively, use Docker Compose for easier management:
docker-compose.yml
version: '3.8'

services:
  support-bot:
    build: .
    container_name: telegram-support-bot
    restart: unless-stopped
    volumes:
      - ./data:/app/data
    env_file:
      - .env
    environment:
      - DB_PATH=/app/data/support_bot.sqlite3
Start with:
docker-compose up -d

Process management

Service management commands

Start

sudo systemctl start telegram-support-bot

Stop

sudo systemctl stop telegram-support-bot

Restart

sudo systemctl restart telegram-support-bot

Status

sudo systemctl status telegram-support-bot

Docker management commands

View logs

docker logs -f support-bot

Restart

docker restart support-bot

Stop

docker stop support-bot

Remove

docker rm -f support-bot

Monitoring and logs

View logs with systemd

The bot logs important events using Python’s logging module:
# View real-time logs
sudo journalctl -u telegram-support-bot -f

# View recent logs
sudo journalctl -u telegram-support-bot -n 100

# View logs from today
sudo journalctl -u telegram-support-bot --since today

Log levels

Configure the log level in your .env file:
support_bot/main.py (lines 23-24)
logging.basicConfig(level=getattr(logging, config.log_level.upper(), logging.INFO))
log = logging.getLogger("support_bot")
Available log levels:
  • DEBUG - Detailed information for diagnosing problems
  • INFO - Confirmation that things are working as expected (default)
  • WARNING - Indication of unexpected events
  • ERROR - Serious problems that prevent functionality

Startup log message

When the bot starts successfully, you’ll see:
support_bot/main.py (lines 50-51)
me = await bot.get_me()
log.info("Started as @%s (id=%s)", me.username, me.id)
Set LOG_MESSAGES=1 in your .env file to store all messages in the SQLite database for auditing and analytics.

Database backup

Your bot uses SQLite with WAL mode enabled for better concurrency:
support_bot/db.py (lines 30-32)
self._conn = await aiosqlite.connect(self._path)
await self._conn.execute("PRAGMA journal_mode=WAL;")
await self._conn.execute("PRAGMA foreign_keys=ON;")

Backup strategies

Create a backup of your database file:
# For systemd deployment
sudo cp /opt/telegram-support-bot/support_bot.sqlite3 \
     /opt/telegram-support-bot/backups/support_bot_$(date +%Y%m%d).sqlite3

# For Docker deployment
docker exec support-bot cp /app/data/support_bot.sqlite3 \
                            /app/data/support_bot_backup.sqlite3
Create a daily backup using cron:
# Add to crontab (crontab -e)
0 2 * * * cp /opt/telegram-support-bot/support_bot.sqlite3 \
             /opt/telegram-support-bot/backups/support_bot_$(date +\%Y\%m\%d).sqlite3

# Clean up old backups (keep last 30 days)
0 3 * * * find /opt/telegram-support-bot/backups -name "*.sqlite3" -mtime +30 -delete
SQLite WAL mode creates additional files. Backup all three:
cp support_bot.sqlite3 backup/
cp support_bot.sqlite3-wal backup/
cp support_bot.sqlite3-shm backup/
Or use SQLite’s built-in backup:
sqlite3 support_bot.sqlite3 ".backup backup/support_bot_$(date +%Y%m%d).sqlite3"
Always test your backups by restoring them to a test environment to ensure they’re valid.

Security considerations

Protect your bot token

1

Use environment variables

Never hardcode your bot token in source code. The bot uses python-dotenv to load configuration:
support_bot/main.py (lines 20-21)
load_dotenv()
config = load_config()
2

Set file permissions

Restrict access to your .env file:
chmod 600 .env
sudo chown telegram-bot:telegram-bot /opt/telegram-support-bot/.env
3

Use secrets management

For production, consider using a secrets management service like:
  • HashiCorp Vault
  • AWS Secrets Manager
  • Azure Key Vault
  • Environment variables from your orchestration platform

Database security

The bot enables foreign key constraints for data integrity:
support_bot/db.py (lines 31-32)
await self._conn.execute("PRAGMA journal_mode=WAL;")
await self._conn.execute("PRAGMA foreign_keys=ON;")
Additional security measures:
  • Set restrictive file permissions: chmod 600 support_bot.sqlite3
  • Regular backups with encryption
  • Monitor database file size for unusual growth
  • Use read-only database replicas for analytics

Network security

HTTPS only

The aiogram library uses HTTPS by default for all Telegram API requests.

Firewall rules

No inbound ports needed. The bot uses long polling to receive updates.

Rate limiting

Telegram enforces rate limits. The bot handles errors gracefully.

Updates

Keep dependencies updated to patch security vulnerabilities.

User privacy

The bot stores user data in compliance with privacy best practices:
support_bot/db.py (lines 62-69)
CREATE TABLE IF NOT EXISTS users (
  user_id      INTEGER PRIMARY KEY,
  username     TEXT,
  first_name   TEXT,
  last_name    TEXT,
  created_at   TEXT NOT NULL,
  updated_at   TEXT NOT NULL
);
Ensure your use of this bot complies with:
  • GDPR (if serving EU users)
  • Your local data protection regulations
  • Telegram’s Terms of Service and Privacy Policy

Health checks

The database includes a health check method:
support_bot/db.py (lines 338-342)
async def healthcheck(self) -> dict[str, Any]:
    cur = await self.conn.execute("SELECT 1;")
    row = await cur.fetchone()
    await cur.close()
    return {"ok": row == (1,)}
You can extend this to create a health check endpoint for monitoring tools.

Troubleshooting deployment

Check the logs for errors:
sudo journalctl -u telegram-support-bot -n 50
Common issues:
  • Invalid bot token
  • Missing environment variables
  • Database file permissions
  • Python version mismatch
The bot uses a transaction lock to prevent conflicts:
support_bot/db.py (lines 48-57)
@asynccontextmanager
async def transaction(self) -> Any:
    async with self._tx_lock:
        await self.conn.execute("BEGIN;")
        try:
            yield
        except BaseException:
            await self.conn.rollback()
            raise
        else:
            await self.conn.commit()
If you still see errors, ensure only one bot instance is running.
Monitor the bot’s memory usage:
# For systemd
systemctl status telegram-support-bot

# For Docker
docker stats support-bot
Consider setting memory limits in your systemd service or Docker container.

Next steps

Customize your bot

Learn how to customize greetings, topic names, and add custom handlers

Troubleshooting

Solutions for common issues and error messages

Build docs developers (and LLMs) love