EssayBot Server Deployment
EssayBot Server (Backend) uses GitHub Actions with a self-hosted runner on the A6000 server.
Server Details
| Environment | Path | Branch | Trigger |
|---|---|---|---|
| Production | /opt/Essaybot-server | main | Push to release/prod |
| UAT | /opt/Essaybot-server-UAT | qdrant-migration | Push to qdrant-migration |
Server: A6000 (self-hosted GitHub runner)
Ports
| Environment | Express | Flask | PM2 Namespace |
|---|---|---|---|
| PROD | 8001 | 6000 | prod |
| UAT | 8002 | 6001 | uat |
| Shared Service | Port |
|---|---|
| MongoDB | 27017 |
| Redis | 6379 |
| RabbitMQ | 5672 |
| Qdrant | 6333 |
PM2 Process Names
| Environment | Express | Flask | Worker |
|---|---|---|---|
| PROD | essaybot-express | essaybot-flask | essaybot-worker |
| UAT | essaybot-express-uat | essaybot-flask-uat | essaybot-worker-uat |
Deployment Triggers
Automatic (GitHub Actions)
Push to branch → GitHub Action triggers → Deploy to corresponding environment
| Branch | Deploys To |
|---|---|
release/prod | Production |
qdrant-migration | UAT |
Manual (Workflow Dispatch)
- Go to Actions → Deploy EssayBot Server
- Click Run workflow
- Select environment (
UATorPROD) - Optionally specify a branch
Deployment Steps (What the CI Does)
- Backup current deployment
- Pull latest code from branch
- Create
.envfile from GitHub Secrets - Install Node.js dependencies (
npm ci) - Setup Python venv and install requirements
- Start Docker services (RabbitMQ, Redis)
- Restart PM2 services (Express, Flask, Worker)
- Health check on
/healthendpoints - Notify Teams channel
GitHub Secrets Required
Environment-Specific
| Secret | Description |
|---|---|
MONGO_URI_UAT | MongoDB connection string for UAT |
MONGO_URI_PROD | MongoDB connection string for PROD |
ESSAYBOT_PRODUCTION_URL_UAT | UI URL for UAT (https://uat.essaybot.dashlab.studio) |
ESSAYBOT_PRODUCTION_URL_PROD | UI URL for PROD (https://essaybot.dashlab.studio) |
DASH_PORTAL_PRODUCTION_URL_UAT | DashPortal URL for UAT |
DASH_PORTAL_PRODUCTION_URL_PROD | DashPortal URL for PROD |
MINIO_BUCKET_UAT | MinIO bucket for UAT (essaybot-uat) |
MINIO_BUCKET_PROD | MinIO bucket for PROD (essaybot) |
Shared (Both Environments)
| Secret | Description |
|---|---|
JWT_SECRET | JWT signing secret |
EXTERNAL_JWT_SECRET | DashPortal cross-auth secret |
MINIO_ACCESS_KEY | MinIO access key |
MINIO_SECRET_KEY | MinIO secret key |
MINIO_ENDPOINT | MinIO endpoint URL |
OLLAMA_URL | vLLM completions endpoint |
OLLAMA_MODEL_URL | vLLM base URL |
VISION_MODEL | Vision model name |
EMBEDDING_MODEL | Embedding model name |
AWS_REGION | AWS region for S3 compatibility |
GH_PAT | GitHub Personal Access Token |
TEAMS_WEBHOOK_URL | MS Teams notification webhook |
PM2 Commands
Check Status
# UAT
sudo -u deploy pm2 status --namespace uat
# PROD
sudo -u deploy pm2 status --namespace prod
View Logs
# UAT
sudo -u deploy pm2 logs --namespace uat --lines 100
# PROD
sudo -u deploy pm2 logs --namespace prod --lines 100
Restart Services
# UAT
sudo -u deploy pm2 restart all --namespace uat
# PROD
sudo -u deploy pm2 restart all --namespace prod
Full Restart (Delete + Start)
# UAT
cd /opt/Essaybot-server-UAT
sudo -u deploy pm2 delete all --namespace uat
sudo -u deploy NAMESPACE=uat pm2 start ecosystem.config.js --only essaybot-express-uat --namespace uat
sudo -u deploy NAMESPACE=uat pm2 start ecosystem.config.js --only essaybot-flask-uat --namespace uat
sudo -u deploy NAMESPACE=uat pm2 start ecosystem.config.js --only essaybot-worker-uat --namespace uat
# PROD
cd /opt/Essaybot-server
sudo -u deploy pm2 delete all --namespace prod
sudo -u deploy NAMESPACE=prod pm2 start ecosystem.config.js --env production --only essaybot-express --namespace prod
sudo -u deploy NAMESPACE=prod pm2 start ecosystem.config.js --env production --only essaybot-flask --namespace prod
sudo -u deploy NAMESPACE=prod pm2 start ecosystem.config.js --env production --only essaybot-worker --namespace prod
Docker Services
# Check status
docker ps
# Restart RabbitMQ and Redis
docker compose restart rabbitmq redis
Health Check Endpoints
| Environment | Express | Flask |
|---|---|---|
| UAT | http://localhost:8002/health | http://localhost:6001/health |
| PROD | http://localhost:8001/health | http://localhost:6000/health |
Rollback
On deployment failure, the CI automatically restores from the latest backup in /opt/Essaybot-server[-UAT]/backups/.
Manual Rollback
# List backups
ls -la /opt/Essaybot-server-UAT/backups/
# Restore specific backup
cd /opt/Essaybot-server-UAT
sudo -u deploy tar -xzf backups/backup-20240115-120000.tar.gz -C .
sudo -u deploy pm2 restart all --namespace uat
Backup Retention
- Automatic cleanup: Keeps only 3 most recent backups
- Log cleanup: Removes logs older than 30 days
- Backup location:
<project-dir>/backups/ - Backup format:
backup-YYYYMMDD-HHMMSS.tar.gz
Troubleshooting
| Issue | Check |
|---|---|
| Services not starting | pm2 logs --namespace uat --lines 50 |
| Port already in use | lsof -ti:8002 then kill -9 <PID> |
| MinIO errors | Verify .env has correct MINIO_* values |
| JWT auth failures | Check EXTERNAL_JWT_SECRET length (should be 15 chars) |
| RabbitMQ connection | docker ps — ensure essaybot-rabbitmq is running |