This guide explains how to deploy the Telegram bot application from development to production, with special focus on using Telegram as the GUI/interface.
Unlike traditional web applications with HTML/CSS interfaces, this application uses Telegram as the entire user interface. Hereβs how it works:
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β USER'S TELEGRAM APP β
β (This is your GUI - iOS/Android/Web/Desktop) β
β β
β ββββββββββββββββββββββββββββββββββββββββββββββββ β
β β /start β β
β β π Welcome! Choose an action: β β
β β ββββββββββββββββ¬βββββββββββββββ β β
β β β π³ Link Acc β π° Balance β β β
β β ββββββββββββββββ΄βββββββββββββββ β β
β β ββββββββββββββββ¬βββββββββββββββ β β
β β β π Trans β β Help β β β
β β ββββββββββββββββ΄βββββββββββββββ β β
β ββββββββββββββββββββββββββββββββββββββββββββββββ β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
βοΈ
(Telegram Bot API)
βοΈ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β YOUR DEPLOYED APPLICATION β
β β
β ββββββββββββββββββ βββββββββββββββββββ β
β β Telegram Bot β ββββββ β Express API β β
β β (Telegraf) β β (REST) β β
β ββββββββββββββββββ βββββββββββββββββββ β
β βοΈ β
β βββββββββββββββββββ β
β β PostgreSQL β β
β β (Data Store) β β
β βββββββββββββββββββ β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
βοΈ
(Plaid API)
βοΈ
βββββββββββββββββββ
β Bank APIs β
βββββββββββββββββββ
This is the equivalent of βbuilding your frontendβ - but Telegram does it for you!
@BotFather/newbot123456789:ABCdefGHIjklMNOpqrsTUVwxyz
TELEGRAM_BOT_TOKEN/setdescription - Set bot description
/setabouttext - Set about text
/setuserpic - Set bot profile picture
/setcommands - Set command list
Example commands setup:
start - Initialize the bot and show main menu
link - Connect your bank account
balance - View account balances
transactions - View recent transactions
help - Show help information
Before deploying, search for your bot in Telegram and send /start. It wonβt respond yet (we havenβt deployed the code), but you should be able to find it.
You have 3 main options:
Best for: Production use, 24/7 availability, scalability
Popular Platforms:
Best for: Full control, cost-effective for long-term
Providers:
Best for: Testing, development, private use
Requirements:
# macOS
brew install heroku/brew/heroku
# Ubuntu/Debian
curl https://cli-assets.heroku.com/install.sh | sh
# Windows
# Download from https://devcenter.heroku.com/articles/heroku-cli
heroku login
heroku create my-telegram-plaid-bot
heroku addons:create heroku-postgresql:mini
This automatically sets DATABASE_URL environment variable.
# Telegram Bot Token (from BotFather)
heroku config:set TELEGRAM_BOT_TOKEN=123456789:ABCdefGHIjklMNOpqrsTUVwxyz
# Plaid Credentials (from https://dashboard.plaid.com)
heroku config:set PLAID_CLIENT_ID=your_client_id
heroku config:set PLAID_SECRET=your_secret
heroku config:set PLAID_ENV=sandbox # or 'production'
# Server Configuration
heroku config:set PORT=3000
heroku config:set API_BASE_URL=https://my-telegram-plaid-bot.herokuapp.com
# Security - Generate random 32-character key
heroku config:set ENCRYPTION_KEY=$(openssl rand -hex 16)
heroku config:set JWT_SECRET=$(openssl rand -hex 32)
# Logging
heroku config:set LOG_LEVEL=info
git push heroku main
heroku run npm run init-db
heroku logs --tail
You should see:
Telegram bot started successfully
Server running on port 3000
Database connection established
/startssh root@your_server_ip
# Update system
apt update && apt upgrade -y
# Install Node.js 18
curl -fsSL https://deb.nodesource.com/setup_18.x | bash -
apt install -y nodejs
# Install PostgreSQL
apt install -y postgresql postgresql-contrib
# Install PM2 (process manager)
npm install -g pm2
# Install Docker (optional, for Docker deployment)
curl -fsSL https://get.docker.com -o get-docker.sh
sh get-docker.sh
# Switch to postgres user
sudo -u postgres psql
# Create database and user
CREATE DATABASE telegram_plaid;
CREATE USER botuser WITH PASSWORD 'secure_password_here';
GRANT ALL PRIVILEGES ON DATABASE telegram_plaid TO botuser;
\q
# Create app directory
mkdir -p /var/www
cd /var/www
# Clone your repository
git clone https://github.com/yourusername/telegram-plaid-bot.git
cd telegram-plaid-bot
# Install dependencies
npm install --production
# Create .env file
cat > .env << 'EOF'
TELEGRAM_BOT_TOKEN=your_token_here
PLAID_CLIENT_ID=your_client_id
PLAID_SECRET=your_secret
PLAID_ENV=sandbox
DATABASE_URL=postgresql://botuser:secure_password_here@localhost:5432/telegram_plaid
PORT=3000
API_BASE_URL=http://your_server_ip:3000
ENCRYPTION_KEY=your_32_character_key_here_abcd
JWT_SECRET=your_jwt_secret_here
LOG_LEVEL=info
EOF
# Initialize database
npm run init-db
# Start application
pm2 start src/index.js --name telegram-plaid-bot
# Save PM2 configuration
pm2 save
# Setup auto-start on system reboot
pm2 startup
# Follow the command it outputs
# View logs
pm2 logs telegram-plaid-bot
# Monitor
pm2 monit
# Allow SSH
ufw allow ssh
# Allow HTTP/HTTPS (for webhooks)
ufw allow 80
ufw allow 443
# Allow your app port
ufw allow 3000
# Enable firewall
ufw enable
# Install Nginx
apt install -y nginx
# Create Nginx configuration
cat > /etc/nginx/sites-available/telegram-bot << 'EOF'
server {
listen 80;
server_name your_domain.com;
location / {
proxy_pass http://localhost:3000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
}
}
EOF
# Enable site
ln -s /etc/nginx/sites-available/telegram-bot /etc/nginx/sites-enabled/
nginx -t
systemctl restart nginx
# Install SSL with Let's Encrypt
apt install -y certbot python3-certbot-nginx
certbot --nginx -d your_domain.com
# Clone repository
git clone https://github.com/yourusername/telegram-plaid-bot.git
cd telegram-plaid-bot
# Create .env file
cp .env.example .env
# Edit .env with your credentials
nano .env
# Start everything
docker-compose up -d
# View logs
docker-compose logs -f
# Initialize database (if not auto-initialized)
docker-compose exec app npm run init-db
Thatβs it! Your bot is running.
# Stop
docker-compose down
# Restart
docker-compose restart
# View status
docker-compose ps
# Access app shell
docker-compose exec app sh
# View database
docker-compose exec db psql -U postgres telegram_plaid
# PM2
pm2 status
# Docker
docker-compose ps
# Heroku
heroku ps
# PM2
pm2 logs telegram-plaid-bot
# Docker
docker-compose logs -f app
# Heroku
heroku logs --tail
# Direct (if running with npm start)
tail -f combined.log
tail -f error.log
# PM2
pm2 restart telegram-plaid-bot
# Docker
docker-compose restart app
# Heroku
heroku restart
# Pull latest code
git pull origin main
# PM2
npm install --production
pm2 restart telegram-plaid-bot
# Docker
docker-compose down
docker-compose build
docker-compose up -d
# Heroku
git push heroku main
Open Telegram and test each command:
/start - Should show welcome message with buttons/help - Should show help information/link - Should generate link token/balance - Should say βno accounts connectedβ/transactions - Should say βno transactions foundβ# Health check
curl https://your-app-url.com/health
# Create link token (replace telegram_id)
curl -X POST https://your-app-url.com/api/plaid/create-link-token \
-H "Content-Type: application/json" \
-d '{"telegram_id": 123456789}'
# Get accounts
curl https://your-app-url.com/api/plaid/accounts/123456789
/link to your botuser_goodpass_good/balance and /transactionsThe bot uses inline keyboards for better UX. Edit src/bot/commands/start.js:
const { Markup } = require('telegraf');
await ctx.reply(
'Choose an action:',
Markup.keyboard([
['π³ Link Account', 'π° Balance'],
['π Transactions', 'β Help']
]).resize()
);
For action buttons within messages:
await ctx.reply(
'Select time period:',
Markup.inlineKeyboard([
[Markup.button.callback('Last 7 days', 'trans_7d')],
[Markup.button.callback('Last 30 days', 'trans_30d')],
[Markup.button.callback('Last 90 days', 'trans_90d')]
])
);
Use Markdown or HTML:
// Markdown
await ctx.replyWithMarkdown('*Bold* _italic_ `code`');
// HTML
await ctx.replyWithHTML('<b>Bold</b> <i>italic</i> <code>code</code>');
Before going live:
PLAID_ENV=production (after Plaid approval)ENCRYPTION_KEY (32 chars)JWT_SECRET# Check if app is running
pm2 status # or docker-compose ps
# Check logs for errors
pm2 logs # or docker-compose logs
# Check bot token
echo $TELEGRAM_BOT_TOKEN
# Restart
pm2 restart telegram-plaid-bot
# Check PostgreSQL is running
systemctl status postgresql # VPS
docker-compose ps db # Docker
# Test connection
psql $DATABASE_URL
# Check credentials in .env
# Verify credentials
echo $PLAID_CLIENT_ID
echo $PLAID_SECRET
# Check environment
echo $PLAID_ENV # Should be 'sandbox' or 'production'
# Test Plaid connectivity
curl https://sandbox.plaid.com/link/token/create
pm2 start src/index.js -i max
Load Balancer: Use Nginx for multiple app instances
Remember: Telegram IS your GUI. Users interact with your app entirely through their Telegram client. No web frontend needed! π