Production Deployment
Infrastructure
| Component | Details |
|---|---|
| App Server | 77.42.82.4 (Ubuntu 22.04) |
| LXD Server | 65.109.236.163 |
| Frontend | https://mvp.zafarsaidov.uz |
| API | https://mvp-api.zafarsaidov.uz |
| DNS/SSL | Cloudflare (proxy + flexible SSL) |
Quick Deploy (Existing Server)
make deploy
# Equivalent to: git pull → docker-compose build → migrate → smoke test
Or manually:
ssh -i private_key root@77.42.82.4
cd /opt/platform-v2
./scripts/deploy.sh
First-Time Server Setup
1. Install Dependencies
ssh root@77.42.82.4
apt update && apt upgrade -y
# Docker
curl -fsSL https://get.docker.com | sh
apt install -y docker-compose git
# Firewall
ufw allow 22/tcp
ufw allow 80/tcp
ufw allow 443/tcp
ufw enable
2. Clone the Repository
cd /opt
git clone git@gitlab.com:zsaidov1988/educenter-platform.git platform-v2
cd platform-v2
3. Configure Environment
cp backend/.env.example backend/.env
nano backend/.env
Critical values to set:
SECRET_KEY=$(python3 -c "import secrets; print(secrets.token_urlsafe(32))")
ADMIN_PASSWORD=<strong-password>
DATABASE_URL=postgresql+asyncpg://platform:<db-password>@postgres:5432/platform
CORS_ORIGINS=https://mvp.zafarsaidov.uz
LXD_ENDPOINT=https://10.0.0.3:8443
LXD_SSH_JUMP_HOST=65.109.236.163
LESSONS_REPO_URL=git@gitlab.com:zsaidov1988/lessons-content.git
4. Place Secrets
# LXD TLS certificates
mkdir -p backend/.lxd
# Copy client.crt and client.key from LXD server setup
# SSH key for LXD server access and lessons repo
cp private_key backend/private_key
chmod 600 backend/private_key
5. Deploy
docker-compose -f docker-compose.prod.yml up -d --build
docker-compose -f docker-compose.prod.yml exec backend alembic upgrade head
docker-compose -f docker-compose.prod.yml exec backend python -m app.db.init_db
6. Verify
# Check containers
docker-compose -f docker-compose.prod.yml ps
# Health check
curl https://mvp-api.zafarsaidov.uz/health
# Run smoke tests
make smoke-test
Updating the Application
# From your local machine:
make deploy
# Or on the server directly:
cd /opt/platform-v2
git pull
docker-compose -f docker-compose.prod.yml up -d --build
docker-compose -f docker-compose.prod.yml exec backend alembic upgrade head
Monitoring
Logs
make prod-logs # Tail all production logs
make prod-logs-backend # Backend only
# On the server:
docker-compose -f docker-compose.prod.yml logs -f backend
docker-compose -f docker-compose.prod.yml logs -f nginx
Container Status
docker-compose -f docker-compose.prod.yml ps # Docker containers
make lxd-list # LXD containers
Restart Services
docker-compose -f docker-compose.prod.yml restart backend
docker-compose -f docker-compose.prod.yml restart nginx
Troubleshooting
Backend not connecting to LXD
make lxd-check
ls -la backend/.lxd/ # Certificates present?
WebSocket terminal not connecting
- Verify container is running:
make lxd-list - Check token is in WebSocket URL:
/ws/terminal/{id}?token={jwt} - Review backend logs for SSH errors
SSL/HTTPS issues
- Verify DNS records point to
77.42.82.4 - Check Cloudflare SSL/TLS setting is "Flexible" or "Full"
- Ensure Cloudflare proxy is enabled (orange cloud icon)
Container creation failing
ssh -i private_key root@65.109.236.163 "lxc list"
# Check available resources:
df -h && free -h
Security Checklist
- Changed default
ADMIN_PASSWORD - Generated strong
SECRET_KEY - Firewall configured (UFW: 22, 80, 443 only)
- SSH key authentication only (no password auth)
- LXD certificates in place and not committed to git
-
private_keynot committed to git (in.gitignore) - HTTPS enabled via Cloudflare
- Regular
apt update && apt upgradescheduled