This guide provides comprehensive instructions for deploying the Telegram Audio Downloader in production environments with enterprise-level reliability, scalability, and monitoring.
Production Environment:
CPU: 4 cores
RAM: 8GB
Storage: 500GB SSD
Network: 100 Mbps
OS: Ubuntu 20.04+ / RHEL 8+ / Windows Server 2019+
High-Load Environment:
CPU: 8 cores
RAM: 16GB
Storage: 2TB NVMe SSD
Network: 1 Gbps
Load Balancer: Required
# System Dependencies
python3.11+
postgresql13+ / mysql8+ (for production database)
redis6+ (for caching and queuing)
nginx (reverse proxy)
supervisor / systemd (process management)
For security in production environments, ensure debug mode is disabled:
# In your Flask application:
app.run(debug=False) # Always set to False in production
# Or use environment variables:
import os
app.run(debug=os.environ.get('FLASK_DEBUG', 'False').lower() == 'true')
# Recommended: Set FLASK_ENV explicitly
# In your .env file:
FLASK_ENV=production
FLASK_DEBUG=False
Add security headers to your Flask application:
from flask_talisman import Talisman
app = Flask(__name__)
Talisman(app, force_https=True)
# Multi-stage production build
FROM python:3.11-slim as builder
WORKDIR /app
RUN apt-get update && apt-get install -y \
build-essential \
git \
&& rm -rf /var/lib/apt/lists/*
COPY requirements.txt .
RUN pip install --no-cache-dir --user -r requirements.txt
# Production stage
FROM python:3.11-slim
# Create non-root user
RUN useradd --create-home --shell /bin/bash appuser
# Install runtime dependencies only
RUN apt-get update && apt-get install -y \
curl \
&& rm -rf /var/lib/apt/lists/*
WORKDIR /app
# Copy Python dependencies from builder
COPY --from=builder /root/.local /home/appuser/.local
ENV PATH=/home/appuser/.local/bin:$PATH
# Copy application
COPY --chown=appuser:appuser . .
# Switch to non-root user
USER appuser
# Health check
HEALTHCHECK --interval=30s --timeout=30s --start-period=5s --retries=3 \
CMD curl -f http://localhost:8080/health || exit 1
EXPOSE 8080
CMD ["python", "-m", "telegram_audio_downloader", "server"]
# docker-compose.prod.yml
version: '3.8'
services:
app:
build:
context: .
dockerfile: Dockerfile.prod
restart: unless-stopped
environment:
- DATABASE_URL=postgresql://user:pass@postgres:5432/telegram_audio
- REDIS_URL=redis://redis:6379/0
- LOG_LEVEL=INFO
- WORKERS=4
volumes:
- app_data:/app/data
- app_logs:/app/logs
depends_on:
- postgres
- redis
networks:
- app_network
nginx:
image: nginx:alpine
restart: unless-stopped
ports:
- "80:80"
- "443:443"
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf:ro
- ./ssl:/etc/nginx/ssl:ro
depends_on:
- app
networks:
- app_network
postgres:
image: postgres:13
restart: unless-stopped
environment:
- POSTGRES_DB=telegram_audio
- POSTGRES_USER=telegram_user
- POSTGRES_PASSWORD_FILE=/run/secrets/postgres_password
volumes:
- postgres_data:/var/lib/postgresql/data
- ./postgres_init.sql:/docker-entrypoint-initdb.d/init.sql:ro
secrets:
- postgres_password
networks:
- app_network
redis:
image: redis:6-alpine
restart: unless-stopped
volumes:
- redis_data:/data
networks:
- app_network
prometheus:
image: prom/prometheus:latest
restart: unless-stopped
volumes:
- ./prometheus.yml:/etc/prometheus/prometheus.yml:ro
- prometheus_data:/prometheus
ports:
- "9090:9090"
networks:
- app_network
grafana:
image: grafana/grafana:latest
restart: unless-stopped
environment:
- GF_SECURITY_ADMIN_PASSWORD_FILE=/run/secrets/grafana_password
volumes:
- grafana_data:/var/lib/grafana
- ./grafana/dashboards:/etc/grafana/provisioning/dashboards:ro
ports:
- "3000:3000"
secrets:
- grafana_password
networks:
- app_network
volumes:
app_data:
app_logs:
postgres_data:
redis_data:
prometheus_data:
grafana_data:
networks:
app_network:
driver: bridge
secrets:
postgres_password:
file: ./secrets/postgres_password.txt
grafana_password:
file: ./secrets/grafana_password.txt
# k8s/namespace.yaml
apiVersion: v1
kind: Namespace
metadata:
name: telegram-audio
labels:
name: telegram-audio
---
# k8s/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: app-config
namespace: telegram-audio
data:
DATABASE_URL: "postgresql://user:password@postgres-service:5432/telegram_audio"
REDIS_URL: "redis://redis-service:6379/0"
LOG_LEVEL: "INFO"
WORKERS: "4"
# k8s/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: telegram-audio-app
namespace: telegram-audio
spec:
replicas: 3
selector:
matchLabels:
app: telegram-audio
template:
metadata:
labels:
app: telegram-audio
spec:
containers:
- name: app
image: telegram-audio-downloader:latest
ports:
- containerPort: 8080
envFrom:
- configMapRef:
name: app-config
resources:
requests:
memory: "512Mi"
cpu: "500m"
limits:
memory: "1Gi"
cpu: "1000m"
livenessProbe:
httpGet:
path: /health
port: 8080
initialDelaySeconds: 30
periodSeconds: 10
readinessProbe:
httpGet:
path: /ready
port: 8080
initialDelaySeconds: 5
periodSeconds: 5
---
# k8s/service.yaml
apiVersion: v1
kind: Service
metadata:
name: telegram-audio-service
namespace: telegram-audio
spec:
selector:
app: telegram-audio
ports:
- port: 80
targetPort: 8080
type: LoadBalancer
# k8s/hpa.yaml
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: telegram-audio-hpa
namespace: telegram-audio
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: telegram-audio-app
minReplicas: 3
maxReplicas: 10
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 70
- type: Resource
resource:
name: memory
target:
type: Utilization
averageUtilization: 80
# Production Environment Variables
export DATABASE_URL="postgresql://user:pass@localhost:5432/telegram_audio"
export REDIS_URL="redis://localhost:6379/0"
export LOG_LEVEL="INFO"
export WORKERS="4"
export SECRET_KEY="your-secret-key-here"
export TELEGRAM_API_ID="your-api-id"
export TELEGRAM_API_HASH="your-api-hash"
export DOWNLOAD_DIR="/app/downloads"
export MAX_CONCURRENT_DOWNLOADS="10"
export RATE_LIMIT_DELAY="1.0"
export MONITORING_ENABLED="true"
export METRICS_PORT="9100"
# config/production.yml
app:
name: "Telegram Audio Downloader"
version: "1.0.0"
debug: false
workers: 4
database:
url: "${DATABASE_URL}"
pool_size: 20
max_overflow: 30
pool_timeout: 30
pool_recycle: 3600
redis:
url: "${REDIS_URL}"
max_connections: 50
telegram:
api_id: "${TELEGRAM_API_ID}"
api_hash: "${TELEGRAM_API_HASH}"
session_name: "production_session"
downloads:
directory: "${DOWNLOAD_DIR}"
max_concurrent: 10
rate_limit_delay: 1.0
chunk_size: 1048576 # 1MB
timeout: 300
monitoring:
enabled: true
port: 9100
health_check_interval: 30
metrics_retention: "7d"
logging:
level: "${LOG_LEVEL}"
format: "json"
file: "/app/logs/app.log"
max_size: "100MB"
backup_count: 5
# prometheus.yml
global:
scrape_interval: 15s
evaluation_interval: 15s
rule_files:
- "rules/*.yml"
scrape_configs:
- job_name: 'telegram-audio-app'
static_configs:
- targets: ['localhost:9100']
scrape_interval: 10s
metrics_path: '/metrics'
- job_name: 'postgres'
static_configs:
- targets: ['postgres-exporter:9187']
- job_name: 'redis'
static_configs:
- targets: ['redis-exporter:9121']
- job_name: 'node'
static_configs:
- targets: ['node-exporter:9100']
{
"dashboard": {
"title": "Telegram Audio Downloader Production Dashboard",
"panels": [
{
"title": "Active Downloads",
"type": "stat",
"targets": [
{
"expr": "telegram_audio_active_downloads",
"legendFormat": "Active Downloads"
}
]
},
{
"title": "Download Rate",
"type": "graph",
"targets": [
{
"expr": "rate(telegram_audio_downloads_total[5m])",
"legendFormat": "Downloads/sec"
}
]
},
{
"title": "Error Rate",
"type": "graph",
"targets": [
{
"expr": "rate(telegram_audio_errors_total[5m])",
"legendFormat": "Errors/sec"
}
]
}
]
}
}
# rules/alerts.yml
groups:
- name: telegram-audio-alerts
rules:
- alert: HighErrorRate
expr: rate(telegram_audio_errors_total[5m]) > 0.1
for: 2m
labels:
severity: warning
annotations:
summary: "High error rate detected"
description: "Error rate is errors/sec"
- alert: HighMemoryUsage
expr: (process_resident_memory_bytes / 1024 / 1024) > 1000
for: 5m
labels:
severity: critical
annotations:
summary: "High memory usage"
description: "Memory usage is MB"
- alert: ServiceDown
expr: up{job="telegram-audio-app"} == 0
for: 1m
labels:
severity: critical
annotations:
summary: "Service is down"
description: "Telegram Audio Downloader service is not responding"
# Security Configuration
export SECURE_HEADERS="true"
export RATE_LIMITING="true"
export API_KEY_REQUIRED="true"
export HTTPS_ONLY="true"
export SESSION_TIMEOUT="3600"
# nginx.conf - Security Headers
server {
listen 443 ssl http2;
server_name your-domain.com;
ssl_certificate /etc/nginx/ssl/cert.pem;
ssl_certificate_key /etc/nginx/ssl/key.pem;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-RSA-AES256-GCM-SHA512:DHE-RSA-AES256-GCM-SHA512;
# Security Headers
add_header X-Frame-Options DENY;
add_header X-Content-Type-Options nosniff;
add_header X-XSS-Protection "1; mode=block";
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains";
add_header Content-Security-Policy "default-src 'self'";
# Rate Limiting
limit_req_zone $binary_remote_addr zone=api:10m rate=10r/s;
limit_req zone=api burst=20 nodelay;
location / {
proxy_pass http://app:8080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
-- PostgreSQL Performance Tuning
ALTER SYSTEM SET shared_buffers = '2GB';
ALTER SYSTEM SET effective_cache_size = '6GB';
ALTER SYSTEM SET maintenance_work_mem = '512MB';
ALTER SYSTEM SET checkpoint_completion_target = 0.9;
ALTER SYSTEM SET wal_buffers = '16MB';
ALTER SYSTEM SET default_statistics_target = 100;
ALTER SYSTEM SET random_page_cost = 1.1;
SELECT pg_reload_conf();
-- Indexes for performance
CREATE INDEX CONCURRENTLY idx_downloads_status ON downloads(status);
CREATE INDEX CONCURRENTLY idx_downloads_created_at ON downloads(created_at);
CREATE INDEX CONCURRENTLY idx_downloads_file_id ON downloads(file_id);
# redis.conf - Production Settings
maxmemory 2gb
maxmemory-policy allkeys-lru
save 900 1
save 300 10
save 60 10000
tcp-keepalive 300
timeout 0
tcp-backlog 511
databases 1
# Performance Settings
WORKERS = 4
MAX_CONCURRENT_DOWNLOADS = 10
CHUNK_SIZE = 1024 * 1024 # 1MB
CONNECTION_POOL_SIZE = 20
REDIS_CONNECTION_POOL_SIZE = 50
RATE_LIMIT_DELAY = 1.0
QUEUE_MAX_SIZE = 1000
#!/bin/bash
# Blue-Green Deployment Script
CURRENT_ENV=$(kubectl get service telegram-audio-service -o jsonpath='{.spec.selector.version}')
NEW_ENV=$([ "$CURRENT_ENV" = "blue" ] && echo "green" || echo "blue")
echo "Current environment: $CURRENT_ENV"
echo "Deploying to: $NEW_ENV"
# Deploy new version
kubectl set image deployment/telegram-audio-app-$NEW_ENV app=telegram-audio:$NEW_VERSION
# Wait for rollout
kubectl rollout status deployment/telegram-audio-app-$NEW_ENV
# Health check
kubectl exec deployment/telegram-audio-app-$NEW_ENV -- curl -f http://localhost:8080/health
# Switch traffic
kubectl patch service telegram-audio-service -p '{"spec":{"selector":{"version":"'$NEW_ENV'"}}}'
echo "Deployment complete. Traffic switched to $NEW_ENV"
# Rolling Update Strategy
spec:
strategy:
type: RollingUpdate
rollingUpdate:
maxUnavailable: 1
maxSurge: 1
progressDeadlineSeconds: 600
#!/bin/bash
# Database Backup Script
BACKUP_DIR="/backups/postgres"
DATE=$(date +%Y%m%d_%H%M%S)
# Create backup
pg_dump -h postgres -U telegram_user telegram_audio > $BACKUP_DIR/backup_$DATE.sql
# Compress backup
gzip $BACKUP_DIR/backup_$DATE.sql
# Clean old backups (keep 30 days)
find $BACKUP_DIR -name "*.sql.gz" -mtime +30 -delete
echo "Backup completed: backup_$DATE.sql.gz"
#!/bin/bash
# Application Data Backup
BACKUP_DIR="/backups/app_data"
DATE=$(date +%Y%m%d_%H%M%S)
# Backup downloads directory
tar -czf $BACKUP_DIR/downloads_$DATE.tar.gz /app/downloads
# Backup configuration
tar -czf $BACKUP_DIR/config_$DATE.tar.gz /app/config
# Backup logs
tar -czf $BACKUP_DIR/logs_$DATE.tar.gz /app/logs
echo "Application data backup completed"
# Health Check Implementation
@app.route('/health')
async def health_check():
checks = {
'database': await check_database(),
'redis': await check_redis(),
'disk_space': check_disk_space(),
'memory': check_memory_usage()
}
all_healthy = all(checks.values())
status_code = 200 if all_healthy else 503
return Response(
json.dumps({
'status': 'healthy' if all_healthy else 'unhealthy',
'checks': checks,
'timestamp': datetime.utcnow().isoformat()
}),
status=status_code,
mimetype='application/json'
)
@app.route('/ready')
async def readiness_check():
# Check if application can serve traffic
ready = (
await check_database_connection() and
await check_telegram_api_connection() and
check_required_directories()
)
return Response(
json.dumps({'ready': ready}),
status=200 if ready else 503,
mimetype='application/json'
)
# Incident Response Runbook
## High Memory Usage
1. Check current memory usage: `kubectl top pods`
2. Check for memory leaks in logs
3. Scale horizontally: `kubectl scale deployment telegram-audio-app --replicas=5`
4. If critical, restart pods: `kubectl rollout restart deployment/telegram-audio-app`
## Database Connection Issues
1. Check database status: `kubectl exec postgres-pod -- pg_isready`
2. Check connection pool: Monitor active connections
3. Restart database if needed: `kubectl rollout restart deployment/postgres`
## High Error Rate
1. Check application logs: `kubectl logs -l app=telegram-audio`
2. Check Telegram API status
3. Verify network connectivity
4. Scale up if needed: `kubectl scale deployment telegram-audio-app --replicas=10`
Production Benchmarks:
Download Rate: 50-100 files/minute
Concurrent Downloads: 10-20
Memory Usage: < 500MB per worker
CPU Usage: < 70% average
Response Time: < 200ms (API endpoints)
Uptime: 99.9%
Error Rate: < 0.1%
For production support, monitor:
/app/logs/
Emergency contacts and escalation procedures should be documented separately.