- Complete deployment workflow documentation - Container architecture explanation - Step-by-step deployment process - Common commands reference - Troubleshooting section - SSL certificate management - Performance tuning guide - Security checklist - Health checks information - Database backup/restore procedures
488 lines
11 KiB
Markdown
488 lines
11 KiB
Markdown
# DigiServer v2 - Quick Deployment Guide
|
||
|
||
## 📋 Overview
|
||
|
||
DigiServer is deployed using Docker Compose with the following architecture:
|
||
|
||
```
|
||
Internet (User)
|
||
↓
|
||
Nginx Reverse Proxy (Port 80/443)
|
||
↓
|
||
Internal Docker Network
|
||
↓
|
||
Flask App (Gunicorn on Port 5000)
|
||
↓
|
||
SQLite Database
|
||
```
|
||
|
||
---
|
||
|
||
## 🚀 Quick Start (One Command)
|
||
|
||
```bash
|
||
cd /srv/digiserver-v2
|
||
bash deploy.sh
|
||
```
|
||
|
||
This will:
|
||
1. ✅ Start Docker containers
|
||
2. ✅ Initialize database
|
||
3. ✅ Run migrations
|
||
4. ✅ Configure HTTPS
|
||
5. ✅ Display access information
|
||
|
||
---
|
||
|
||
## 📦 Container Architecture
|
||
|
||
### **Container 1: digiserver-app (Flask)**
|
||
- **Image**: Built from Dockerfile (Python 3.13)
|
||
- **Port**: 5000 (internal only)
|
||
- **Volumes**:
|
||
- `./data:/app` - Persistent application data
|
||
- `./data/instance:/app/instance` - Database & configuration
|
||
- `./data/uploads:/app/app/static/uploads` - User uploads
|
||
- **Startup**: Automatically initializes database on first run
|
||
- **Health Check**: Every 30 seconds
|
||
|
||
### **Container 2: nginx (Reverse Proxy)**
|
||
- **Image**: nginx:alpine
|
||
- **Ports**: 80 & 443 (exposed to internet)
|
||
- **Volumes**:
|
||
- `nginx.conf` - Main configuration
|
||
- `./data/nginx-ssl/` - SSL certificates
|
||
- `./data/nginx-logs/` - Access/error logs
|
||
- `./data/certbot/` - Let's Encrypt challenges
|
||
- **Startup**: Waits for Flask app to start
|
||
- **Health Check**: Every 30 seconds
|
||
|
||
---
|
||
|
||
## 🔧 Deployment Steps Explained
|
||
|
||
### **Step 1: Start Containers**
|
||
```bash
|
||
docker-compose up -d
|
||
```
|
||
- Builds Flask app image (if needed)
|
||
- Starts both containers
|
||
- Waits for containers to be healthy
|
||
|
||
### **Step 2: Database Initialization** (docker-entrypoint.sh)
|
||
When Flask container starts:
|
||
1. Create required directories
|
||
2. Check if database exists
|
||
3. If NOT exists:
|
||
- Initialize SQLite database (dashboard.db)
|
||
- Create admin user from environment variables
|
||
4. Start Gunicorn server (4 workers, 120s timeout)
|
||
|
||
### **Step 3: Run Migrations**
|
||
```bash
|
||
docker-compose exec -T digiserver-app python /app/migrations/[migration_name].py
|
||
```
|
||
Applied migrations:
|
||
- `add_https_config_table.py` - HTTPS settings
|
||
- `add_player_user_table.py` - Player user management
|
||
- `add_email_to_https_config.py` - Email configuration
|
||
- `migrate_player_user_global.py` - Global settings
|
||
|
||
### **Step 4: Configure HTTPS**
|
||
- SSL certificates stored in `./data/nginx-ssl/`
|
||
- Pre-generated self-signed certs for development
|
||
- Ready for Let's Encrypt integration
|
||
|
||
### **Step 5: Reverse Proxy Routing** (nginx.conf)
|
||
```
|
||
HTTP (80):
|
||
• Redirect all traffic to HTTPS
|
||
• Allow ACME challenges for Let's Encrypt
|
||
|
||
HTTPS (443):
|
||
• TLS 1.2+, HTTP/2 enabled
|
||
• Proxy all requests to Flask app
|
||
• Security headers added
|
||
• Gzip compression enabled
|
||
• Max upload size: 2GB
|
||
• Proxy timeout: 300s
|
||
```
|
||
|
||
### **Step 6: ProxyFix Middleware** (app/app.py)
|
||
Extracts real client information from Nginx headers:
|
||
- `X-Forwarded-For` → Real client IP
|
||
- `X-Forwarded-Proto` → Protocol (http/https)
|
||
- `X-Forwarded-Host` → Original hostname
|
||
- `X-Forwarded-Port` → Original port
|
||
|
||
---
|
||
|
||
## 📂 Directory Structure & Persistence
|
||
|
||
```
|
||
/srv/digiserver-v2/
|
||
├── app/ (Flask application code)
|
||
├── data/ (PERSISTENT - mounted as Docker volume)
|
||
│ ├── app/ (Copy of app/ for container)
|
||
│ ├── instance/ (dashboard.db - SQLite database)
|
||
│ ├── uploads/ (User uploaded files)
|
||
│ ├── nginx-ssl/ (SSL certificates)
|
||
│ ├── nginx-logs/ (Nginx logs)
|
||
│ └── certbot/ (Let's Encrypt challenges)
|
||
├── migrations/ (Database schema updates)
|
||
├── docker-compose.yml (Container orchestration)
|
||
├── Dockerfile (Flask app image definition)
|
||
├── nginx.conf (Reverse proxy configuration)
|
||
└── docker-entrypoint.sh (Container startup script)
|
||
```
|
||
|
||
---
|
||
|
||
## 🔐 Default Credentials
|
||
|
||
```
|
||
Username: admin
|
||
Password: admin123
|
||
```
|
||
|
||
⚠️ **CHANGE IMMEDIATELY IN PRODUCTION!**
|
||
|
||
---
|
||
|
||
## 🌐 Access Points
|
||
|
||
After deployment, access the app at:
|
||
- `https://localhost` (if deployed locally)
|
||
- `https://192.168.0.121` (if deployed on server)
|
||
- `https://<DOMAIN>` (if DNS configured)
|
||
|
||
---
|
||
|
||
## ⚙️ Environment Variables (Optional)
|
||
|
||
Create `.env` file in project root:
|
||
|
||
```bash
|
||
# Network Configuration
|
||
HOSTNAME=digiserver
|
||
DOMAIN=digiserver.example.com
|
||
IP_ADDRESS=192.168.0.121
|
||
|
||
# SSL/HTTPS
|
||
EMAIL=admin@example.com
|
||
|
||
# Flask Configuration
|
||
SECRET_KEY=your-secret-key-here
|
||
FLASK_ENV=production
|
||
|
||
# Admin User
|
||
ADMIN_USERNAME=admin
|
||
ADMIN_PASSWORD=admin123
|
||
```
|
||
|
||
Then start with:
|
||
```bash
|
||
docker-compose up -d
|
||
```
|
||
|
||
---
|
||
|
||
## 🛠️ Common Commands
|
||
|
||
### **Start/Stop Containers**
|
||
```bash
|
||
# Start containers
|
||
docker-compose up -d
|
||
|
||
# Stop containers
|
||
docker-compose down
|
||
|
||
# Restart containers
|
||
docker-compose restart
|
||
|
||
# Restart specific container
|
||
docker-compose restart digiserver-app
|
||
docker-compose restart nginx
|
||
```
|
||
|
||
### **View Logs**
|
||
```bash
|
||
# All containers
|
||
docker-compose logs
|
||
|
||
# Follow logs (real-time)
|
||
docker-compose logs -f
|
||
|
||
# Specific container
|
||
docker-compose logs -f digiserver-app
|
||
docker-compose logs -f nginx
|
||
|
||
# Show last 50 lines
|
||
docker-compose logs --tail=50 digiserver-app
|
||
```
|
||
|
||
### **Container Status**
|
||
```bash
|
||
# Show running containers
|
||
docker-compose ps
|
||
|
||
# Show container details
|
||
docker-compose ps -a
|
||
|
||
# Check container health
|
||
docker ps --format="table {{.Names}}\t{{.Status}}"
|
||
```
|
||
|
||
### **Database Operations**
|
||
```bash
|
||
# Access database shell
|
||
docker-compose exec digiserver-app sqlite3 /app/instance/dashboard.db
|
||
|
||
# Backup database
|
||
docker-compose exec digiserver-app cp /app/instance/dashboard.db /app/instance/dashboard.db.backup
|
||
|
||
# Restore database
|
||
docker-compose exec digiserver-app cp /app/instance/dashboard.db.backup /app/instance/dashboard.db
|
||
```
|
||
|
||
### **Nginx Operations**
|
||
```bash
|
||
# Validate Nginx configuration
|
||
docker exec digiserver-nginx nginx -t
|
||
|
||
# Reload Nginx (without restart)
|
||
docker exec digiserver-nginx nginx -s reload
|
||
|
||
# View Nginx logs
|
||
docker-compose logs -f nginx
|
||
```
|
||
|
||
---
|
||
|
||
## 🔒 SSL Certificate Management
|
||
|
||
### **Generate New Self-Signed Certificate**
|
||
```bash
|
||
bash generate_nginx_certs.sh 192.168.0.121 365
|
||
docker-compose restart nginx
|
||
```
|
||
|
||
Parameters:
|
||
- `192.168.0.121` - Domain/IP for certificate
|
||
- `365` - Certificate validity in days
|
||
|
||
### **Set Up Let's Encrypt (Production)**
|
||
1. Update `DOMAIN` and `EMAIL` in environment
|
||
2. Modify `nginx.conf` to enable certbot challenges
|
||
3. Run certbot:
|
||
```bash
|
||
docker run --rm -v $(pwd)/data/certbot:/etc/letsencrypt \
|
||
-v $(pwd)/data/nginx-logs:/var/log/letsencrypt \
|
||
certbot/certbot certonly --webroot \
|
||
-w /var/www/certbot \
|
||
-d yourdomain.com \
|
||
-m your-email@example.com \
|
||
--agree-tos
|
||
```
|
||
|
||
---
|
||
|
||
## 🐛 Troubleshooting
|
||
|
||
### **Containers not starting?**
|
||
```bash
|
||
# Check docker-compose logs
|
||
docker-compose logs
|
||
|
||
# Check system resources
|
||
docker stats
|
||
|
||
# Restart Docker daemon
|
||
sudo systemctl restart docker
|
||
```
|
||
|
||
### **Application not responding?**
|
||
```bash
|
||
# Check app container health
|
||
docker-compose ps
|
||
|
||
# View app logs
|
||
docker-compose logs -f digiserver-app
|
||
|
||
# Test Flask directly
|
||
docker-compose exec digiserver-app curl http://localhost:5000/
|
||
```
|
||
|
||
### **HTTPS not working?**
|
||
```bash
|
||
# Verify Nginx config
|
||
docker exec digiserver-nginx nginx -t
|
||
|
||
# Check SSL certificates exist
|
||
ls -la ./data/nginx-ssl/
|
||
|
||
# View Nginx error logs
|
||
docker-compose logs nginx
|
||
```
|
||
|
||
### **Database issues?**
|
||
```bash
|
||
# Check database file exists
|
||
ls -la ./data/instance/dashboard.db
|
||
|
||
# Verify database permissions
|
||
docker-compose exec digiserver-app ls -la /app/instance/
|
||
|
||
# Check database tables
|
||
docker-compose exec digiserver-app sqlite3 /app/instance/dashboard.db ".tables"
|
||
```
|
||
|
||
### **Port already in use?**
|
||
```bash
|
||
# Find process using port 80
|
||
sudo lsof -i :80
|
||
|
||
# Find process using port 443
|
||
sudo lsof -i :443
|
||
|
||
# Kill process (if needed)
|
||
sudo kill -9 <PID>
|
||
```
|
||
|
||
---
|
||
|
||
## 📊 Health Checks
|
||
|
||
Both containers have health checks:
|
||
|
||
**Flask App**: Pings `http://localhost:5000/` every 30 seconds
|
||
**Nginx**: Pings `http://localhost:80/` every 30 seconds
|
||
|
||
Check health status:
|
||
```bash
|
||
docker-compose ps
|
||
# Look for "Up (healthy)" status
|
||
```
|
||
|
||
---
|
||
|
||
## 🔄 Database Backup & Restore
|
||
|
||
### **Backup**
|
||
```bash
|
||
# Create backup
|
||
docker-compose exec digiserver-app cp /app/instance/dashboard.db /app/instance/dashboard.backup.db
|
||
|
||
# Download to local machine
|
||
cp ./data/instance/dashboard.backup.db ./backup/
|
||
```
|
||
|
||
### **Restore**
|
||
```bash
|
||
# Stop containers
|
||
docker-compose stop
|
||
|
||
# Restore database
|
||
cp ./backup/dashboard.backup.db ./data/instance/dashboard.db
|
||
|
||
# Start containers
|
||
docker-compose up -d
|
||
```
|
||
|
||
---
|
||
|
||
## 📈 Performance Tuning
|
||
|
||
### **Gunicorn Workers** (docker-entrypoint.sh)
|
||
```bash
|
||
# Default: 4 workers
|
||
# Formula: (2 × CPU_count) + 1
|
||
# For 4-core CPU: 9 workers
|
||
|
||
# Modify docker-entrypoint.sh:
|
||
gunicorn --workers 9 ...
|
||
```
|
||
|
||
### **Nginx Worker Processes** (nginx.conf)
|
||
```nginx
|
||
# Default: auto (CPU count)
|
||
worker_processes auto;
|
||
|
||
# Or specify manually:
|
||
worker_processes 4;
|
||
```
|
||
|
||
### **Upload Timeout** (nginx.conf)
|
||
```nginx
|
||
# Default: 300s
|
||
proxy_connect_timeout 300s;
|
||
proxy_send_timeout 300s;
|
||
proxy_read_timeout 300s;
|
||
```
|
||
|
||
---
|
||
|
||
## 🔐 Security Checklist
|
||
|
||
- [ ] Change admin password immediately
|
||
- [ ] Set strong `SECRET_KEY` environment variable
|
||
- [ ] Enable firewall rules (allow only ports 80, 443)
|
||
- [ ] Set up HTTPS with Let's Encrypt
|
||
- [ ] Configure regular database backups
|
||
- [ ] Review Nginx security headers
|
||
- [ ] Update Flask dependencies regularly
|
||
- [ ] Monitor container logs for errors
|
||
- [ ] Restrict admin panel access (IP whitelist optional)
|
||
- [ ] Enable Flask debug mode only in development
|
||
|
||
---
|
||
|
||
## 📞 Support & Documentation
|
||
|
||
- **Nginx Setup**: See `NGINX_SETUP_QUICK.md`
|
||
- **ProxyFix Configuration**: See `PROXY_FIX_SETUP.md`
|
||
- **Deployment Commands**: See `DEPLOYMENT_COMMANDS.md`
|
||
- **Issue Troubleshooting**: Check `old_code_documentation/`
|
||
|
||
---
|
||
|
||
## ✅ Deployment Checklist
|
||
|
||
- [ ] Docker & Docker Compose installed
|
||
- [ ] Running from `/srv/digiserver-v2` directory
|
||
- [ ] Environment variables configured (optional)
|
||
- [ ] Port 80/443 available
|
||
- [ ] Sufficient disk space (min 5GB)
|
||
- [ ] Sufficient RAM (min 2GB free)
|
||
- [ ] Network connectivity verified
|
||
- [ ] SSL certificates generated or obtained
|
||
- [ ] Admin credentials changed (production)
|
||
|
||
---
|
||
|
||
## 🚀 Next Steps After Deployment
|
||
|
||
1. **Access Web Interface**
|
||
- Login with admin credentials
|
||
- Change password immediately
|
||
|
||
2. **Configure Application**
|
||
- Set up players
|
||
- Upload content
|
||
- Configure groups & permissions
|
||
|
||
3. **Production Hardening**
|
||
- Enable Let's Encrypt HTTPS
|
||
- Configure firewall rules
|
||
- Set up database backups
|
||
- Monitor logs
|
||
|
||
4. **Optional Enhancements**
|
||
- Set up custom domain
|
||
- Configure email notifications
|
||
- Install optional dependencies (LibreOffice, etc.)
|
||
|
||
---
|
||
|
||
**Last Updated**: January 15, 2026
|