updated player deployment for digiserver

This commit is contained in:
ske087
2026-06-07 23:40:50 +03:00
parent b97372f74d
commit f674330b93
30 changed files with 3459 additions and 201 deletions
@@ -0,0 +1,564 @@
# 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
```
---
## 🚀 Complete Deployment Workflow
### **1️⃣ Clone & Setup**
```bash
# Copy the app folder from repository
git clone <repository>
cd digiserver-v2
# Copy environment file and modify as needed
cp .env.example .env
# Edit .env with your configuration:
nano .env
```
**Configure in .env:**
```env
SECRET_KEY=your-secret-key-change-this
ADMIN_USERNAME=admin
ADMIN_PASSWORD=your-secure-password
DOMAIN=your-domain.com
EMAIL=admin@your-domain.com
IP_ADDRESS=192.168.0.111
```
---
### **2️⃣ Deploy via Script**
```bash
# Run the deployment script
./deploy.sh
```
This automatically:
1. ✅ Creates `data/` directories (instance, uploads, nginx-ssl, etc.)
2. ✅ Copies nginx configs from repo root to `data/`
3. ✅ Starts Docker containers
4. ✅ Initializes database
5. ✅ Runs all migrations
6. ✅ Configures HTTPS with SSL certificates
7. ✅ Displays access information
**Output shows:**
- Access URLs (HTTP/HTTPS)
- Default credentials
- Next steps for configuration
---
### **3️⃣ Network Migration (When Network Changes)**
When moving the server to a different network with a new IP:
```bash
# Migrate to the new network IP
./migrate_network.sh 10.55.150.160
# Optional: with custom hostname
./migrate_network.sh 10.55.150.160 digiserver-secured
```
This automatically:
1. ✅ Regenerates SSL certificates for new IP
2. ✅ Updates database HTTPS configuration
3. ✅ Restarts nginx and app containers
4. ✅ Verifies HTTPS connectivity
---
### **4️⃣ Normal Operations**
**Restart containers:**
```bash
docker compose restart
```
**Stop containers:**
```bash
docker compose down
```
**View logs:**
```bash
docker compose logs -f
```
**View container status:**
```bash
docker compose ps
```
---
## 📦 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
@@ -0,0 +1,71 @@
# DigiServer Standalone Deployment Archive
This folder contains files from the original standalone DigiServer v2 deployment setup. These files are **no longer used** in the Enterprise Digital Platform integrated environment.
## Why These Files Are Here
DigiServer v2 was originally developed as a standalone application with its own:
- Docker Compose configuration
- Nginx reverse proxy
- Deployment scripts
- HTTPS/SSL setup utilities
When DigiServer was integrated into the Enterprise Digital Platform, these functions were consolidated into the platform-wide infrastructure (root-level `docker-compose.yml`, central nginx, etc.).
## Files in This Archive
| File | Purpose | Status |
|------|---------|--------|
| `docker-compose.yml` | Standalone app orchestration | ❌ Replaced by root docker-compose.yml |
| `nginx.conf` | Standalone reverse proxy config | ❌ Replaced by platform nginx |
| `nginx-custom-domains.conf` | Custom domain support | ❌ Replaced by platform nginx |
| `QUICK_DEPLOYMENT.md` | Standalone deployment guide | 📚 Reference only |
| `deploy.sh` | Standalone deployment script | ❌ No longer needed |
| `verify-deployment.sh` | Standalone verification script | ❌ No longer needed |
| `deployment-commands-reference.sh` | Deployment command reference | 📚 Reference only |
| `generate_nginx_certs.sh` | Standalone HTTPS cert generation | ❌ Platform handles this |
| `migrate_network.sh` | Network migration utility | ❌ Standalone only |
## Files Still in Use
The following files from the original setup are **still active** and needed:
-**Dockerfile** - Used by platform docker-compose.yml to build digiserver image
-**docker-entrypoint.sh** - Referenced by Dockerfile as container startup script
## When You Might Need Files from This Archive
### Reference Information
- Review `QUICK_DEPLOYMENT.md` if you need to understand original standalone setup
- Check `deployment-commands-reference.sh` for historical deployment context
### Troubleshooting
- `verify-deployment.sh` - Could be adapted for debugging container health
- `nginx.conf` - Reference for nginx configuration patterns (platform uses central nginx)
### Historical Record
- `deploy.sh` - Shows original deployment workflow
- `docker-compose.yml` - Shows original app structure for reference
## For Enterprise Platform
All deployment is now handled through:
- **Root `docker-compose.yml`** - Orchestrates all services including digiserver
- **Root `nginx/nginx.conf`** - Central reverse proxy configuration
- **Docker multi-service architecture** - All apps in one network
## Restoring a File (if needed)
To restore any file from this archive to active use:
```bash
cp standalone-deployment-archive/<filename> ../
```
However, most files will need modifications to work with the integrated platform architecture.
---
**Archive Date:** June 7, 2026
**DigiServer Integration:** Complete
**Status:** Enterprise Digital Platform v1.0
@@ -0,0 +1,206 @@
#!/bin/bash
# Automated deployment script for DigiServer on a new PC
# Run this script to completely set up DigiServer with all configurations
set -e # Exit on any error
# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
echo -e "${BLUE}╔════════════════════════════════════════════════════════════════╗${NC}"
echo -e "${BLUE}║ DigiServer Automated Deployment ║${NC}"
echo -e "${BLUE}╚════════════════════════════════════════════════════════════════╝${NC}"
echo ""
# Check if docker compose is available
if ! docker compose version &> /dev/null; then
echo -e "${RED}❌ docker compose not found!${NC}"
echo "Please install docker compose first"
exit 1
fi
# Check if we're in the project directory
if [ ! -f "docker-compose.yml" ]; then
echo -e "${RED}❌ docker-compose.yml not found!${NC}"
echo "Please run this script from the digiserver-v2 directory"
exit 1
fi
# ============================================================================
# INITIALIZATION: Create data directories and copy nginx configs
# ============================================================================
echo -e "${YELLOW}📁 Initializing data directories...${NC}"
# Create necessary data directories
mkdir -p data/instance
mkdir -p data/uploads
mkdir -p data/nginx-ssl
mkdir -p data/nginx-logs
mkdir -p data/certbot
# Copy nginx configuration files from repo root to data folder
if [ -f "nginx.conf" ]; then
cp nginx.conf data/nginx.conf
echo -e " ${GREEN}${NC} nginx.conf copied to data/"
else
echo -e " ${RED}❌ nginx.conf not found in repo root!${NC}"
exit 1
fi
if [ -f "nginx-custom-domains.conf" ]; then
cp nginx-custom-domains.conf data/nginx-custom-domains.conf
echo -e " ${GREEN}${NC} nginx-custom-domains.conf copied to data/"
else
echo -e " ${RED}❌ nginx-custom-domains.conf not found in repo root!${NC}"
exit 1
fi
echo -e "${GREEN}✅ Data directories initialized${NC}"
echo ""
# ============================================================================
# CONFIGURATION VARIABLES
# ============================================================================
HOSTNAME="${HOSTNAME:-digiserver}"
DOMAIN="${DOMAIN:-digiserver.sibiusb.harting.intra}"
IP_ADDRESS="${IP_ADDRESS:-10.76.152.164}"
EMAIL="${EMAIL:-admin@example.com}"
PORT="${PORT:-443}"
echo -e "${BLUE}Configuration:${NC}"
echo " Hostname: $HOSTNAME"
echo " Domain: $DOMAIN"
echo " IP Address: $IP_ADDRESS"
echo " Email: $EMAIL"
echo " Port: $PORT"
echo ""
# ============================================================================
# STEP 1: Start containers
# ============================================================================
echo -e "${YELLOW}📦 [1/6] Starting containers...${NC}"
docker compose up -d
echo -e "${YELLOW}⏳ Waiting for containers to be healthy...${NC}"
sleep 10
# Verify containers are running
if ! docker compose ps | grep -q "Up"; then
echo -e "${RED}❌ Containers failed to start!${NC}"
docker compose logs
exit 1
fi
echo -e "${GREEN}✅ Containers started successfully${NC}"
echo ""
# ============================================================================
# STEP 2: Run database migrations
# ============================================================================
echo -e "${YELLOW}📊 [2/6] Running database migrations...${NC}"
echo -e " • Creating https_config table..."
docker compose exec -T digiserver-app python /app/migrations/add_https_config_table.py
echo -e " • Creating player_user table..."
docker compose exec -T digiserver-app python /app/migrations/add_player_user_table.py
echo -e " • Adding email to https_config..."
docker compose exec -T digiserver-app python /app/migrations/add_email_to_https_config.py
echo -e " • Migrating player_user global settings..."
docker compose exec -T digiserver-app python /app/migrations/migrate_player_user_global.py
echo -e "${GREEN}✅ All database migrations completed${NC}"
echo ""
# ============================================================================
# STEP 3: Configure HTTPS
# ============================================================================
echo -e "${YELLOW}🔒 [3/6] Configuring HTTPS...${NC}"
docker compose exec -T digiserver-app python /app/https_manager.py enable \
"$HOSTNAME" \
"$DOMAIN" \
"$EMAIL" \
"$IP_ADDRESS" \
"$PORT"
echo -e "${GREEN}✅ HTTPS configured successfully${NC}"
echo ""
# ============================================================================
# STEP 4: Verify database setup
# ============================================================================
echo -e "${YELLOW}🔍 [4/6] Verifying database setup...${NC}"
docker compose exec -T digiserver-app python -c "
from app.app import create_app
from sqlalchemy import inspect
app = create_app()
with app.app_context():
inspector = inspect(app.extensions.db.engine)
tables = inspector.get_table_names()
print(' Database tables:')
for table in sorted(tables):
print(f' ✓ {table}')
print(f'')
print(f' ✅ Total tables: {len(tables)}')
" 2>/dev/null || echo " ⚠️ Database verification skipped"
echo ""
# ============================================================================
# STEP 5: Verify Caddy configuration
# ============================================================================
echo -e "${YELLOW}🔧 [5/6] Verifying Caddy configuration...${NC}"
docker compose exec -T caddy caddy validate --config /etc/caddy/Caddyfile >/dev/null 2>&1
if [ $? -eq 0 ]; then
echo -e " ${GREEN}✅ Caddy configuration is valid${NC}"
else
echo -e " ${YELLOW}⚠️ Caddy validation skipped${NC}"
fi
echo ""
# ============================================================================
# STEP 6: Display summary
# ============================================================================
echo -e "${YELLOW}📋 [6/6] Displaying configuration summary...${NC}"
echo ""
docker compose exec -T digiserver-app python /app/https_manager.py status
echo ""
echo -e "${GREEN}╔════════════════════════════════════════════════════════════════╗${NC}"
echo -e "${GREEN}║ 🎉 Deployment Complete! ║${NC}"
echo -e "${GREEN}╚════════════════════════════════════════════════════════════════╝${NC}"
echo ""
echo -e "${BLUE}📍 Access Points:${NC}"
echo " 🔒 https://$HOSTNAME"
echo " 🔒 https://$IP_ADDRESS"
echo " 🔒 https://$DOMAIN"
echo ""
echo -e "${BLUE}📝 Default Credentials:${NC}"
echo " Username: admin"
echo " Password: admin123 (⚠️ CHANGE IN PRODUCTION)"
echo ""
echo -e "${BLUE}📚 Documentation:${NC}"
echo " • DEPLOYMENT_COMMANDS.md - Detailed docker exec commands"
echo " • HTTPS_CONFIGURATION.md - HTTPS setup details"
echo " • setup_https.sh - Manual configuration script"
echo ""
echo -e "${YELLOW}Next Steps:${NC}"
echo "1. Access the application at one of the URLs above"
echo "2. Log in with admin credentials"
echo "3. Change the default password immediately"
echo "4. Configure your players and content"
echo ""
echo -e "${BLUE}📞 Support:${NC}"
echo "For troubleshooting, see DEPLOYMENT_COMMANDS.md section 7"
echo ""
@@ -0,0 +1,246 @@
#!/bin/bash
# DigiServer v2 Production Deployment Commands Reference
# Use this file as a reference for all deployment-related operations
echo "📋 DigiServer v2 Production Deployment Reference"
echo "================================================="
echo ""
echo "QUICK START:"
echo " 1. Set environment variables"
echo " 2. Create .env file"
echo " 3. Run: docker-compose up -d"
echo ""
echo "Available commands below (copy/paste as needed):"
echo ""
# ============================================================================
# SECTION: INITIAL SETUP
# ============================================================================
echo "=== SECTION 1: INITIAL SETUP ==="
echo ""
echo "Generate Secret Key:"
echo ' python -c "import secrets; print(secrets.token_urlsafe(32))"'
echo ""
echo "Create environment file from template:"
echo " cp .env.example .env"
echo " nano .env # Edit with your values"
echo ""
echo "Required .env variables:"
echo " SECRET_KEY=<generated-32-char-key>"
echo " ADMIN_USERNAME=admin"
echo " ADMIN_PASSWORD=<strong-password>"
echo " ADMIN_EMAIL=admin@company.com"
echo " DOMAIN=your-domain.com"
echo " EMAIL=admin@your-domain.com"
echo ""
# ============================================================================
# SECTION: DOCKER OPERATIONS
# ============================================================================
echo "=== SECTION 2: DOCKER OPERATIONS ==="
echo ""
echo "Build images:"
echo " docker-compose build"
echo ""
echo "Start services:"
echo " docker-compose up -d"
echo ""
echo "Stop services:"
echo " docker-compose down"
echo ""
echo "Restart services:"
echo " docker-compose restart"
echo ""
echo "View container status:"
echo " docker-compose ps"
echo ""
echo "View logs (live):"
echo " docker-compose logs -f digiserver-app"
echo ""
echo "View logs (last 100 lines):"
echo " docker-compose logs --tail=100 digiserver-app"
echo ""
# ============================================================================
# SECTION: DATABASE OPERATIONS
# ============================================================================
echo "=== SECTION 3: DATABASE OPERATIONS ==="
echo ""
echo "Initialize database (first deployment only):"
echo " docker-compose exec digiserver-app flask db upgrade"
echo ""
echo "Run database migrations:"
echo " docker-compose exec digiserver-app flask db upgrade head"
echo ""
echo "Create new migration (after model changes):"
echo " docker-compose exec digiserver-app flask db migrate -m 'description'"
echo ""
echo "Backup database:"
echo " docker-compose exec digiserver-app cp instance/dashboard.db /backup/dashboard.db.bak"
echo ""
echo "Restore database:"
echo " docker-compose exec digiserver-app cp /backup/dashboard.db.bak instance/dashboard.db"
echo ""
# ============================================================================
# SECTION: VERIFICATION & TESTING
# ============================================================================
echo "=== SECTION 4: VERIFICATION & TESTING ==="
echo ""
echo "Health check:"
echo " curl -k https://your-domain.com/api/health"
echo ""
echo "Check CORS headers (should see Access-Control-Allow-*):"
echo " curl -i -k https://your-domain.com/api/playlists"
echo ""
echo "Check HTTPS only (should redirect):"
echo " curl -i http://your-domain.com/"
echo ""
echo "Test certificate:"
echo " openssl s_client -connect your-domain.com:443 -showcerts"
echo ""
echo "Check SSL certificate expiry:"
echo " openssl x509 -enddate -noout -in data/nginx-ssl/cert.pem"
echo ""
# ============================================================================
# SECTION: TROUBLESHOOTING
# ============================================================================
echo "=== SECTION 5: TROUBLESHOOTING ==="
echo ""
echo "View full container logs:"
echo " docker-compose logs digiserver-app"
echo ""
echo "Execute command in container:"
echo " docker-compose exec digiserver-app bash"
echo ""
echo "Check container resources:"
echo " docker stats"
echo ""
echo "Remove and rebuild from scratch:"
echo " docker-compose down -v"
echo " docker-compose build --no-cache"
echo " docker-compose up -d"
echo ""
echo "Check disk space:"
echo " du -sh data/"
echo ""
echo "View network configuration:"
echo " docker-compose exec digiserver-app netstat -tuln"
echo ""
# ============================================================================
# SECTION: MAINTENANCE
# ============================================================================
echo "=== SECTION 6: MAINTENANCE ==="
echo ""
echo "Clean up unused Docker resources:"
echo " docker system prune -a"
echo ""
echo "Backup entire application:"
echo " tar -czf digiserver-backup-\$(date +%Y%m%d).tar.gz ."
echo ""
echo "Update Docker images:"
echo " docker-compose pull"
echo " docker-compose up -d"
echo ""
echo "Rebuild and redeploy:"
echo " docker-compose down"
echo " docker-compose build --no-cache"
echo " docker-compose up -d"
echo ""
# ============================================================================
# SECTION: MONITORING
# ============================================================================
echo "=== SECTION 7: MONITORING ==="
echo ""
echo "Monitor containers in real-time:"
echo " watch -n 1 docker-compose ps"
echo ""
echo "Monitor resource usage:"
echo " docker stats --no-stream"
echo ""
echo "Check application errors:"
echo " docker-compose logs --since 10m digiserver-app | grep ERROR"
echo ""
# ============================================================================
# SECTION: GIT OPERATIONS
# ============================================================================
echo "=== SECTION 8: GIT OPERATIONS ==="
echo ""
echo "Check deployment status:"
echo " git status"
echo ""
echo "View deployment history:"
echo " git log --oneline -5"
echo ""
echo "Commit deployment changes:"
echo " git add ."
echo " git commit -m 'Deployment configuration'"
echo ""
echo "Tag release:"
echo " git tag -a v2.0.0 -m 'Production release'"
echo " git push --tags"
echo ""
# ============================================================================
# SECTION: EMERGENCY PROCEDURES
# ============================================================================
echo "=== SECTION 9: EMERGENCY PROCEDURES ==="
echo ""
echo "Kill stuck container:"
echo " docker-compose kill digiserver-app"
echo ""
echo "Restore from backup:"
echo " docker-compose down"
echo " cp /backup/dashboard.db.bak data/instance/dashboard.db"
echo " docker-compose up -d"
echo ""
echo "Rollback to previous version:"
echo " git checkout v1.9.0"
echo " docker-compose down"
echo " docker-compose build"
echo " docker-compose up -d"
echo ""
# ============================================================================
# SECTION: QUICK REFERENCE
# ============================================================================
echo "=== SECTION 10: QUICK REFERENCE ALIASES ==="
echo ""
echo "Add these to your ~/.bashrc for quick access:"
echo ""
cat << 'EOF'
alias ds-start='docker-compose up -d'
alias ds-stop='docker-compose down'
alias ds-logs='docker-compose logs -f digiserver-app'
alias ds-health='curl -k https://your-domain/api/health'
alias ds-status='docker-compose ps'
alias ds-bash='docker-compose exec digiserver-app bash'
EOF
echo ""
# ============================================================================
# DONE
# ============================================================================
echo "=== END OF REFERENCE ==="
echo ""
echo "For detailed documentation, see:"
echo " - PRODUCTION_DEPLOYMENT_GUIDE.md"
echo " - DEPLOYMENT_READINESS_SUMMARY.md"
echo " - old_code_documentation/"
echo ""
@@ -0,0 +1,61 @@
#version: '3.8'
services:
digiserver-app:
build: .
container_name: digiserver-v2
# Don't expose directly; use Caddy reverse proxy instead
expose:
- "5000"
volumes:
# Code is in the Docker image - no volume mount needed
# Only mount persistent data folders:
- ./data/instance:/app/instance
- ./data/uploads:/app/app/static/uploads
environment:
- FLASK_ENV=production
- SECRET_KEY=${SECRET_KEY:-your-secret-key-change-this}
- ADMIN_USERNAME=${ADMIN_USERNAME:-admin}
- ADMIN_PASSWORD=${ADMIN_PASSWORD:-admin123}
restart: unless-stopped
healthcheck:
test: ["CMD", "python", "-c", "import urllib.request; urllib.request.urlopen('http://localhost:5000/').read()"]
interval: 30s
timeout: 10s
retries: 3
start_period: 40s
networks:
- digiserver-network
# Nginx reverse proxy with HTTPS support
nginx:
image: nginx:alpine
container_name: digiserver-nginx
ports:
- "80:80"
- "443:443"
volumes:
- ./data/nginx.conf:/etc/nginx/nginx.conf:ro
- ./data/nginx-custom-domains.conf:/etc/nginx/conf.d/custom-domains.conf:rw
- ./data/nginx-ssl:/etc/nginx/ssl:ro
- ./data/nginx-logs:/var/log/nginx
- ./data/certbot:/var/www/certbot:ro # For Let's Encrypt ACME challenges
environment:
- DOMAIN=${DOMAIN:-localhost}
- EMAIL=${EMAIL:-admin@localhost}
depends_on:
digiserver-app:
condition: service_started
restart: unless-stopped
healthcheck:
test: ["CMD", "wget", "--quiet", "--tries=1", "--spider", "http://localhost:80/"]
interval: 30s
timeout: 10s
retries: 3
start_period: 10s
networks:
- digiserver-network
networks:
digiserver-network:
driver: bridge
@@ -0,0 +1,30 @@
#!/bin/bash
# Generate self-signed SSL certificates for Nginx
# Usage: ./generate_nginx_certs.sh [domain] [days]
DOMAIN=${1:-localhost}
DAYS=${2:-365}
CERT_DIR="./data/nginx-ssl"
echo "🔐 Generating self-signed SSL certificate for Nginx"
echo "Domain: $DOMAIN"
echo "Valid for: $DAYS days"
echo "Certificate directory: $CERT_DIR"
# Create directory if it doesnt exist
mkdir -p "$CERT_DIR"
# Generate private key and certificate
openssl req -x509 -nodes -days "$DAYS" \
-newkey rsa:2048 \
-keyout "$CERT_DIR/key.pem" \
-out "$CERT_DIR/cert.pem" \
-subj "/CN=$DOMAIN/O=DigiServer/C=US"
# Set proper permissions
chmod 644 "$CERT_DIR/cert.pem"
chmod 600 "$CERT_DIR/key.pem"
echo "✅ Certificates generated successfully!"
echo "Certificate: $CERT_DIR/cert.pem"
echo "Key: $CERT_DIR/key.pem"
@@ -0,0 +1,153 @@
#!/bin/bash
# Network Migration Script for DigiServer
# Use this when moving the server to a new network with a different IP address
# Example: ./migrate_network.sh 10.55.150.160
set -e
# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m'
# Check arguments
if [ $# -lt 1 ]; then
echo -e "${RED}❌ Usage: ./migrate_network.sh <new_ip_address> [hostname]${NC}"
echo ""
echo " Example: ./migrate_network.sh 10.55.150.160"
echo " Example: ./migrate_network.sh 10.55.150.160 digiserver-secured"
echo ""
exit 1
fi
NEW_IP="$1"
HOSTNAME="${2:-digiserver}"
EMAIL="${EMAIL:-admin@example.com}"
PORT="${PORT:-443}"
# Validate IP format
if ! [[ "$NEW_IP" =~ ^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$ ]]; then
echo -e "${RED}❌ Invalid IP address format: $NEW_IP${NC}"
exit 1
fi
echo -e "${BLUE}╔════════════════════════════════════════════════════════════════╗${NC}"
echo -e "${BLUE}║ DigiServer Network Migration ║${NC}"
echo -e "${BLUE}╚════════════════════════════════════════════════════════════════╝${NC}"
echo ""
echo -e "${BLUE}Migration Settings:${NC}"
echo " New IP Address: $NEW_IP"
echo " Hostname: $HOSTNAME"
echo " Email: $EMAIL"
echo " Port: $PORT"
echo ""
# Check if containers are running
echo -e "${YELLOW}🔍 [1/4] Checking containers...${NC}"
if ! docker compose ps | grep -q "digiserver-app"; then
echo -e "${RED}❌ digiserver-app container not running!${NC}"
echo "Please start containers with: docker compose up -d"
exit 1
fi
echo -e "${GREEN}✅ Containers are running${NC}"
echo ""
# Step 1: Regenerate SSL certificates for new IP
echo -e "${YELLOW}🔐 [2/4] Regenerating SSL certificates for new IP...${NC}"
echo " Generating self-signed certificate for $NEW_IP..."
CERT_DIR="./data/nginx-ssl"
mkdir -p "$CERT_DIR"
openssl req -x509 -nodes -days 365 \
-newkey rsa:2048 \
-keyout "$CERT_DIR/key.pem" \
-out "$CERT_DIR/cert.pem" \
-subj "/CN=$NEW_IP/O=DigiServer/C=US" >/dev/null 2>&1
chmod 644 "$CERT_DIR/cert.pem"
chmod 600 "$CERT_DIR/key.pem"
echo -e " ${GREEN}${NC} Certificates regenerated for $NEW_IP"
echo -e "${GREEN}✅ SSL certificates updated${NC}"
echo ""
# Step 2: Update HTTPS configuration in database
echo -e "${YELLOW}🔧 [3/4] Updating HTTPS configuration in database...${NC}"
docker compose exec -T digiserver-app python << EOF
from app.app import create_app
from app.models.https_config import HTTPSConfig
from app.extensions import db
app = create_app('production')
with app.app_context():
# Update or create HTTPS config for the new IP
https_config = HTTPSConfig.query.first()
if https_config:
https_config.hostname = '$HOSTNAME'
https_config.ip_address = '$NEW_IP'
https_config.email = '$EMAIL'
https_config.port = $PORT
https_config.enabled = True
db.session.commit()
print(f" ✓ HTTPS configuration updated")
print(f" Hostname: {https_config.hostname}")
print(f" IP: {https_config.ip_address}")
print(f" Port: {https_config.port}")
else:
print(" ⚠️ No existing HTTPS config found")
print(" This will be created on next app startup")
EOF
echo -e "${GREEN}✅ Database configuration updated${NC}"
echo ""
# Step 3: Restart containers
echo -e "${YELLOW}🔄 [4/4] Restarting containers...${NC}"
docker compose restart nginx digiserver-app
sleep 3
if ! docker compose ps | grep -q "Up"; then
echo -e "${RED}❌ Containers failed to restart!${NC}"
docker compose logs | tail -20
exit 1
fi
echo -e "${GREEN}✅ Containers restarted successfully${NC}"
echo ""
# Verification
echo -e "${YELLOW}🔍 Verifying HTTPS connectivity...${NC}"
sleep 2
if curl -s -k -I https://$NEW_IP 2>/dev/null | grep -q "HTTP"; then
echo -e "${GREEN}✅ HTTPS connection verified${NC}"
else
echo -e "${YELLOW}⚠️ HTTPS verification pending (containers warming up)${NC}"
fi
echo ""
echo -e "${GREEN}╔════════════════════════════════════════════════════════════════╗${NC}"
echo -e "${GREEN}║ ✅ Network Migration Complete! ║${NC}"
echo -e "${GREEN}╚════════════════════════════════════════════════════════════════╝${NC}"
echo ""
echo -e "${BLUE}📍 New Access Points:${NC}"
echo " 🔒 https://$NEW_IP"
echo " 🔒 https://$HOSTNAME.local (if mDNS enabled)"
echo ""
echo -e "${BLUE}📋 Changes Made:${NC}"
echo " ✓ SSL certificates regenerated for $NEW_IP"
echo " ✓ Database HTTPS config updated"
echo " ✓ Nginx and app containers restarted"
echo ""
echo -e "${YELLOW}⏳ Allow 30 seconds for containers to become fully healthy${NC}"
echo ""
@@ -0,0 +1,21 @@
# Nginx configuration for custom HTTPS domains
# This file will be dynamically generated based on HTTPSConfig database entries
# Include this in your nginx.conf with: include /etc/nginx/conf.d/custom-domains.conf;
# Example entry for custom domain:
# server {
# listen 443 ssl http2;
# listen [::]:443 ssl http2;
# server_name digiserver.example.com;
#
# ssl_certificate /etc/nginx/ssl/custom/cert.pem;
# ssl_certificate_key /etc/nginx/ssl/custom/key.pem;
#
# location / {
# proxy_pass http://digiserver_app;
# proxy_set_header Host $host;
# proxy_set_header X-Real-IP $remote_addr;
# proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# proxy_set_header X-Forwarded-Proto $scheme;
# }
# }
@@ -0,0 +1,129 @@
user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
use epoll;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
types_hash_max_size 2048;
client_max_body_size 2048M;
# Gzip compression
gzip on;
gzip_vary on;
gzip_proxied any;
gzip_comp_level 6;
gzip_types text/plain text/css text/xml text/javascript application/json application/javascript application/xml+rss application/rss+xml;
# Upstream to Flask application
upstream digiserver_app {
server digiserver-app:5000;
keepalive 32;
}
# HTTP Server - redirect to HTTPS
server {
listen 80 default_server;
listen [::]:80 default_server;
server_name _;
# Allow ACME challenges for Let's Encrypt
location /.well-known/acme-challenge/ {
root /var/www/certbot;
}
# Redirect HTTP to HTTPS for non-ACME requests
location / {
return 301 https://$host$request_uri;
}
}
# HTTPS Server (with self-signed cert by default)
server {
listen 443 ssl http2 default_server;
listen [::]:443 ssl http2 default_server;
server_name localhost;
# SSL certificate paths (will be volume-mounted)
ssl_certificate /etc/nginx/ssl/cert.pem;
ssl_certificate_key /etc/nginx/ssl/key.pem;
# SSL Configuration
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers on;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
# Security Headers
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header Referrer-Policy "no-referrer-when-downgrade" always;
add_header Content-Security-Policy "default-src 'self' http: https: data: blob: 'unsafe-inline'" always;
# CORS Headers for API endpoints (allows player device connections)
add_header 'Access-Control-Allow-Origin' '*' always;
add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, OPTIONS' always;
add_header 'Access-Control-Allow-Headers' 'Content-Type, Authorization' always;
add_header 'Access-Control-Max-Age' '3600' always;
# Handle OPTIONS requests for CORS preflight
if ($request_method = 'OPTIONS') {
return 204;
}
# Proxy settings
location / {
proxy_pass http://digiserver_app;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Host $server_name;
proxy_set_header X-Forwarded-Port $server_port;
# Timeouts for large uploads
proxy_connect_timeout 300s;
proxy_send_timeout 300s;
proxy_read_timeout 300s;
# Buffering
proxy_buffering on;
proxy_buffer_size 128k;
proxy_buffers 4 256k;
proxy_busy_buffers_size 256k;
}
# Static files caching
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ {
proxy_pass http://digiserver_app;
proxy_cache_valid 200 60d;
expires 60d;
add_header Cache-Control "public, immutable";
}
}
# Additional server blocks for custom domains can be included here
include /etc/nginx/conf.d/*.conf;
}
@@ -0,0 +1,342 @@
#!/bin/bash
# Production Deployment Verification Script
# Run this before and after production deployment
set -e
echo "╔════════════════════════════════════════════════════════════════╗"
echo "║ DigiServer v2 Production Deployment Verification ║"
echo "╚════════════════════════════════════════════════════════════════╝"
TIMESTAMP=$(date +%Y-%m-%d\ %H:%M:%S)
cd "$(dirname "$0")"
# Color codes
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
# Counters
PASSED=0
FAILED=0
WARNINGS=0
# Helper functions
pass() {
echo -e "${GREEN}${NC} $1"
((PASSED++))
}
fail() {
echo -e "${RED}${NC} $1"
((FAILED++))
}
warn() {
echo -e "${YELLOW}${NC} $1"
((WARNINGS++))
}
info() {
echo -e "${BLUE}${NC} $1"
}
section() {
echo -e "\n${BLUE}═══════════════════════════════════════${NC}"
echo -e "${BLUE} $1${NC}"
echo -e "${BLUE}═══════════════════════════════════════${NC}"
}
# ============================================================================
section "1. Git Status"
# ============================================================================
if git rev-parse --git-dir > /dev/null 2>&1; then
pass "Git repository initialized"
BRANCH=$(git rev-parse --abbrev-ref HEAD)
COMMIT=$(git rev-parse --short HEAD)
info "Current branch: $BRANCH, Commit: $COMMIT"
if [ -n "$(git status --porcelain)" ]; then
warn "Uncommitted changes detected"
git status --short
else
pass "All changes committed"
fi
else
fail "Not a git repository"
fi
# ============================================================================
section "2. Environment Configuration"
# ============================================================================
if [ -f .env ]; then
pass ".env file exists"
else
warn ".env file not found (using defaults or docker-compose environment)"
fi
if [ -f .env.example ]; then
pass ".env.example template exists"
else
warn ".env.example template missing"
fi
# ============================================================================
section "3. Docker Configuration"
# ============================================================================
if command -v docker &> /dev/null; then
pass "Docker installed"
DOCKER_VERSION=$(docker --version | cut -d' ' -f3 | tr -d ',')
info "Docker version: $DOCKER_VERSION"
else
fail "Docker not installed"
fi
if command -v docker-compose &> /dev/null; then
pass "Docker Compose installed"
DC_VERSION=$(docker-compose --version | cut -d' ' -f3 | tr -d ',')
info "Docker Compose version: $DC_VERSION"
else
fail "Docker Compose not installed"
fi
if [ -f docker-compose.yml ]; then
pass "docker-compose.yml exists"
# Validate syntax
if docker-compose config > /dev/null 2>&1; then
pass "docker-compose.yml syntax valid"
else
fail "docker-compose.yml syntax error"
fi
else
fail "docker-compose.yml not found"
fi
# ============================================================================
section "4. Dockerfile & Images"
# ============================================================================
if [ -f Dockerfile ]; then
pass "Dockerfile exists"
# Check for security best practices
if grep -q "HEALTHCHECK" Dockerfile; then
pass "Health check configured"
else
warn "No health check in Dockerfile"
fi
if grep -q "USER appuser" Dockerfile || grep -q "USER.*:1000" Dockerfile; then
pass "Non-root user configured"
else
warn "Root user may be used in container"
fi
if grep -q "FROM.*alpine\|FROM.*slim\|FROM.*distroless" Dockerfile; then
pass "Minimal base image used"
else
warn "Large base image detected"
fi
else
fail "Dockerfile not found"
fi
# ============================================================================
section "5. Python Dependencies"
# ============================================================================
if [ -f requirements.txt ]; then
pass "requirements.txt exists"
PACKAGE_COUNT=$(wc -l < requirements.txt)
info "Total packages: $PACKAGE_COUNT"
# Check for critical packages
for pkg in Flask SQLAlchemy gunicorn flask-cors cryptography; do
if grep -q "$pkg" requirements.txt; then
pass "$pkg installed"
else
warn "$pkg not found in requirements.txt"
fi
done
# Check for specific versions
FLASK_VERSION=$(grep "^Flask==" requirements.txt | cut -d'=' -f3)
SQLALCHEMY_VERSION=$(grep "^SQLAlchemy==" requirements.txt | cut -d'=' -f3)
if [ -n "$FLASK_VERSION" ]; then
info "Flask version: $FLASK_VERSION"
fi
if [ -n "$SQLALCHEMY_VERSION" ]; then
info "SQLAlchemy version: $SQLALCHEMY_VERSION"
fi
else
fail "requirements.txt not found"
fi
# ============================================================================
section "6. Database Configuration"
# ============================================================================
if [ -d migrations ]; then
pass "migrations directory exists"
MIGRATION_COUNT=$(find migrations -name "*.py" | wc -l)
info "Migration files: $MIGRATION_COUNT"
if [ "$MIGRATION_COUNT" -gt 0 ]; then
pass "Database migrations configured"
else
warn "No migration files found"
fi
else
warn "migrations directory not found"
fi
# ============================================================================
section "7. SSL/TLS Certificate"
# ============================================================================
if [ -f data/nginx-ssl/cert.pem ]; then
pass "SSL certificate found"
CERT_EXPIRY=$(openssl x509 -enddate -noout -in data/nginx-ssl/cert.pem 2>/dev/null | cut -d= -f2)
EXPIRY_EPOCH=$(date -d "$CERT_EXPIRY" +%s 2>/dev/null || echo 0)
NOW_EPOCH=$(date +%s)
DAYS_LEFT=$(( ($EXPIRY_EPOCH - $NOW_EPOCH) / 86400 ))
info "Certificate expires: $CERT_EXPIRY"
info "Days remaining: $DAYS_LEFT days"
if [ "$DAYS_LEFT" -lt 0 ]; then
fail "Certificate has expired!"
elif [ "$DAYS_LEFT" -lt 30 ]; then
warn "Certificate expires in less than 30 days"
else
pass "Certificate is valid"
fi
if [ -f data/nginx-ssl/key.pem ]; then
pass "SSL private key found"
else
warn "SSL private key not found"
fi
else
warn "SSL certificate not found (self-signed required)"
fi
# ============================================================================
section "8. Configuration Files"
# ============================================================================
if [ -f app/config.py ]; then
pass "Flask config.py exists"
if grep -q "class ProductionConfig" app/config.py; then
pass "ProductionConfig class defined"
else
warn "ProductionConfig class missing"
fi
if grep -q "SESSION_COOKIE_SECURE" app/config.py; then
pass "SESSION_COOKIE_SECURE configured"
else
warn "SESSION_COOKIE_SECURE not configured"
fi
else
fail "app/config.py not found"
fi
if [ -f nginx.conf ]; then
pass "nginx.conf exists"
if grep -q "ssl_protocols" nginx.conf; then
pass "SSL protocols configured"
else
warn "SSL protocols not configured"
fi
if grep -q "access-control-allow" nginx.conf; then
pass "CORS headers in nginx"
else
info "CORS headers may be handled by Flask only"
fi
else
warn "nginx.conf not found"
fi
# ============================================================================
section "9. Runtime Verification"
# ============================================================================
if docker-compose ps 2>/dev/null | grep -q "Up"; then
pass "Docker containers are running"
# Check if app is healthy
if docker-compose ps 2>/dev/null | grep -q "digiserver-app.*healthy"; then
pass "DigiServer app container is healthy"
else
warn "DigiServer app container health status unknown"
fi
if docker-compose ps 2>/dev/null | grep -q "digiserver-nginx.*healthy"; then
pass "Nginx container is healthy"
else
warn "Nginx container health status unknown"
fi
else
info "Docker containers not running (will start on deployment)"
fi
# ============================================================================
section "10. Security Best Practices"
# ============================================================================
# Check for hardcoded secrets
if grep -r "SECRET_KEY\|PASSWORD\|API_KEY" app/ 2>/dev/null | grep -v "os.getenv\|config.py\|#" | wc -l | grep -q "^0$"; then
pass "No hardcoded secrets found"
else
warn "Possible hardcoded secrets detected (verify they use os.getenv)"
fi
# Check for debug mode
if grep -q "DEBUG.*=.*True" app/config.py 2>/dev/null; then
fail "DEBUG mode is enabled"
else
pass "DEBUG mode is disabled"
fi
# ============================================================================
section "Summary"
# ============================================================================
echo ""
echo -e "Test Results:"
echo -e " ${GREEN}Passed: $PASSED${NC}"
echo -e " ${YELLOW}Warnings: $WARNINGS${NC}"
echo -e " ${RED}Failed: $FAILED${NC}"
TOTAL=$((PASSED + FAILED + WARNINGS))
PERCENTAGE=$((PASSED * 100 / (PASSED + FAILED)))
if [ "$FAILED" -eq 0 ]; then
echo -e "\n${GREEN}✓ Production Deployment Ready!${NC}"
echo "Recommendation: Safe to deploy to production"
exit 0
elif [ "$FAILED" -le 2 ] && [ "$WARNINGS" -gt 0 ]; then
echo -e "\n${YELLOW}⚠ Deployment Possible with Caution${NC}"
echo "Recommendation: Address warnings before deployment"
exit 0
else
echo -e "\n${RED}✗ Deployment Not Recommended${NC}"
echo "Recommendation: Fix critical failures before deployment"
exit 1
fi