Compare commits
1 Commits
nginx
...
bb293b6a81
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
bb293b6a81 |
4
.dockerignore
Normal file → Executable file
@@ -52,4 +52,6 @@ PLAYER_AUTH.md
|
|||||||
PROGRESS.md
|
PROGRESS.md
|
||||||
README.md
|
README.md
|
||||||
|
|
||||||
|
# Config templates
|
||||||
|
player_config_template.ini
|
||||||
|
player_auth_module.py
|
||||||
|
|||||||
0
.gitignore
vendored
Normal file → Executable file
73
Caddyfile
Executable file
@@ -0,0 +1,73 @@
|
|||||||
|
{
|
||||||
|
# Global options
|
||||||
|
email admin@example.com
|
||||||
|
# Admin API for configuration management (listen on all interfaces)
|
||||||
|
admin 0.0.0.0:2019
|
||||||
|
}
|
||||||
|
|
||||||
|
# Shared reverse proxy configuration
|
||||||
|
(reverse_proxy_config) {
|
||||||
|
reverse_proxy digiserver-app:5000 {
|
||||||
|
header_up Host {host}
|
||||||
|
header_up X-Real-IP {remote_host}
|
||||||
|
header_up X-Forwarded-Proto {scheme}
|
||||||
|
|
||||||
|
# Timeouts for large uploads
|
||||||
|
transport http {
|
||||||
|
read_timeout 300s
|
||||||
|
write_timeout 300s
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# File upload size limit (2GB)
|
||||||
|
request_body {
|
||||||
|
max_size 2GB
|
||||||
|
}
|
||||||
|
|
||||||
|
# Security headers
|
||||||
|
header {
|
||||||
|
X-Frame-Options "SAMEORIGIN"
|
||||||
|
X-Content-Type-Options "nosniff"
|
||||||
|
X-XSS-Protection "1; mode=block"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Logging
|
||||||
|
log {
|
||||||
|
output file /var/log/caddy/access.log
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Localhost (development/local access - HTTP only for local dev)
|
||||||
|
http://localhost {
|
||||||
|
import reverse_proxy_config
|
||||||
|
}
|
||||||
|
|
||||||
|
# Main HTTPS entry point with multiple hostnames and IP
|
||||||
|
https://digiserver, https://10.76.152.164, https://digiserver.sibiusb.harting.intra {
|
||||||
|
import reverse_proxy_config
|
||||||
|
tls internal
|
||||||
|
}
|
||||||
|
|
||||||
|
# HTTP redirects to HTTPS for each hostname
|
||||||
|
http://digiserver {
|
||||||
|
redir https://{host}{uri}
|
||||||
|
}
|
||||||
|
|
||||||
|
http://10.76.152.164 {
|
||||||
|
redir https://{host}{uri}
|
||||||
|
}
|
||||||
|
|
||||||
|
http://digiserver.sibiusb.harting.intra {
|
||||||
|
redir https://{host}{uri}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Catch-all for any other HTTP requests
|
||||||
|
http://* {
|
||||||
|
import reverse_proxy_config
|
||||||
|
}
|
||||||
|
|
||||||
|
# Catch-all for any other HTTPS requests (fallback)
|
||||||
|
https://* {
|
||||||
|
import reverse_proxy_config
|
||||||
|
tls internal
|
||||||
|
}
|
||||||
0
Dockerfile
Normal file → Executable file
413
HTTPS_STATUS.txt
Normal file
@@ -0,0 +1,413 @@
|
|||||||
|
╔═══════════════════════════════════════════════════════════════════════════════╗
|
||||||
|
║ HTTPS MANAGEMENT SYSTEM IMPLEMENTATION ║
|
||||||
|
║ ✅ COMPLETE ║
|
||||||
|
╚═══════════════════════════════════════════════════════════════════════════════╝
|
||||||
|
|
||||||
|
📦 DELIVERABLES
|
||||||
|
═══════════════════════════════════════════════════════════════════════════════
|
||||||
|
|
||||||
|
✅ CREATED FILES (9 new files)
|
||||||
|
───────────────────────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
1. 🗄️ DATABASE MODEL
|
||||||
|
└─ app/models/https_config.py
|
||||||
|
• HTTPSConfig database model
|
||||||
|
• Fields: hostname, domain, ip_address, port, status, audit trail
|
||||||
|
• Methods: get_config(), create_or_update(), to_dict()
|
||||||
|
• Auto timestamps for created/updated dates
|
||||||
|
|
||||||
|
2. 🛣️ ADMIN ROUTES
|
||||||
|
└─ app/blueprints/admin.py (UPDATED)
|
||||||
|
• GET /admin/https-config - Configuration page
|
||||||
|
• POST /admin/https-config/update - Update settings
|
||||||
|
• GET /admin/https-config/status - JSON status endpoint
|
||||||
|
• Full validation and error handling
|
||||||
|
• Admin-only access control
|
||||||
|
|
||||||
|
3. 🎨 ADMIN TEMPLATE
|
||||||
|
└─ app/templates/admin/https_config.html
|
||||||
|
• Beautiful, user-friendly configuration interface
|
||||||
|
• Status display section
|
||||||
|
• Configuration form with toggle switch
|
||||||
|
• Input validation feedback
|
||||||
|
• Real-time preview of access points
|
||||||
|
• Comprehensive help sections
|
||||||
|
• Responsive mobile design
|
||||||
|
|
||||||
|
4. 📊 ADMIN DASHBOARD
|
||||||
|
└─ app/templates/admin/admin.html (UPDATED)
|
||||||
|
• New card: "🔒 HTTPS Configuration"
|
||||||
|
• Links to HTTPS configuration page
|
||||||
|
• Gradient design with lock icon
|
||||||
|
|
||||||
|
5. 🔄 DATABASE MIGRATION
|
||||||
|
└─ migrations/add_https_config_table.py
|
||||||
|
• Creates https_config table
|
||||||
|
• Sets up indexes and constraints
|
||||||
|
• Audit trail fields
|
||||||
|
|
||||||
|
6. 🖥️ CLI UTILITY
|
||||||
|
└─ https_manager.py
|
||||||
|
• Command-line interface
|
||||||
|
• Commands: status, enable, disable, show
|
||||||
|
• Useful for automation and scripting
|
||||||
|
|
||||||
|
7. 🚀 SETUP SCRIPT
|
||||||
|
└─ setup_https.sh
|
||||||
|
• Automated setup script
|
||||||
|
• Runs database migration
|
||||||
|
• Displays step-by-step instructions
|
||||||
|
|
||||||
|
8. 📚 DOCUMENTATION
|
||||||
|
├─ HTTPS_CONFIGURATION.md (Comprehensive guide)
|
||||||
|
├─ HTTPS_IMPLEMENTATION_SUMMARY.md (Architecture & details)
|
||||||
|
└─ HTTPS_QUICK_REFERENCE.md (Admin quick start)
|
||||||
|
|
||||||
|
═══════════════════════════════════════════════════════════════════════════════
|
||||||
|
|
||||||
|
✅ UPDATED FILES (3 modified files)
|
||||||
|
───────────────────────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
1. ✏️ app/models/__init__.py
|
||||||
|
• Added HTTPSConfig import
|
||||||
|
• Exported in __all__ list
|
||||||
|
|
||||||
|
2. ✏️ app/blueprints/admin.py
|
||||||
|
• Imported HTTPSConfig model
|
||||||
|
• Added three new routes for HTTPS management
|
||||||
|
• 160+ lines of new admin functionality
|
||||||
|
|
||||||
|
3. ✏️ app/templates/admin/admin.html
|
||||||
|
• Added HTTPS Configuration card to dashboard
|
||||||
|
• Purple gradient with lock icon
|
||||||
|
|
||||||
|
4. ✏️ Caddyfile
|
||||||
|
• Updated to use domain: digiserver.sibiusb.harting.intra
|
||||||
|
• IP fallback: 10.76.152.164
|
||||||
|
|
||||||
|
═══════════════════════════════════════════════════════════════════════════════
|
||||||
|
|
||||||
|
🎯 KEY FEATURES
|
||||||
|
═══════════════════════════════════════════════════════════════════════════════
|
||||||
|
|
||||||
|
✅ WEB INTERFACE
|
||||||
|
• Enable/Disable HTTPS with toggle switch
|
||||||
|
• Configure hostname, domain, IP address, port
|
||||||
|
• Status display with current settings
|
||||||
|
• Real-time preview of access URLs
|
||||||
|
• User-friendly form with validations
|
||||||
|
• Responsive design for all devices
|
||||||
|
|
||||||
|
✅ CONFIGURATION OPTIONS
|
||||||
|
• Hostname: Short server name
|
||||||
|
• Domain: Full domain name (e.g., digiserver.sibiusb.harting.intra)
|
||||||
|
• IP Address: Server IP (e.g., 10.76.152.164)
|
||||||
|
• Port: HTTPS port (default 443)
|
||||||
|
• Enable/Disable toggle
|
||||||
|
|
||||||
|
✅ SECURITY
|
||||||
|
• Admin-only access with permission checks
|
||||||
|
• Input validation (domain, IP, port)
|
||||||
|
• Admin audit trail (who changed what, when)
|
||||||
|
• Server-side validation
|
||||||
|
• Logged in system logs
|
||||||
|
|
||||||
|
✅ VALIDATION
|
||||||
|
• Domain format validation
|
||||||
|
• IPv4 address validation (0-255 range)
|
||||||
|
• Port range validation (1-65535)
|
||||||
|
• Required field checks
|
||||||
|
• User-friendly error messages
|
||||||
|
|
||||||
|
✅ LOGGING
|
||||||
|
• All configuration changes logged
|
||||||
|
• Admin username recorded
|
||||||
|
• Timestamps for all changes
|
||||||
|
• Searchable in admin dashboard
|
||||||
|
|
||||||
|
✅ INTEGRATION
|
||||||
|
• Works with existing Caddy reverse proxy
|
||||||
|
• Automatic Let's Encrypt SSL certificates
|
||||||
|
• No manual certificate management
|
||||||
|
• Automatic certificate renewal
|
||||||
|
• HTTP/HTTPS dual access
|
||||||
|
|
||||||
|
═══════════════════════════════════════════════════════════════════════════════
|
||||||
|
|
||||||
|
🚀 QUICK START (5 Minutes)
|
||||||
|
═══════════════════════════════════════════════════════════════════════════════
|
||||||
|
|
||||||
|
1️⃣ RUN DATABASE MIGRATION
|
||||||
|
┌─ Option A: Automated
|
||||||
|
│ bash setup_https.sh
|
||||||
|
│
|
||||||
|
└─ Option B: Manual
|
||||||
|
python /app/migrations/add_https_config_table.py
|
||||||
|
|
||||||
|
2️⃣ START APPLICATION
|
||||||
|
docker-compose up -d
|
||||||
|
|
||||||
|
3️⃣ LOG IN AS ADMIN
|
||||||
|
• Navigate to admin panel
|
||||||
|
• Use admin credentials
|
||||||
|
|
||||||
|
4️⃣ CONFIGURE HTTPS
|
||||||
|
• Go to: Admin Panel → 🔒 HTTPS Configuration
|
||||||
|
• Toggle: Enable HTTPS ✅
|
||||||
|
• Fill in:
|
||||||
|
- Hostname: digiserver
|
||||||
|
- Domain: digiserver.sibiusb.harting.intra
|
||||||
|
- IP: 10.76.152.164
|
||||||
|
- Port: 443
|
||||||
|
• Click: Save HTTPS Configuration
|
||||||
|
|
||||||
|
5️⃣ VERIFY
|
||||||
|
• Check status shows "✅ HTTPS ENABLED"
|
||||||
|
• Access via: https://digiserver.sibiusb.harting.intra
|
||||||
|
• Fallback: http://10.76.152.164
|
||||||
|
|
||||||
|
═══════════════════════════════════════════════════════════════════════════════
|
||||||
|
|
||||||
|
📋 DATABASE SCHEMA
|
||||||
|
═══════════════════════════════════════════════════════════════════════════════
|
||||||
|
|
||||||
|
TABLE: https_config
|
||||||
|
┌─────────────────┬──────────────┬──────────────────────────────────────┐
|
||||||
|
│ Column │ Type │ Purpose │
|
||||||
|
├─────────────────┼──────────────┼──────────────────────────────────────┤
|
||||||
|
│ id │ INTEGER (PK) │ Primary key │
|
||||||
|
│ https_enabled │ BOOLEAN │ Enable/disable HTTPS │
|
||||||
|
│ hostname │ STRING(255) │ Server hostname (e.g., digiserver) │
|
||||||
|
│ domain │ STRING(255) │ Domain (e.g., domain.local) │
|
||||||
|
│ ip_address │ STRING(45) │ IP address (IPv4/IPv6) │
|
||||||
|
│ port │ INTEGER │ HTTPS port (default 443) │
|
||||||
|
│ created_at │ DATETIME │ Creation timestamp │
|
||||||
|
│ updated_at │ DATETIME │ Last update timestamp │
|
||||||
|
│ updated_by │ STRING(255) │ Admin who made change │
|
||||||
|
└─────────────────┴──────────────┴──────────────────────────────────────┘
|
||||||
|
|
||||||
|
═══════════════════════════════════════════════════════════════════════════════
|
||||||
|
|
||||||
|
🔐 SECURITY FEATURES
|
||||||
|
═══════════════════════════════════════════════════════════════════════════════
|
||||||
|
|
||||||
|
✅ Access Control
|
||||||
|
• Admin-only routes with @admin_required decorator
|
||||||
|
• Permission checks on all endpoints
|
||||||
|
• Login required for configuration access
|
||||||
|
|
||||||
|
✅ Input Validation
|
||||||
|
• Domain format validation
|
||||||
|
• IP address validation (IPv4/IPv6)
|
||||||
|
• Port range validation (1-65535)
|
||||||
|
• Required field validation
|
||||||
|
• Error messages for invalid inputs
|
||||||
|
|
||||||
|
✅ SSL/TLS Management
|
||||||
|
• Automatic Let's Encrypt certificates
|
||||||
|
• Automatic renewal before expiration
|
||||||
|
• Security headers (HSTS, X-Frame-Options, etc.)
|
||||||
|
• HTTP/2 and HTTP/3 support via Caddy
|
||||||
|
|
||||||
|
✅ Audit Trail
|
||||||
|
• All changes logged with timestamp
|
||||||
|
• Admin username recorded
|
||||||
|
• Enable/disable events tracked
|
||||||
|
• Searchable in server logs
|
||||||
|
|
||||||
|
═══════════════════════════════════════════════════════════════════════════════
|
||||||
|
|
||||||
|
🛠️ ADMIN COMMANDS
|
||||||
|
═══════════════════════════════════════════════════════════════════════════════
|
||||||
|
|
||||||
|
CLI UTILITY: https_manager.py
|
||||||
|
───────────────────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
Show Status:
|
||||||
|
python https_manager.py status
|
||||||
|
|
||||||
|
Enable HTTPS:
|
||||||
|
python https_manager.py enable digiserver digiserver.sibiusb.harting.intra 10.76.152.164 443
|
||||||
|
|
||||||
|
Disable HTTPS:
|
||||||
|
python https_manager.py disable
|
||||||
|
|
||||||
|
Show Configuration:
|
||||||
|
python https_manager.py show
|
||||||
|
|
||||||
|
═══════════════════════════════════════════════════════════════════════════════
|
||||||
|
|
||||||
|
📊 ACCESS POINTS
|
||||||
|
═══════════════════════════════════════════════════════════════════════════════
|
||||||
|
|
||||||
|
AFTER CONFIGURATION:
|
||||||
|
|
||||||
|
┌─ HTTPS (Recommended) ────────────────────────────────────────────┐
|
||||||
|
│ URL: https://digiserver.sibiusb.harting.intra │
|
||||||
|
│ Protocol: HTTPS (SSL/TLS) │
|
||||||
|
│ Port: 443 │
|
||||||
|
│ Certificate: Let's Encrypt (auto-renewed) │
|
||||||
|
│ Use: All secure connections, recommended for everyone │
|
||||||
|
└──────────────────────────────────────────────────────────────────┘
|
||||||
|
|
||||||
|
┌─ HTTP (Fallback) ────────────────────────────────────────────────┐
|
||||||
|
│ URL: http://10.76.152.164 │
|
||||||
|
│ Protocol: HTTP (plain text) │
|
||||||
|
│ Port: 80 │
|
||||||
|
│ Use: Troubleshooting, direct IP access, local network │
|
||||||
|
└──────────────────────────────────────────────────────────────────┘
|
||||||
|
|
||||||
|
═══════════════════════════════════════════════════════════════════════════════
|
||||||
|
|
||||||
|
📚 DOCUMENTATION FILES
|
||||||
|
═══════════════════════════════════════════════════════════════════════════════
|
||||||
|
|
||||||
|
1. HTTPS_QUICK_REFERENCE.md
|
||||||
|
• Quick setup guide (5 minutes)
|
||||||
|
• Admin checklist
|
||||||
|
• Common tasks
|
||||||
|
• Troubleshooting basics
|
||||||
|
• STATUS: ⭐ START HERE!
|
||||||
|
|
||||||
|
2. HTTPS_CONFIGURATION.md
|
||||||
|
• Comprehensive feature guide
|
||||||
|
• Step-by-step workflow
|
||||||
|
• Configuration details
|
||||||
|
• Prerequisites and requirements
|
||||||
|
• Integration overview
|
||||||
|
• Troubleshooting guide
|
||||||
|
• STATUS: For detailed reference
|
||||||
|
|
||||||
|
3. HTTPS_IMPLEMENTATION_SUMMARY.md
|
||||||
|
• Architecture and design
|
||||||
|
• Files created/modified
|
||||||
|
• Database schema
|
||||||
|
• Integration details
|
||||||
|
• Implementation checklist
|
||||||
|
• STATUS: For developers
|
||||||
|
|
||||||
|
═══════════════════════════════════════════════════════════════════════════════
|
||||||
|
|
||||||
|
✅ WORKFLOW
|
||||||
|
═══════════════════════════════════════════════════════════════════════════════
|
||||||
|
|
||||||
|
INITIAL STATE (HTTP ONLY)
|
||||||
|
┌─────────────────────┐
|
||||||
|
│ App on Port 80 │
|
||||||
|
│ HTTP only │
|
||||||
|
└────────┬────────────┘
|
||||||
|
│
|
||||||
|
└─ Accessible at: http://10.76.152.164
|
||||||
|
|
||||||
|
USER CONFIGURES HTTPS
|
||||||
|
┌─────────────────────────────────────────────┐
|
||||||
|
│ Admin Sets: │
|
||||||
|
│ • Hostname: digiserver │
|
||||||
|
│ • Domain: digiserver.sibiusb.harting.intra │
|
||||||
|
│ • IP: 10.76.152.164 │
|
||||||
|
│ • Port: 443 │
|
||||||
|
└────────┬────────────────────────────────────┘
|
||||||
|
│
|
||||||
|
↓
|
||||||
|
CONFIGURATION SAVED
|
||||||
|
┌──────────────────────────────────────────────┐
|
||||||
|
│ • Settings stored in database │
|
||||||
|
│ • Change logged with admin name & timestamp │
|
||||||
|
│ • Status updated in admin panel │
|
||||||
|
└────────┬─────────────────────────────────────┘
|
||||||
|
│
|
||||||
|
↓
|
||||||
|
SYSTEM OPERATIONAL
|
||||||
|
├─ HTTPS Active (Port 443)
|
||||||
|
│ URL: https://digiserver.sibiusb.harting.intra
|
||||||
|
│ Certificate: Auto-managed by Let's Encrypt
|
||||||
|
│
|
||||||
|
└─ HTTP Fallback (Port 80)
|
||||||
|
URL: http://10.76.152.164
|
||||||
|
For troubleshooting and backup access
|
||||||
|
|
||||||
|
═══════════════════════════════════════════════════════════════════════════════
|
||||||
|
|
||||||
|
✨ HIGHLIGHTS
|
||||||
|
═══════════════════════════════════════════════════════════════════════════════
|
||||||
|
|
||||||
|
🎯 USER EXPERIENCE
|
||||||
|
• No manual configuration needed
|
||||||
|
• Simple toggle to enable/disable
|
||||||
|
• Real-time preview of settings
|
||||||
|
• Status display shows current state
|
||||||
|
• Mobile-responsive interface
|
||||||
|
|
||||||
|
🔒 SECURITY
|
||||||
|
• Admin-only access
|
||||||
|
• Input validation on all fields
|
||||||
|
• Audit trail of all changes
|
||||||
|
• Automatic SSL certificates
|
||||||
|
• No sensitive data stored in plain text
|
||||||
|
|
||||||
|
⚙️ FLEXIBILITY
|
||||||
|
• Configurable hostname, domain, IP
|
||||||
|
• Custom port support
|
||||||
|
• Enable/disable without data loss
|
||||||
|
• CLI and web interface both available
|
||||||
|
• Works with existing Caddy setup
|
||||||
|
|
||||||
|
📊 MONITORING
|
||||||
|
• Status endpoint for integration
|
||||||
|
• Logged changes in server logs
|
||||||
|
• Admin dashboard status display
|
||||||
|
• CLI status command
|
||||||
|
|
||||||
|
🚀 AUTOMATION
|
||||||
|
• CLI interface for scripting
|
||||||
|
• Can be automated via setup scripts
|
||||||
|
• Supports headless configuration
|
||||||
|
• REST API endpoint for status
|
||||||
|
|
||||||
|
═══════════════════════════════════════════════════════════════════════════════
|
||||||
|
|
||||||
|
📋 CHECKLIST
|
||||||
|
═══════════════════════════════════════════════════════════════════════════════
|
||||||
|
|
||||||
|
IMPLEMENTATION
|
||||||
|
✅ Database model created (https_config.py)
|
||||||
|
✅ Admin routes added (3 new endpoints)
|
||||||
|
✅ Admin template created (https_config.html)
|
||||||
|
✅ Dashboard card added
|
||||||
|
✅ Database migration created
|
||||||
|
✅ CLI utility implemented
|
||||||
|
✅ Setup script created
|
||||||
|
✅ Documentation completed (3 guides)
|
||||||
|
✅ Code integrated with existing system
|
||||||
|
✅ Admin-only access enforced
|
||||||
|
✅ Input validation implemented
|
||||||
|
✅ Logging implemented
|
||||||
|
✅ Error handling added
|
||||||
|
|
||||||
|
DEPLOYMENT
|
||||||
|
⏳ Run database migration: python migrations/add_https_config_table.py
|
||||||
|
⏳ Start application: docker-compose up -d
|
||||||
|
⏳ Configure via admin panel
|
||||||
|
⏳ Verify access points
|
||||||
|
⏳ Check status display
|
||||||
|
⏳ Review logs for changes
|
||||||
|
|
||||||
|
═══════════════════════════════════════════════════════════════════════════════
|
||||||
|
|
||||||
|
🎉 SYSTEM READY
|
||||||
|
═══════════════════════════════════════════════════════════════════════════════
|
||||||
|
|
||||||
|
All files have been created and integrated.
|
||||||
|
The HTTPS configuration management system is complete and ready to use.
|
||||||
|
|
||||||
|
NEXT STEPS:
|
||||||
|
1. Run database migration
|
||||||
|
2. Restart application
|
||||||
|
3. Access admin panel
|
||||||
|
4. Navigate to HTTPS Configuration
|
||||||
|
5. Enable and configure HTTPS settings
|
||||||
|
6. Verify access points
|
||||||
|
|
||||||
|
For detailed instructions, see: HTTPS_QUICK_REFERENCE.md
|
||||||
|
|
||||||
|
═══════════════════════════════════════════════════════════════════════════════
|
||||||
@@ -1,487 +0,0 @@
|
|||||||
# 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
|
|
||||||
120
QUICK_START.md
Normal file
@@ -0,0 +1,120 @@
|
|||||||
|
# 🚀 DigiServer Deployment - Quick Reference Card
|
||||||
|
|
||||||
|
## Instant Deployment
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd /path/to/digiserver-v2
|
||||||
|
./deploy.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
That's it! ✅
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📖 Documentation Files
|
||||||
|
|
||||||
|
| File | Purpose | Size |
|
||||||
|
|------|---------|------|
|
||||||
|
| [DEPLOYMENT_INDEX.md](DEPLOYMENT_INDEX.md) | Navigation guide | 8.1 KB |
|
||||||
|
| [DEPLOYMENT_README.md](DEPLOYMENT_README.md) | Complete guide | 9.4 KB |
|
||||||
|
| [DOCKER_EXEC_COMMANDS.md](DOCKER_EXEC_COMMANDS.md) | Command reference | 7.6 KB |
|
||||||
|
| [DEPLOYMENT_COMMANDS.md](DEPLOYMENT_COMMANDS.md) | Detailed guide | 6.8 KB |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🔧 Executable Scripts
|
||||||
|
|
||||||
|
| Script | Purpose | Time |
|
||||||
|
|--------|---------|------|
|
||||||
|
| [deploy.sh](deploy.sh) | Fully automated | 2-3 min |
|
||||||
|
| [setup_https.sh](setup_https.sh) | Semi-automated | 3-5 min |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🎯 Common Commands
|
||||||
|
|
||||||
|
### Check Status
|
||||||
|
```bash
|
||||||
|
docker-compose ps
|
||||||
|
```
|
||||||
|
|
||||||
|
### View Logs
|
||||||
|
```bash
|
||||||
|
docker-compose logs -f digiserver-app
|
||||||
|
```
|
||||||
|
|
||||||
|
### Verify HTTPS Configuration
|
||||||
|
```bash
|
||||||
|
docker-compose exec -T digiserver-app python /app/https_manager.py status
|
||||||
|
```
|
||||||
|
|
||||||
|
### Access the Application
|
||||||
|
```
|
||||||
|
https://digiserver.sibiusb.harting.intra
|
||||||
|
https://10.76.152.164
|
||||||
|
https://digiserver
|
||||||
|
```
|
||||||
|
|
||||||
|
### Default Login
|
||||||
|
```
|
||||||
|
Username: admin
|
||||||
|
Password: admin123
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🆘 Troubleshooting
|
||||||
|
|
||||||
|
| Issue | Solution |
|
||||||
|
|-------|----------|
|
||||||
|
| Containers won't start | `docker-compose logs` |
|
||||||
|
| Migration fails | Check DB connection, see docs |
|
||||||
|
| HTTPS errors | Clear Caddy cache: `docker volume rm digiserver-v2_caddy-*` |
|
||||||
|
| Port conflict | `lsof -i :443` or change in docker-compose.yml |
|
||||||
|
|
||||||
|
See [DEPLOYMENT_README.md#-troubleshooting](DEPLOYMENT_README.md#-troubleshooting) for full guide.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🌍 Deploy on Different PC
|
||||||
|
|
||||||
|
1. Copy project files
|
||||||
|
2. Install Docker & Docker Compose
|
||||||
|
3. Run `./deploy.sh`
|
||||||
|
|
||||||
|
Done! 🎉
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🔑 Customize Deployment
|
||||||
|
|
||||||
|
```bash
|
||||||
|
HOSTNAME=myserver \
|
||||||
|
DOMAIN=myserver.internal \
|
||||||
|
IP_ADDRESS=192.168.1.100 \
|
||||||
|
EMAIL=admin@example.com \
|
||||||
|
./deploy.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📚 Need More Help?
|
||||||
|
|
||||||
|
- **First time?** → [DEPLOYMENT_README.md](DEPLOYMENT_README.md)
|
||||||
|
- **Need a command?** → [DOCKER_EXEC_COMMANDS.md](DOCKER_EXEC_COMMANDS.md)
|
||||||
|
- **Lost?** → [DEPLOYMENT_INDEX.md](DEPLOYMENT_INDEX.md)
|
||||||
|
- **Troubleshooting?** → [DEPLOYMENT_README.md#-troubleshooting](DEPLOYMENT_README.md#-troubleshooting)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## ✨ What You Get
|
||||||
|
|
||||||
|
✅ Web application with admin dashboard
|
||||||
|
✅ HTTPS with self-signed certificates
|
||||||
|
✅ User management system
|
||||||
|
✅ Player & content management
|
||||||
|
✅ Fully configured & ready to use
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Ready to deploy?** `./deploy.sh` 🚀
|
||||||
5
app/app.py
Normal file → Executable file
@@ -4,7 +4,6 @@ Modern Flask application with blueprint architecture
|
|||||||
"""
|
"""
|
||||||
import os
|
import os
|
||||||
from flask import Flask, render_template
|
from flask import Flask, render_template
|
||||||
from werkzeug.middleware.proxy_fix import ProxyFix
|
|
||||||
from dotenv import load_dotenv
|
from dotenv import load_dotenv
|
||||||
|
|
||||||
from app.config import DevelopmentConfig, ProductionConfig, TestingConfig
|
from app.config import DevelopmentConfig, ProductionConfig, TestingConfig
|
||||||
@@ -38,10 +37,6 @@ def create_app(config_name=None):
|
|||||||
|
|
||||||
app.config.from_object(config)
|
app.config.from_object(config)
|
||||||
|
|
||||||
# Apply ProxyFix middleware for reverse proxy (Nginx/Caddy)
|
|
||||||
# This ensures proper handling of X-Forwarded-* headers
|
|
||||||
app.wsgi_app = ProxyFix(app.wsgi_app, x_for=1, x_proto=1, x_host=1, x_port=1)
|
|
||||||
|
|
||||||
# Initialize extensions
|
# Initialize extensions
|
||||||
db.init_app(app)
|
db.init_app(app)
|
||||||
bcrypt.init_app(app)
|
bcrypt.init_app(app)
|
||||||
|
|||||||
0
app/blueprints/__init__.py
Normal file → Executable file
@@ -11,7 +11,6 @@ from app.extensions import db, bcrypt
|
|||||||
from app.models import User, Player, Group, Content, ServerLog, Playlist, HTTPSConfig
|
from app.models import User, Player, Group, Content, ServerLog, Playlist, HTTPSConfig
|
||||||
from app.utils.logger import log_action
|
from app.utils.logger import log_action
|
||||||
from app.utils.caddy_manager import CaddyConfigGenerator
|
from app.utils.caddy_manager import CaddyConfigGenerator
|
||||||
from app.utils.nginx_config_reader import get_nginx_status
|
|
||||||
|
|
||||||
admin_bp = Blueprint('admin', __name__, url_prefix='/admin')
|
admin_bp = Blueprint('admin', __name__, url_prefix='/admin')
|
||||||
|
|
||||||
@@ -871,14 +870,10 @@ def https_config():
|
|||||||
db.session.commit()
|
db.session.commit()
|
||||||
log_action('info', f'HTTPS status auto-corrected to enabled (detected from request)')
|
log_action('info', f'HTTPS status auto-corrected to enabled (detected from request)')
|
||||||
|
|
||||||
# Get Nginx configuration status
|
|
||||||
nginx_status = get_nginx_status()
|
|
||||||
|
|
||||||
return render_template('admin/https_config.html',
|
return render_template('admin/https_config.html',
|
||||||
config=config,
|
config=config,
|
||||||
is_https_active=is_https_active,
|
is_https_active=is_https_active,
|
||||||
current_host=current_host,
|
current_host=current_host)
|
||||||
nginx_status=nginx_status)
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
log_action('error', f'Error loading HTTPS config page: {str(e)}')
|
log_action('error', f'Error loading HTTPS config page: {str(e)}')
|
||||||
flash('Error loading HTTPS configuration page.', 'danger')
|
flash('Error loading HTTPS configuration page.', 'danger')
|
||||||
|
|||||||
0
app/blueprints/api.py
Normal file → Executable file
0
app/blueprints/auth.py
Normal file → Executable file
0
app/blueprints/content.py
Normal file → Executable file
0
app/blueprints/content_old.py
Normal file → Executable file
0
app/blueprints/groups.py
Normal file → Executable file
0
app/blueprints/main.py
Normal file → Executable file
0
app/blueprints/players.py
Normal file → Executable file
0
app/blueprints/playlist.py
Normal file → Executable file
5
app/config.py
Normal file → Executable file
@@ -29,11 +29,6 @@ class Config:
|
|||||||
SESSION_COOKIE_HTTPONLY = True
|
SESSION_COOKIE_HTTPONLY = True
|
||||||
SESSION_COOKIE_SAMESITE = 'Lax'
|
SESSION_COOKIE_SAMESITE = 'Lax'
|
||||||
|
|
||||||
# Reverse proxy trust (for Nginx/Caddy with ProxyFix middleware)
|
|
||||||
# These are set by werkzeug.middleware.proxy_fix
|
|
||||||
TRUSTED_PROXIES = os.getenv('TRUSTED_PROXIES', '127.0.0.1,10.0.0.0/8,172.16.0.0/12,192.168.0.0/16')
|
|
||||||
PREFERRED_URL_SCHEME = os.getenv('PREFERRED_URL_SCHEME', 'https')
|
|
||||||
|
|
||||||
# Cache
|
# Cache
|
||||||
SEND_FILE_MAX_AGE_DEFAULT = 300 # 5 minutes for static files
|
SEND_FILE_MAX_AGE_DEFAULT = 300 # 5 minutes for static files
|
||||||
|
|
||||||
|
|||||||
0
app/extensions.py
Normal file → Executable file
0
app/models/__init__.py
Normal file → Executable file
0
app/models/content.py
Normal file → Executable file
0
app/models/group.py
Normal file → Executable file
0
app/models/player.py
Normal file → Executable file
0
app/models/player_edit.py
Normal file → Executable file
0
app/models/player_feedback.py
Normal file → Executable file
0
app/models/player_user.py
Normal file → Executable file
0
app/models/playlist.py
Normal file → Executable file
0
app/models/server_log.py
Normal file → Executable file
0
app/models/user.py
Normal file → Executable file
0
app/static/icons/edit.svg
Normal file → Executable file
|
Before Width: | Height: | Size: 294 B After Width: | Height: | Size: 294 B |
0
app/static/icons/home.svg
Normal file → Executable file
|
Before Width: | Height: | Size: 311 B After Width: | Height: | Size: 311 B |
0
app/static/icons/info.svg
Normal file → Executable file
|
Before Width: | Height: | Size: 329 B After Width: | Height: | Size: 329 B |
0
app/static/icons/monitor.svg
Normal file → Executable file
|
Before Width: | Height: | Size: 301 B After Width: | Height: | Size: 301 B |
0
app/static/icons/moon.svg
Normal file → Executable file
|
Before Width: | Height: | Size: 257 B After Width: | Height: | Size: 257 B |
0
app/static/icons/playlist.svg
Normal file → Executable file
|
Before Width: | Height: | Size: 259 B After Width: | Height: | Size: 259 B |
0
app/static/icons/sun.svg
Normal file → Executable file
|
Before Width: | Height: | Size: 651 B After Width: | Height: | Size: 651 B |
0
app/static/icons/trash.svg
Normal file → Executable file
|
Before Width: | Height: | Size: 334 B After Width: | Height: | Size: 334 B |
0
app/static/icons/upload.svg
Normal file → Executable file
|
Before Width: | Height: | Size: 345 B After Width: | Height: | Size: 345 B |
0
app/static/icons/warning.svg
Normal file → Executable file
|
Before Width: | Height: | Size: 396 B After Width: | Height: | Size: 396 B |
0
app/static/uploads/.gitkeep
Normal file → Executable file
0
app/templates/admin/admin.html
Normal file → Executable file
0
app/templates/admin/customize_logos.html
Normal file → Executable file
0
app/templates/admin/dependencies.html
Normal file → Executable file
0
app/templates/admin/editing_users.html
Normal file → Executable file
@@ -160,95 +160,6 @@
|
|||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Nginx Status Card -->
|
|
||||||
<div class="card nginx-status-card">
|
|
||||||
<h2>🔧 Nginx Reverse Proxy Status</h2>
|
|
||||||
{% if nginx_status.available %}
|
|
||||||
<div class="nginx-status-content">
|
|
||||||
<div class="status-item">
|
|
||||||
<strong>Status:</strong>
|
|
||||||
<span class="badge badge-success">✅ Nginx Configured</span>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="status-item">
|
|
||||||
<strong>Configuration Path:</strong>
|
|
||||||
<code>{{ nginx_status.path }}</code>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{% if nginx_status.ssl_enabled %}
|
|
||||||
<div class="status-item">
|
|
||||||
<strong>SSL/TLS:</strong>
|
|
||||||
<span class="badge badge-success">🔒 Enabled</span>
|
|
||||||
</div>
|
|
||||||
{% else %}
|
|
||||||
<div class="status-item">
|
|
||||||
<strong>SSL/TLS:</strong>
|
|
||||||
<span class="badge badge-warning">⚠️ Not Configured</span>
|
|
||||||
</div>
|
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
{% if nginx_status.http_ports %}
|
|
||||||
<div class="status-item">
|
|
||||||
<strong>HTTP Ports:</strong>
|
|
||||||
<code>{{ nginx_status.http_ports|join(', ') }}</code>
|
|
||||||
</div>
|
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
{% if nginx_status.https_ports %}
|
|
||||||
<div class="status-item">
|
|
||||||
<strong>HTTPS Ports:</strong>
|
|
||||||
<code>{{ nginx_status.https_ports|join(', ') }}</code>
|
|
||||||
</div>
|
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
{% if nginx_status.server_names %}
|
|
||||||
<div class="status-item">
|
|
||||||
<strong>Server Names:</strong>
|
|
||||||
{% for name in nginx_status.server_names %}
|
|
||||||
<code>{{ name }}</code>{% if not loop.last %}<br>{% endif %}
|
|
||||||
{% endfor %}
|
|
||||||
</div>
|
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
{% if nginx_status.upstream_servers %}
|
|
||||||
<div class="status-item">
|
|
||||||
<strong>Upstream Servers:</strong>
|
|
||||||
{% for server in nginx_status.upstream_servers %}
|
|
||||||
<code>{{ server }}</code>{% if not loop.last %}<br>{% endif %}
|
|
||||||
{% endfor %}
|
|
||||||
</div>
|
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
{% if nginx_status.ssl_protocols %}
|
|
||||||
<div class="status-item">
|
|
||||||
<strong>SSL Protocols:</strong>
|
|
||||||
<code>{{ nginx_status.ssl_protocols|join(', ') }}</code>
|
|
||||||
</div>
|
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
{% if nginx_status.client_max_body_size %}
|
|
||||||
<div class="status-item">
|
|
||||||
<strong>Max Body Size:</strong>
|
|
||||||
<code>{{ nginx_status.client_max_body_size }}</code>
|
|
||||||
</div>
|
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
{% if nginx_status.gzip_enabled %}
|
|
||||||
<div class="status-item">
|
|
||||||
<strong>Gzip Compression:</strong>
|
|
||||||
<span class="badge badge-success">✅ Enabled</span>
|
|
||||||
</div>
|
|
||||||
{% endif %}
|
|
||||||
</div>
|
|
||||||
{% else %}
|
|
||||||
<div class="status-disabled">
|
|
||||||
<p>⚠️ <strong>Nginx configuration not accessible</strong></p>
|
|
||||||
<p>Error: {{ nginx_status.error|default('Unknown error') }}</p>
|
|
||||||
<p style="font-size: 12px; color: #666;">Path checked: {{ nginx_status.path }}</p>
|
|
||||||
</div>
|
|
||||||
{% endif %}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Information Section -->
|
<!-- Information Section -->
|
||||||
<div class="card info-card">
|
<div class="card info-card">
|
||||||
<h2>ℹ️ Important Information</h2>
|
<h2>ℹ️ Important Information</h2>
|
||||||
@@ -555,45 +466,6 @@
|
|||||||
color: #0066cc;
|
color: #0066cc;
|
||||||
}
|
}
|
||||||
|
|
||||||
.nginx-status-card {
|
|
||||||
background: linear-gradient(135deg, #f0f7ff 0%, #e7f3ff 100%);
|
|
||||||
border-left: 5px solid #0066cc;
|
|
||||||
margin-bottom: 30px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.nginx-status-card h2 {
|
|
||||||
color: #0066cc;
|
|
||||||
margin-top: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.nginx-status-content {
|
|
||||||
padding: 10px 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.status-item {
|
|
||||||
padding: 12px;
|
|
||||||
background: white;
|
|
||||||
border-radius: 4px;
|
|
||||||
margin-bottom: 10px;
|
|
||||||
border-left: 3px solid #0066cc;
|
|
||||||
font-size: 14px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.status-item strong {
|
|
||||||
display: inline-block;
|
|
||||||
min-width: 150px;
|
|
||||||
color: #333;
|
|
||||||
}
|
|
||||||
|
|
||||||
.status-item code {
|
|
||||||
background: #f0f7ff;
|
|
||||||
padding: 4px 8px;
|
|
||||||
border-radius: 3px;
|
|
||||||
font-family: 'Courier New', monospace;
|
|
||||||
color: #0066cc;
|
|
||||||
word-break: break-all;
|
|
||||||
}
|
|
||||||
|
|
||||||
.info-sections {
|
.info-sections {
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
|
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
|
||||||
|
|||||||
0
app/templates/admin/leftover_media.html
Normal file → Executable file
0
app/templates/admin/user_management.html
Normal file → Executable file
0
app/templates/auth/change_password.html
Normal file → Executable file
0
app/templates/auth/login.html
Normal file → Executable file
0
app/templates/auth/register.html
Normal file → Executable file
0
app/templates/base.html
Normal file → Executable file
0
app/templates/content/content_list.html
Normal file → Executable file
0
app/templates/content/content_list_new.html
Normal file → Executable file
0
app/templates/content/edit_content.html
Normal file → Executable file
0
app/templates/content/manage_playlist_content.html
Normal file → Executable file
0
app/templates/content/media_library.html
Normal file → Executable file
0
app/templates/content/upload_content.html
Normal file → Executable file
0
app/templates/content/upload_media.html
Normal file → Executable file
0
app/templates/dashboard.html
Normal file → Executable file
0
app/templates/errors/403.html
Normal file → Executable file
0
app/templates/errors/404.html
Normal file → Executable file
0
app/templates/errors/500.html
Normal file → Executable file
0
app/templates/groups/create_group.html
Normal file → Executable file
0
app/templates/groups/edit_group.html
Normal file → Executable file
0
app/templates/groups/group_fullscreen.html
Normal file → Executable file
0
app/templates/groups/groups_list.html
Normal file → Executable file
0
app/templates/groups/manage_group.html
Normal file → Executable file
0
app/templates/players/add_player.html
Normal file → Executable file
0
app/templates/players/edit_player.html
Normal file → Executable file
0
app/templates/players/edited_media.html
Normal file → Executable file
0
app/templates/players/manage_player.html
Normal file → Executable file
0
app/templates/players/player_fullscreen.html
Normal file → Executable file
0
app/templates/players/player_page.html
Normal file → Executable file
0
app/templates/players/players_list.html
Normal file → Executable file
0
app/templates/playlist/manage_playlist.html
Normal file → Executable file
0
app/utils/__init__.py
Normal file → Executable file
0
app/utils/group_player_management.py
Normal file → Executable file
0
app/utils/logger.py
Normal file → Executable file
@@ -1,120 +0,0 @@
|
|||||||
"""Nginx configuration reader utility."""
|
|
||||||
import os
|
|
||||||
import re
|
|
||||||
from typing import Dict, List, Optional, Any
|
|
||||||
|
|
||||||
|
|
||||||
class NginxConfigReader:
|
|
||||||
"""Read and parse Nginx configuration files."""
|
|
||||||
|
|
||||||
def __init__(self, config_path: str = '/etc/nginx/nginx.conf'):
|
|
||||||
"""Initialize Nginx config reader."""
|
|
||||||
self.config_path = config_path
|
|
||||||
self.config_content = None
|
|
||||||
self.is_available = os.path.exists(config_path)
|
|
||||||
|
|
||||||
if self.is_available:
|
|
||||||
try:
|
|
||||||
with open(config_path, 'r') as f:
|
|
||||||
self.config_content = f.read()
|
|
||||||
except Exception as e:
|
|
||||||
self.is_available = False
|
|
||||||
self.error = str(e)
|
|
||||||
|
|
||||||
def get_status(self) -> Dict[str, Any]:
|
|
||||||
"""Get Nginx configuration status."""
|
|
||||||
if not self.is_available:
|
|
||||||
return {
|
|
||||||
'available': False,
|
|
||||||
'error': 'Nginx configuration not found',
|
|
||||||
'path': self.config_path
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
'available': True,
|
|
||||||
'path': self.config_path,
|
|
||||||
'file_exists': os.path.exists(self.config_path),
|
|
||||||
'ssl_enabled': self._check_ssl_enabled(),
|
|
||||||
'http_ports': self._extract_http_ports(),
|
|
||||||
'https_ports': self._extract_https_ports(),
|
|
||||||
'upstream_servers': self._extract_upstream_servers(),
|
|
||||||
'server_names': self._extract_server_names(),
|
|
||||||
'ssl_protocols': self._extract_ssl_protocols(),
|
|
||||||
'client_max_body_size': self._extract_client_max_body_size(),
|
|
||||||
'gzip_enabled': self._check_gzip_enabled(),
|
|
||||||
}
|
|
||||||
|
|
||||||
def _check_ssl_enabled(self) -> bool:
|
|
||||||
"""Check if SSL is enabled."""
|
|
||||||
if not self.config_content:
|
|
||||||
return False
|
|
||||||
return 'ssl_certificate' in self.config_content
|
|
||||||
|
|
||||||
def _extract_http_ports(self) -> List[int]:
|
|
||||||
"""Extract HTTP listening ports."""
|
|
||||||
if not self.config_content:
|
|
||||||
return []
|
|
||||||
pattern = r'listen\s+(\d+)'
|
|
||||||
matches = re.findall(pattern, self.config_content)
|
|
||||||
return sorted(list(set(int(p) for p in matches if int(p) < 1000)))
|
|
||||||
|
|
||||||
def _extract_https_ports(self) -> List[int]:
|
|
||||||
"""Extract HTTPS listening ports."""
|
|
||||||
if not self.config_content:
|
|
||||||
return []
|
|
||||||
pattern = r'listen\s+(\d+).*ssl'
|
|
||||||
matches = re.findall(pattern, self.config_content)
|
|
||||||
return sorted(list(set(int(p) for p in matches)))
|
|
||||||
|
|
||||||
def _extract_upstream_servers(self) -> List[str]:
|
|
||||||
"""Extract upstream servers."""
|
|
||||||
if not self.config_content:
|
|
||||||
return []
|
|
||||||
upstream_match = re.search(r'upstream\s+\w+\s*{([^}]+)}', self.config_content)
|
|
||||||
if upstream_match:
|
|
||||||
upstream_content = upstream_match.group(1)
|
|
||||||
servers = re.findall(r'server\s+([^\s;]+)', upstream_content)
|
|
||||||
return servers
|
|
||||||
return []
|
|
||||||
|
|
||||||
def _extract_server_names(self) -> List[str]:
|
|
||||||
"""Extract server names."""
|
|
||||||
if not self.config_content:
|
|
||||||
return []
|
|
||||||
pattern = r'server_name\s+([^;]+);'
|
|
||||||
matches = re.findall(pattern, self.config_content)
|
|
||||||
result = []
|
|
||||||
for match in matches:
|
|
||||||
names = match.strip().split()
|
|
||||||
result.extend(names)
|
|
||||||
return result
|
|
||||||
|
|
||||||
def _extract_ssl_protocols(self) -> List[str]:
|
|
||||||
"""Extract SSL protocols."""
|
|
||||||
if not self.config_content:
|
|
||||||
return []
|
|
||||||
pattern = r'ssl_protocols\s+([^;]+);'
|
|
||||||
match = re.search(pattern, self.config_content)
|
|
||||||
if match:
|
|
||||||
return match.group(1).strip().split()
|
|
||||||
return []
|
|
||||||
|
|
||||||
def _extract_client_max_body_size(self) -> Optional[str]:
|
|
||||||
"""Extract client max body size."""
|
|
||||||
if not self.config_content:
|
|
||||||
return None
|
|
||||||
pattern = r'client_max_body_size\s+([^;]+);'
|
|
||||||
match = re.search(pattern, self.config_content)
|
|
||||||
return match.group(1).strip() if match else None
|
|
||||||
|
|
||||||
def _check_gzip_enabled(self) -> bool:
|
|
||||||
"""Check if gzip is enabled."""
|
|
||||||
if not self.config_content:
|
|
||||||
return False
|
|
||||||
return bool(re.search(r'gzip\s+on\s*;', self.config_content))
|
|
||||||
|
|
||||||
|
|
||||||
def get_nginx_status() -> Dict[str, Any]:
|
|
||||||
"""Get Nginx configuration status."""
|
|
||||||
reader = NginxConfigReader()
|
|
||||||
return reader.get_status()
|
|
||||||
0
app/utils/pptx_converter.py
Normal file → Executable file
0
app/utils/uploads.py
Normal file → Executable file
30
deploy.sh
@@ -16,10 +16,10 @@ echo -e "${BLUE}║ DigiServer Automated Deployment
|
|||||||
echo -e "${BLUE}╚════════════════════════════════════════════════════════════════╝${NC}"
|
echo -e "${BLUE}╚════════════════════════════════════════════════════════════════╝${NC}"
|
||||||
echo ""
|
echo ""
|
||||||
|
|
||||||
# Check if docker-compose is available
|
# Check if docker compose is available
|
||||||
if ! command -v docker-compose &> /dev/null; then
|
if ! docker compose version &> /dev/null; then
|
||||||
echo -e "${RED}❌ docker-compose not found!${NC}"
|
echo -e "${RED}❌ docker compose not found!${NC}"
|
||||||
echo "Please install docker-compose first"
|
echo "Please install docker compose first"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@@ -51,15 +51,15 @@ echo ""
|
|||||||
# STEP 1: Start containers
|
# STEP 1: Start containers
|
||||||
# ============================================================================
|
# ============================================================================
|
||||||
echo -e "${YELLOW}📦 [1/6] Starting containers...${NC}"
|
echo -e "${YELLOW}📦 [1/6] Starting containers...${NC}"
|
||||||
docker-compose up -d
|
docker compose up -d
|
||||||
|
|
||||||
echo -e "${YELLOW}⏳ Waiting for containers to be healthy...${NC}"
|
echo -e "${YELLOW}⏳ Waiting for containers to be healthy...${NC}"
|
||||||
sleep 10
|
sleep 10
|
||||||
|
|
||||||
# Verify containers are running
|
# Verify containers are running
|
||||||
if ! docker-compose ps | grep -q "Up"; then
|
if ! docker compose ps | grep -q "Up"; then
|
||||||
echo -e "${RED}❌ Containers failed to start!${NC}"
|
echo -e "${RED}❌ Containers failed to start!${NC}"
|
||||||
docker-compose logs
|
docker compose logs
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
echo -e "${GREEN}✅ Containers started successfully${NC}"
|
echo -e "${GREEN}✅ Containers started successfully${NC}"
|
||||||
@@ -71,13 +71,13 @@ echo ""
|
|||||||
echo -e "${YELLOW}📊 [2/6] Running database migrations...${NC}"
|
echo -e "${YELLOW}📊 [2/6] Running database migrations...${NC}"
|
||||||
|
|
||||||
echo -e " • Creating https_config table..."
|
echo -e " • Creating https_config table..."
|
||||||
docker-compose exec -T digiserver-app python /app/migrations/add_https_config_table.py
|
docker compose exec -T digiserver-app python /app/migrations/add_https_config_table.py
|
||||||
echo -e " • Creating player_user table..."
|
echo -e " • Creating player_user table..."
|
||||||
docker-compose exec -T digiserver-app python /app/migrations/add_player_user_table.py
|
docker compose exec -T digiserver-app python /app/migrations/add_player_user_table.py
|
||||||
echo -e " • Adding email to https_config..."
|
echo -e " • Adding email to https_config..."
|
||||||
docker-compose exec -T digiserver-app python /app/migrations/add_email_to_https_config.py
|
docker compose exec -T digiserver-app python /app/migrations/add_email_to_https_config.py
|
||||||
echo -e " • Migrating player_user global settings..."
|
echo -e " • Migrating player_user global settings..."
|
||||||
docker-compose exec -T digiserver-app python /app/migrations/migrate_player_user_global.py
|
docker compose exec -T digiserver-app python /app/migrations/migrate_player_user_global.py
|
||||||
|
|
||||||
echo -e "${GREEN}✅ All database migrations completed${NC}"
|
echo -e "${GREEN}✅ All database migrations completed${NC}"
|
||||||
echo ""
|
echo ""
|
||||||
@@ -87,7 +87,7 @@ echo ""
|
|||||||
# ============================================================================
|
# ============================================================================
|
||||||
echo -e "${YELLOW}🔒 [3/6] Configuring HTTPS...${NC}"
|
echo -e "${YELLOW}🔒 [3/6] Configuring HTTPS...${NC}"
|
||||||
|
|
||||||
docker-compose exec -T digiserver-app python /app/https_manager.py enable \
|
docker compose exec -T digiserver-app python /app/https_manager.py enable \
|
||||||
"$HOSTNAME" \
|
"$HOSTNAME" \
|
||||||
"$DOMAIN" \
|
"$DOMAIN" \
|
||||||
"$EMAIL" \
|
"$EMAIL" \
|
||||||
@@ -102,7 +102,7 @@ echo ""
|
|||||||
# ============================================================================
|
# ============================================================================
|
||||||
echo -e "${YELLOW}🔍 [4/6] Verifying database setup...${NC}"
|
echo -e "${YELLOW}🔍 [4/6] Verifying database setup...${NC}"
|
||||||
|
|
||||||
docker-compose exec -T digiserver-app python -c "
|
docker compose exec -T digiserver-app python -c "
|
||||||
from app.app import create_app
|
from app.app import create_app
|
||||||
from sqlalchemy import inspect
|
from sqlalchemy import inspect
|
||||||
|
|
||||||
@@ -123,7 +123,7 @@ echo ""
|
|||||||
# ============================================================================
|
# ============================================================================
|
||||||
echo -e "${YELLOW}🔧 [5/6] Verifying Caddy configuration...${NC}"
|
echo -e "${YELLOW}🔧 [5/6] Verifying Caddy configuration...${NC}"
|
||||||
|
|
||||||
docker-compose exec -T caddy caddy validate --config /etc/caddy/Caddyfile >/dev/null 2>&1
|
docker compose exec -T caddy caddy validate --config /etc/caddy/Caddyfile >/dev/null 2>&1
|
||||||
if [ $? -eq 0 ]; then
|
if [ $? -eq 0 ]; then
|
||||||
echo -e " ${GREEN}✅ Caddy configuration is valid${NC}"
|
echo -e " ${GREEN}✅ Caddy configuration is valid${NC}"
|
||||||
else
|
else
|
||||||
@@ -137,7 +137,7 @@ echo ""
|
|||||||
echo -e "${YELLOW}📋 [6/6] Displaying configuration summary...${NC}"
|
echo -e "${YELLOW}📋 [6/6] Displaying configuration summary...${NC}"
|
||||||
echo ""
|
echo ""
|
||||||
|
|
||||||
docker-compose exec -T digiserver-app python /app/https_manager.py status
|
docker compose exec -T digiserver-app python /app/https_manager.py status
|
||||||
|
|
||||||
echo ""
|
echo ""
|
||||||
echo -e "${GREEN}╔════════════════════════════════════════════════════════════════╗${NC}"
|
echo -e "${GREEN}╔════════════════════════════════════════════════════════════════╗${NC}"
|
||||||
|
|||||||
27
docker-compose.http.yml
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
version: '3.8'
|
||||||
|
|
||||||
|
services:
|
||||||
|
digiserver:
|
||||||
|
build: .
|
||||||
|
container_name: digiserver-v2-http
|
||||||
|
ports:
|
||||||
|
- "80:5000" # Direct HTTP exposure on port 80
|
||||||
|
volumes:
|
||||||
|
- ./instance:/app/instance
|
||||||
|
- ./app/static/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
|
||||||
|
|
||||||
|
# Usage: docker-compose -f docker-compose.http.yml up -d
|
||||||
|
# Access at: http://localhost or http://your-server-ip
|
||||||
|
# Note: This is for development/testing only. Use docker-compose.yml for production HTTPS.
|
||||||
24
docker-compose.yml
Normal file → Executable file
@@ -26,19 +26,19 @@ services:
|
|||||||
networks:
|
networks:
|
||||||
- digiserver-network
|
- digiserver-network
|
||||||
|
|
||||||
# Nginx reverse proxy with HTTPS support
|
# Caddy reverse proxy with automatic HTTPS
|
||||||
nginx:
|
caddy:
|
||||||
image: nginx:alpine
|
image: caddy:2-alpine
|
||||||
container_name: digiserver-nginx
|
container_name: digiserver-caddy
|
||||||
ports:
|
ports:
|
||||||
- "80:80"
|
- "80:80"
|
||||||
- "443:443"
|
- "443:443"
|
||||||
|
- "443:443/udp" # HTTP/3 support
|
||||||
|
- "2019:2019" # Caddy admin API
|
||||||
volumes:
|
volumes:
|
||||||
- ./nginx.conf:/etc/nginx/nginx.conf:ro
|
- ./data/Caddyfile:/etc/caddy/Caddyfile:ro
|
||||||
- ./nginx-custom-domains.conf:/etc/nginx/conf.d/custom-domains.conf:rw
|
- ./data/caddy-data:/data
|
||||||
- ./data/nginx-ssl:/etc/nginx/ssl:ro
|
- ./data/caddy-config:/config
|
||||||
- ./data/nginx-logs:/var/log/nginx
|
|
||||||
- ./data/certbot:/var/www/certbot:ro # For Let's Encrypt ACME challenges
|
|
||||||
environment:
|
environment:
|
||||||
- DOMAIN=${DOMAIN:-localhost}
|
- DOMAIN=${DOMAIN:-localhost}
|
||||||
- EMAIL=${EMAIL:-admin@localhost}
|
- EMAIL=${EMAIL:-admin@localhost}
|
||||||
@@ -46,12 +46,6 @@ services:
|
|||||||
digiserver-app:
|
digiserver-app:
|
||||||
condition: service_started
|
condition: service_started
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
healthcheck:
|
|
||||||
test: ["CMD", "wget", "--quiet", "--tries=1", "--spider", "http://localhost:80/"]
|
|
||||||
interval: 30s
|
|
||||||
timeout: 10s
|
|
||||||
retries: 3
|
|
||||||
start_period: 10s
|
|
||||||
networks:
|
networks:
|
||||||
- digiserver-network
|
- digiserver-network
|
||||||
|
|
||||||
|
|||||||
0
fix_player_user_schema.py
Normal file → Executable file
@@ -1,30 +0,0 @@
|
|||||||
#!/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"
|
|
||||||
157
https_manager.py
Normal file
@@ -0,0 +1,157 @@
|
|||||||
|
"""Utility script for managing HTTPS configuration from command line."""
|
||||||
|
import sys
|
||||||
|
import os
|
||||||
|
sys.path.insert(0, '/app')
|
||||||
|
|
||||||
|
from app.app import create_app
|
||||||
|
from app.models.https_config import HTTPSConfig
|
||||||
|
|
||||||
|
def show_help():
|
||||||
|
"""Display help information."""
|
||||||
|
print("""
|
||||||
|
HTTPS Configuration Management Utility
|
||||||
|
======================================
|
||||||
|
|
||||||
|
Usage:
|
||||||
|
python https_manager.py <command> [arguments]
|
||||||
|
|
||||||
|
Commands:
|
||||||
|
status Show current HTTPS configuration status
|
||||||
|
enable <hostname> <domain> <email> <ip> [port]
|
||||||
|
Enable HTTPS with specified settings
|
||||||
|
disable Disable HTTPS
|
||||||
|
show Show detailed configuration
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
# Show current status
|
||||||
|
python https_manager.py status
|
||||||
|
|
||||||
|
# Enable HTTPS
|
||||||
|
python https_manager.py enable digiserver digiserver.sibiusb.harting.intra admin@example.com 10.76.152.164 443
|
||||||
|
|
||||||
|
# Disable HTTPS
|
||||||
|
python https_manager.py disable
|
||||||
|
|
||||||
|
# Show detailed config
|
||||||
|
python https_manager.py show
|
||||||
|
""")
|
||||||
|
|
||||||
|
def show_status():
|
||||||
|
"""Show current HTTPS status."""
|
||||||
|
app = create_app()
|
||||||
|
with app.app_context():
|
||||||
|
config = HTTPSConfig.get_config()
|
||||||
|
if config:
|
||||||
|
print("\n" + "=" * 50)
|
||||||
|
print("HTTPS Configuration Status")
|
||||||
|
print("=" * 50)
|
||||||
|
print(f"Status: {'✅ ENABLED' if config.https_enabled else '⚠️ DISABLED'}")
|
||||||
|
print(f"Hostname: {config.hostname or 'N/A'}")
|
||||||
|
print(f"Domain: {config.domain or 'N/A'}")
|
||||||
|
print(f"IP Address: {config.ip_address or 'N/A'}")
|
||||||
|
print(f"Port: {config.port}")
|
||||||
|
print(f"Updated: {config.updated_at.strftime('%Y-%m-%d %H:%M:%S')} by {config.updated_by or 'N/A'}")
|
||||||
|
if config.https_enabled:
|
||||||
|
print(f"\nAccess URL: https://{config.domain}")
|
||||||
|
print(f"Fallback: http://{config.ip_address}")
|
||||||
|
print("=" * 50 + "\n")
|
||||||
|
else:
|
||||||
|
print("\n⚠️ No HTTPS configuration found. Use 'enable' command to create one.\n")
|
||||||
|
|
||||||
|
def enable_https(hostname: str, domain: str, ip_address: str, email: str, port: str = '443'):
|
||||||
|
"""Enable HTTPS with specified settings."""
|
||||||
|
app = create_app()
|
||||||
|
with app.app_context():
|
||||||
|
try:
|
||||||
|
port_num = int(port)
|
||||||
|
config = HTTPSConfig.create_or_update(
|
||||||
|
https_enabled=True,
|
||||||
|
hostname=hostname,
|
||||||
|
domain=domain,
|
||||||
|
ip_address=ip_address,
|
||||||
|
email=email,
|
||||||
|
port=port_num,
|
||||||
|
updated_by='cli_admin'
|
||||||
|
)
|
||||||
|
print("\n" + "=" * 50)
|
||||||
|
print("✅ HTTPS Configuration Updated")
|
||||||
|
print("=" * 50)
|
||||||
|
print(f"Hostname: {hostname}")
|
||||||
|
print(f"Domain: {domain}")
|
||||||
|
print(f"Email: {email}")
|
||||||
|
print(f"IP Address: {ip_address}")
|
||||||
|
print(f"Port: {port_num}")
|
||||||
|
print(f"\nAccess URL: https://{domain}")
|
||||||
|
print(f"Fallback: http://{ip_address}")
|
||||||
|
print("=" * 50 + "\n")
|
||||||
|
except Exception as e:
|
||||||
|
print(f"\n❌ Error: {str(e)}\n")
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
def disable_https():
|
||||||
|
"""Disable HTTPS."""
|
||||||
|
app = create_app()
|
||||||
|
with app.app_context():
|
||||||
|
try:
|
||||||
|
config = HTTPSConfig.create_or_update(
|
||||||
|
https_enabled=False,
|
||||||
|
updated_by='cli_admin'
|
||||||
|
)
|
||||||
|
print("\n" + "=" * 50)
|
||||||
|
print("⚠️ HTTPS Disabled")
|
||||||
|
print("=" * 50)
|
||||||
|
print("The application is now running on HTTP only (port 80)")
|
||||||
|
print("=" * 50 + "\n")
|
||||||
|
except Exception as e:
|
||||||
|
print(f"\n❌ Error: {str(e)}\n")
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
def show_config():
|
||||||
|
"""Show detailed configuration."""
|
||||||
|
app = create_app()
|
||||||
|
with app.app_context():
|
||||||
|
config = HTTPSConfig.get_config()
|
||||||
|
if config:
|
||||||
|
print("\n" + "=" * 50)
|
||||||
|
print("Detailed HTTPS Configuration")
|
||||||
|
print("=" * 50)
|
||||||
|
for key, value in config.to_dict().items():
|
||||||
|
print(f"{key:.<30} {value}")
|
||||||
|
print("=" * 50 + "\n")
|
||||||
|
else:
|
||||||
|
print("\n⚠️ No HTTPS configuration found.\n")
|
||||||
|
|
||||||
|
def main():
|
||||||
|
"""Main entry point."""
|
||||||
|
if len(sys.argv) < 2:
|
||||||
|
show_help()
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
command = sys.argv[1].lower()
|
||||||
|
|
||||||
|
if command == 'status':
|
||||||
|
show_status()
|
||||||
|
elif command == 'enable':
|
||||||
|
if len(sys.argv) < 6:
|
||||||
|
print("\nError: 'enable' requires: hostname domain email ip_address [port]\n")
|
||||||
|
show_help()
|
||||||
|
sys.exit(1)
|
||||||
|
hostname = sys.argv[2]
|
||||||
|
domain = sys.argv[3]
|
||||||
|
email = sys.argv[4]
|
||||||
|
ip_address = sys.argv[5]
|
||||||
|
port = sys.argv[6] if len(sys.argv) > 6 else '443'
|
||||||
|
enable_https(hostname, domain, ip_address, email, port)
|
||||||
|
elif command == 'disable':
|
||||||
|
disable_https()
|
||||||
|
elif command == 'show':
|
||||||
|
show_config()
|
||||||
|
elif command in ['help', '-h', '--help']:
|
||||||
|
show_help()
|
||||||
|
else:
|
||||||
|
print(f"\nUnknown command: {command}\n")
|
||||||
|
show_help()
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
main()
|
||||||
10
init-data.sh
@@ -4,7 +4,7 @@
|
|||||||
set -e
|
set -e
|
||||||
|
|
||||||
echo "🔧 Initializing data folder..."
|
echo "🔧 Initializing data folder..."
|
||||||
mkdir -p data/{app,instance,uploads}
|
mkdir -p data/{app,instance,uploads,caddy-data,caddy-config}
|
||||||
|
|
||||||
echo "📁 Copying app folder..."
|
echo "📁 Copying app folder..."
|
||||||
rm -rf data/app
|
rm -rf data/app
|
||||||
@@ -16,10 +16,14 @@ rm -rf data/migrations
|
|||||||
cp -r migrations data/
|
cp -r migrations data/
|
||||||
|
|
||||||
echo "🔧 Copying utility scripts..."
|
echo "🔧 Copying utility scripts..."
|
||||||
cp fix_player_user_schema.py data/
|
cp https_manager.py player_auth_module.py fix_player_user_schema.py data/
|
||||||
|
|
||||||
|
echo "📄 Copying Caddyfile..."
|
||||||
|
cp Caddyfile data/
|
||||||
|
|
||||||
echo "🔐 Setting permissions..."
|
echo "🔐 Setting permissions..."
|
||||||
chmod 755 data/{app,instance,uploads}
|
chmod 755 data/{app,instance,uploads,caddy-data,caddy-config}
|
||||||
|
chmod 644 data/Caddyfile
|
||||||
chmod -R 755 data/app/
|
chmod -R 755 data/app/
|
||||||
find data/app -type f \( -name "*.py" -o -name "*.html" -o -name "*.css" -o -name "*.js" \) -exec chmod 644 {} \;
|
find data/app -type f \( -name "*.py" -o -name "*.html" -o -name "*.css" -o -name "*.js" \) -exec chmod 644 {} \;
|
||||||
chmod 777 data/instance data/uploads
|
chmod 777 data/instance data/uploads
|
||||||
|
|||||||
0
migrations/add_player_user_table.py
Normal file → Executable file
0
migrations/migrate_player_user_global.py
Normal file → Executable file
@@ -1,21 +0,0 @@
|
|||||||
# 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;
|
|
||||||
# }
|
|
||||||
# }
|
|
||||||
117
nginx.conf
@@ -1,117 +0,0 @@
|
|||||||
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;
|
|
||||||
|
|
||||||
# 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;
|
|
||||||
|
|
||||||
# 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
old_code_documentation/.env.example
Normal file → Executable file
0
old_code_documentation/DOCKER.md
Normal file → Executable file
0
old_code_documentation/HTTPS_SETUP.md
Normal file → Executable file
0
old_code_documentation/IMPLEMENTATION_OPTIONAL_LIBREOFFICE.md
Normal file → Executable file
@@ -1,84 +0,0 @@
|
|||||||
# Quick Start: Nginx Setup for DigiServer v2
|
|
||||||
|
|
||||||
## Pre-requisites
|
|
||||||
- SSL certificates in `./data/nginx-ssl/cert.pem` and `./data/nginx-ssl/key.pem`
|
|
||||||
- Docker and Docker Compose installed
|
|
||||||
- Port 80 and 443 available
|
|
||||||
|
|
||||||
## Quick Setup (3 steps)
|
|
||||||
|
|
||||||
### 1. Generate Self-Signed Certificates
|
|
||||||
```bash
|
|
||||||
./generate_nginx_certs.sh localhost 365
|
|
||||||
```
|
|
||||||
|
|
||||||
### 2. Update Nginx Configuration
|
|
||||||
- Edit `nginx.conf` to set your domain:
|
|
||||||
```nginx
|
|
||||||
server_name localhost; # Change to your domain
|
|
||||||
```
|
|
||||||
|
|
||||||
### 3. Start Docker Compose
|
|
||||||
```bash
|
|
||||||
docker-compose up -d
|
|
||||||
```
|
|
||||||
|
|
||||||
## Verification
|
|
||||||
|
|
||||||
### Check if Nginx is running
|
|
||||||
```bash
|
|
||||||
docker ps | grep nginx
|
|
||||||
```
|
|
||||||
|
|
||||||
### Test HTTP → HTTPS redirect
|
|
||||||
```bash
|
|
||||||
curl -L http://localhost
|
|
||||||
```
|
|
||||||
|
|
||||||
### Test HTTPS (with self-signed cert)
|
|
||||||
```bash
|
|
||||||
curl -k https://localhost
|
|
||||||
```
|
|
||||||
|
|
||||||
### View logs
|
|
||||||
```bash
|
|
||||||
docker logs digiserver-nginx
|
|
||||||
docker exec digiserver-nginx tail -f /var/log/nginx/access.log
|
|
||||||
```
|
|
||||||
|
|
||||||
## Using Production Certificates
|
|
||||||
|
|
||||||
### Option A: Let's Encrypt (Free)
|
|
||||||
1. Install certbot: `apt-get install certbot`
|
|
||||||
2. Generate cert: `certbot certonly --standalone -d your-domain.com`
|
|
||||||
3. Copy cert: `cp /etc/letsencrypt/live/your-domain.com/fullchain.pem ./data/nginx-ssl/cert.pem`
|
|
||||||
4. Copy key: `cp /etc/letsencrypt/live/your-domain.com/privkey.pem ./data/nginx-ssl/key.pem`
|
|
||||||
5. Fix permissions: `sudo chown 101:101 ./data/nginx-ssl/*`
|
|
||||||
6. Reload: `docker exec digiserver-nginx nginx -s reload`
|
|
||||||
|
|
||||||
### Option B: Commercial Certificate
|
|
||||||
1. Place your certificate files in `./data/nginx-ssl/cert.pem` and `./data/nginx-ssl/key.pem`
|
|
||||||
2. Fix permissions: `sudo chown 101:101 ./data/nginx-ssl/*`
|
|
||||||
3. Reload: `docker exec digiserver-nginx nginx -s reload`
|
|
||||||
|
|
||||||
## Troubleshooting
|
|
||||||
|
|
||||||
| Issue | Solution |
|
|
||||||
|-------|----------|
|
|
||||||
| Port 80/443 in use | `sudo netstat -tlnp \| grep :80` or `:443` |
|
|
||||||
| Certificate permission denied | `sudo chown 101:101 ./data/nginx-ssl/*` |
|
|
||||||
| Nginx won't start | `docker logs digiserver-nginx` |
|
|
||||||
| Connection refused | Check firewall: `sudo ufw allow 80/tcp && sudo ufw allow 443/tcp` |
|
|
||||||
|
|
||||||
## File Locations
|
|
||||||
- Main config: `./nginx.conf`
|
|
||||||
- SSL certs: `./data/nginx-ssl/`
|
|
||||||
- Logs: `./data/nginx-logs/`
|
|
||||||
- Custom domains: `./nginx-custom-domains.conf` (auto-generated)
|
|
||||||
|
|
||||||
## Next: Production Setup
|
|
||||||
1. Update `.env` with your DOMAIN and EMAIL
|
|
||||||
2. Configure HTTPS settings in admin panel
|
|
||||||
3. Run: `python nginx_manager.py generate`
|
|
||||||
4. Test: `docker exec digiserver-nginx nginx -t`
|
|
||||||
5. Reload: `docker exec digiserver-nginx nginx -s reload`
|
|
||||||