Skip to content

Deployment

maule edited this page Aug 16, 2026 · 1 revision

Deployment Guide

Deploy your TGbotPHP bot to production.

Pre-Deployment Checklist

  • Code reviewed for security
  • All secrets in environment variables
  • HTTPS enabled on server
  • Error logging configured
  • Database backups setup (if applicable)
  • Monitoring/alerts setup
  • Webhook IP validation enabled
  • Rate limiting configured
  • .env file NOT committed to git
  • Security headers configured

Hosting Options

Shared Hosting

Most affordable option. Requires HTTPS support.

Recommended providers:

  • Bluehost
  • SiteGround
  • HostGator
  • GoDaddy

Setup:

  1. Upload files via FTP/SFTP
  2. Configure .env file
  3. Point webhook to https://your-domain.com/webhook.php
  4. Test webhook: https://api.telegram.org/botYOUR_TOKEN/getWebhookInfo

VPS (Virtual Private Server)

More control, better performance.

Providers:

  • DigitalOcean
  • Linode
  • Vultr
  • AWS EC2

Ubuntu/Debian Setup:

# SSH into server
ssh root@your-vps-ip

# Update system
apt update && apt upgrade -y

# Install PHP and extensions
apt install -y php php-curl php-json php-cli

# Install Composer
curl -sS https://getcomposer.org/installer | php
mv composer.phar /usr/local/bin/composer

# Create bot directory
mkdir -p /var/www/telegram-bot
cd /var/www/telegram-bot

# Clone or upload files
git clone https://github.com/yourusername/your-bot.git .

# Install dependencies
composer install --no-dev

# Set permissions
chmod 755 webhook.php
mkdir -p logs
chmod 755 logs

# Configure .env
cp .env.example .env
# Edit .env with your settings

Docker

Containerized deployment for consistency.

Dockerfile:

FROM php:8.4-cli

RUN docker-php-ext-install curl

WORKDIR /app

COPY . .

RUN curl -sS https://getcomposer.org/installer | php
RUN php composer.phar install --no-dev

EXPOSE 8080

CMD ["php", "-S", "0.0.0.0:8080"]

docker-compose.yml:

version: '3.8'

services:
  bot:
    build: .
    ports:
      - "8080:8080"
    environment:
      TELEGRAM_BOT_TOKEN: ${TELEGRAM_BOT_TOKEN}
      DEBUG_MODE: "false"
    volumes:
      - ./logs:/app/logs

Deploy:

docker-compose up -d

HTTPS Certificate

Let's Encrypt (Free)

# Install certbot
apt install -y certbot python3-certbot-nginx

# Generate certificate
certbot certonly --standalone -d your-domain.com

# Renew automatically
certbot renew --dry-run

Self-Signed (Testing Only)

openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem -days 365 -nodes

Webhook Setup

Register Webhook

curl -X POST "https://api.telegram.org/bot<TOKEN>/setWebhook" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://your-domain.com/webhook.php",
    "secret_token": "your_secret_token_here"
  }'

Verify Webhook

curl "https://api.telegram.org/bot<TOKEN>/getWebhookInfo"

Expected response:

{
  "ok": true,
  "result": {
    "url": "https://your-domain.com/webhook.php",
    "has_custom_certificate": false,
    "pending_update_count": 0,
    "max_connections": 40
  }
}

Troubleshooting Webhook

Issue: "pending_update_count" is high

  • Check server logs
  • Verify bot is responding
  • Restart bot service

Issue: Connection refused

  • Check firewall rules
  • Verify HTTPS certificate
  • Test endpoint with curl

Database Setup (MySQL)

If your bot uses a database:

# Install MySQL
apt install -y mysql-server

# Create database
mysql -u root -p
CREATE DATABASE telegram_bot;
CREATE USER 'bot'@'localhost' IDENTIFIED BY 'secure_password';
GRANT ALL PRIVILEGES ON telegram_bot.* TO 'bot'@'localhost';
FLUSH PRIVILEGES;
EXIT;

Store credentials in .env:

DB_HOST=localhost
DB_USER=bot
DB_PASS=secure_password
DB_NAME=telegram_bot

Environment Variables

Production .env

# Bot
TELEGRAM_BOT_TOKEN=your_token_here
TELEGRAM_SECRET_TOKEN=your_secret_token_here

# Environment
DEBUG_MODE=false
DEBUG_LOG_FILE=/var/log/telegram-bot.log

# Security
ALLOW_HTTPS_ONLY=true
VALIDATE_WEBHOOK_IP=true

# Database
DB_HOST=localhost
DB_USER=bot_user
DB_PASS=secure_password
DB_NAME=telegram_bot

Load from .env

<?php
$env = parse_ini_file(__DIR__ . '/.env');

define('BOT_TOKEN', $env['TELEGRAM_BOT_TOKEN']);
define('DEBUG_MODE', $env['DEBUG_MODE'] === 'true');

Logging

File Logging

# Create log directory
mkdir -p /var/log/telegram-bot
chmod 755 /var/log/telegram-bot

# Create empty log file
touch /var/log/telegram-bot/bot.log
chmod 644 /var/log/telegram-bot/bot.log

Configure in .env

DEBUG_LOG_FILE=/var/log/telegram-bot/bot.log

Rotate Logs

logrotate configuration:

# /etc/logrotate.d/telegram-bot
/var/log/telegram-bot/bot.log {
    daily
    rotate 7
    compress
    delaycompress
    notifempty
    create 0644 www-data www-data
    sharedscripts
    postrotate
        systemctl restart php-fpm > /dev/null 2>&1 || true
    endscript
}

Monitoring

Webhook Status

<?php
function checkWebhookStatus() {
    $token = getenv('TELEGRAM_BOT_TOKEN');
    
    $ch = curl_init("https://api.telegram.org/bot$token/getWebhookInfo");
    curl_setopt_array($ch, [
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_TIMEOUT => 10,
    ]);
    
    $response = json_decode(curl_exec($ch), true);
    
    return [
        'url' => $response['result']['url'] ?? null,
        'pending' => $response['result']['pending_update_count'] ?? 0,
        'timestamp' => date('Y-m-d H:i:s'),
    ];
}

Health Check Script

#!/bin/bash
# /usr/local/bin/check-bot-health.sh

TOKEN="your_token"
WEBHOOK_URL="https://api.telegram.org/bot$TOKEN/getWebhookInfo"
LOG_FILE="/var/log/telegram-bot/health.log"

STATUS=$(curl -s "$WEBHOOK_URL" | jq '.result.pending_update_count')

echo "[$(date)] Pending updates: $STATUS" >> $LOG_FILE

if [ "$STATUS" -gt 100 ]; then
    # Alert - too many pending updates
    echo "WARNING: High pending update count: $STATUS" | mail -s "Bot Alert" admin@example.com
fi

Run every 5 minutes:

*/5 * * * * /usr/local/bin/check-bot-health.sh

Security Deployment

Firewall Rules

# Allow HTTPS only
sudo ufw allow 443/tcp
sudo ufw allow 80/tcp  # For Let's Encrypt renewal
sudo ufw deny 8080/tcp # Close non-standard ports

File Permissions

# Webhook script
chmod 644 webhook.php

# Bot library
chmod 644 botlib.php

# Log directory
chmod 750 logs/
chown www-data:www-data logs/

# .env file
chmod 600 .env
chown www-data:www-data .env

Nginx Security

server {
    listen 443 ssl http2;
    server_name your-domain.com;
    
    ssl_certificate /etc/letsencrypt/live/your-domain.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/your-domain.com/privkey.pem;
    
    # Security headers
    add_header Strict-Transport-Security "max-age=31536000" always;
    add_header X-Content-Type-Options "nosniff" always;
    add_header X-Frame-Options "DENY" always;
    
    root /var/www/telegram-bot;
    index webhook.php;
    
    location ~ \.php$ {
        include snippets/fastcgi-php.conf;
        fastcgi_pass unix:/var/run/php/php8.4-fpm.sock;
    }
    
    location ~ /\. {
        deny all;
    }
}

server {
    listen 80;
    server_name your-domain.com;
    return 301 https://$server_name$request_uri;
}

Scaling

Multiple Servers

Use a load balancer (like HAProxy) to distribute requests:

Internet -> Load Balancer -> Bot Server 1
                          -> Bot Server 2
                          -> Bot Server 3

Caching

Use Redis for caching:

<?php
$redis = new Redis();
$redis->connect('localhost');

// Cache user preferences
$redis->set("user_$userId", json_encode($prefs), 3600);
$prefs = json_decode($redis->get("user_$userId"));

Backup Strategy

Daily Backups

#!/bin/bash
# /usr/local/bin/backup-bot.sh

DATE=$(date +%Y%m%d)
BACKUP_DIR="/backups/telegram-bot"

mkdir -p $BACKUP_DIR

# Backup files
tar -czf $BACKUP_DIR/bot-files-$DATE.tar.gz /var/www/telegram-bot/

# Backup database
mysqldump -u bot -p$DB_PASS telegram_bot | gzip > $BACKUP_DIR/bot-db-$DATE.sql.gz

# Keep only 30 days
find $BACKUP_DIR -name "*.tar.gz" -mtime +30 -delete
find $BACKUP_DIR -name "*.sql.gz" -mtime +30 -delete

Run daily:

0 2 * * * /usr/local/bin/backup-bot.sh

Performance Tuning

PHP Configuration

; /etc/php/8.4/fpm/pool.d/telegram-bot.conf
[telegram-bot]
pm = ondemand
pm.max_children = 50
pm.process_idle_timeout = 10s
pm.max_requests = 500

Nginx Configuration

client_body_buffer_size 10M;
client_max_body_size 10M;

# Connection optimization
keepalive_timeout 30;
keepalive_requests 100;

# Gzip compression
gzip on;
gzip_types text/plain text/xml application/json;
gzip_min_length 1000;

See also: Security Guide, Troubleshooting