Compare commits
5 Commits
bb293b6a81
...
cf44843418
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
cf44843418 | ||
|
|
a4262da7c9 | ||
|
|
024430754c | ||
|
|
d17ed79e29 | ||
|
|
21eb63659a |
4
.dockerignore
Executable file → Normal file
@@ -52,6 +52,4 @@ PLAYER_AUTH.md
|
||||
PROGRESS.md
|
||||
README.md
|
||||
|
||||
# Config templates
|
||||
player_config_template.ini
|
||||
player_auth_module.py
|
||||
|
||||
|
||||
0
.gitignore
vendored
Executable file → Normal file
73
Caddyfile
@@ -1,73 +0,0 @@
|
||||
{
|
||||
# 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
Executable file → Normal file
413
HTTPS_STATUS.txt
@@ -1,413 +0,0 @@
|
||||
╔═══════════════════════════════════════════════════════════════════════════════╗
|
||||
║ 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
|
||||
|
||||
═══════════════════════════════════════════════════════════════════════════════
|
||||
487
QUICK_DEPLOYMENT.md
Normal file
@@ -0,0 +1,487 @@
|
||||
# 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
@@ -1,120 +0,0 @@
|
||||
# 🚀 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
Executable file → Normal file
@@ -4,6 +4,7 @@ Modern Flask application with blueprint architecture
|
||||
"""
|
||||
import os
|
||||
from flask import Flask, render_template
|
||||
from werkzeug.middleware.proxy_fix import ProxyFix
|
||||
from dotenv import load_dotenv
|
||||
|
||||
from app.config import DevelopmentConfig, ProductionConfig, TestingConfig
|
||||
@@ -37,6 +38,10 @@ def create_app(config_name=None):
|
||||
|
||||
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
|
||||
db.init_app(app)
|
||||
bcrypt.init_app(app)
|
||||
|
||||
0
app/blueprints/__init__.py
Executable file → Normal file
@@ -11,6 +11,7 @@ from app.extensions import db, bcrypt
|
||||
from app.models import User, Player, Group, Content, ServerLog, Playlist, HTTPSConfig
|
||||
from app.utils.logger import log_action
|
||||
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')
|
||||
|
||||
@@ -870,10 +871,14 @@ def https_config():
|
||||
db.session.commit()
|
||||
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',
|
||||
config=config,
|
||||
is_https_active=is_https_active,
|
||||
current_host=current_host)
|
||||
current_host=current_host,
|
||||
nginx_status=nginx_status)
|
||||
except Exception as e:
|
||||
log_action('error', f'Error loading HTTPS config page: {str(e)}')
|
||||
flash('Error loading HTTPS configuration page.', 'danger')
|
||||
|
||||
0
app/blueprints/api.py
Executable file → Normal file
0
app/blueprints/auth.py
Executable file → Normal file
0
app/blueprints/content.py
Executable file → Normal file
0
app/blueprints/content_old.py
Executable file → Normal file
0
app/blueprints/groups.py
Executable file → Normal file
0
app/blueprints/main.py
Executable file → Normal file
0
app/blueprints/players.py
Executable file → Normal file
0
app/blueprints/playlist.py
Executable file → Normal file
5
app/config.py
Executable file → Normal file
@@ -29,6 +29,11 @@ class Config:
|
||||
SESSION_COOKIE_HTTPONLY = True
|
||||
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
|
||||
SEND_FILE_MAX_AGE_DEFAULT = 300 # 5 minutes for static files
|
||||
|
||||
|
||||
0
app/extensions.py
Executable file → Normal file
0
app/models/__init__.py
Executable file → Normal file
0
app/models/content.py
Executable file → Normal file
0
app/models/group.py
Executable file → Normal file
0
app/models/player.py
Executable file → Normal file
0
app/models/player_edit.py
Executable file → Normal file
0
app/models/player_feedback.py
Executable file → Normal file
0
app/models/player_user.py
Executable file → Normal file
0
app/models/playlist.py
Executable file → Normal file
0
app/models/server_log.py
Executable file → Normal file
0
app/models/user.py
Executable file → Normal file
0
app/static/icons/edit.svg
Executable file → Normal file
|
Before Width: | Height: | Size: 294 B After Width: | Height: | Size: 294 B |
0
app/static/icons/home.svg
Executable file → Normal file
|
Before Width: | Height: | Size: 311 B After Width: | Height: | Size: 311 B |
0
app/static/icons/info.svg
Executable file → Normal file
|
Before Width: | Height: | Size: 329 B After Width: | Height: | Size: 329 B |
0
app/static/icons/monitor.svg
Executable file → Normal file
|
Before Width: | Height: | Size: 301 B After Width: | Height: | Size: 301 B |
0
app/static/icons/moon.svg
Executable file → Normal file
|
Before Width: | Height: | Size: 257 B After Width: | Height: | Size: 257 B |
0
app/static/icons/playlist.svg
Executable file → Normal file
|
Before Width: | Height: | Size: 259 B After Width: | Height: | Size: 259 B |
0
app/static/icons/sun.svg
Executable file → Normal file
|
Before Width: | Height: | Size: 651 B After Width: | Height: | Size: 651 B |
0
app/static/icons/trash.svg
Executable file → Normal file
|
Before Width: | Height: | Size: 334 B After Width: | Height: | Size: 334 B |
0
app/static/icons/upload.svg
Executable file → Normal file
|
Before Width: | Height: | Size: 345 B After Width: | Height: | Size: 345 B |
0
app/static/icons/warning.svg
Executable file → Normal file
|
Before Width: | Height: | Size: 396 B After Width: | Height: | Size: 396 B |
0
app/static/uploads/.gitkeep
Executable file → Normal file
0
app/templates/admin/admin.html
Executable file → Normal file
0
app/templates/admin/customize_logos.html
Executable file → Normal file
0
app/templates/admin/dependencies.html
Executable file → Normal file
0
app/templates/admin/editing_users.html
Executable file → Normal file
@@ -160,6 +160,95 @@
|
||||
</form>
|
||||
</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 -->
|
||||
<div class="card info-card">
|
||||
<h2>ℹ️ Important Information</h2>
|
||||
@@ -466,6 +555,45 @@
|
||||
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 {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
|
||||
|
||||
0
app/templates/admin/leftover_media.html
Executable file → Normal file
0
app/templates/admin/user_management.html
Executable file → Normal file
0
app/templates/auth/change_password.html
Executable file → Normal file
0
app/templates/auth/login.html
Executable file → Normal file
0
app/templates/auth/register.html
Executable file → Normal file
0
app/templates/base.html
Executable file → Normal file
0
app/templates/content/content_list.html
Executable file → Normal file
0
app/templates/content/content_list_new.html
Executable file → Normal file
0
app/templates/content/edit_content.html
Executable file → Normal file
0
app/templates/content/manage_playlist_content.html
Executable file → Normal file
0
app/templates/content/media_library.html
Executable file → Normal file
0
app/templates/content/upload_content.html
Executable file → Normal file
0
app/templates/content/upload_media.html
Executable file → Normal file
0
app/templates/dashboard.html
Executable file → Normal file
0
app/templates/errors/403.html
Executable file → Normal file
0
app/templates/errors/404.html
Executable file → Normal file
0
app/templates/errors/500.html
Executable file → Normal file
0
app/templates/groups/create_group.html
Executable file → Normal file
0
app/templates/groups/edit_group.html
Executable file → Normal file
0
app/templates/groups/group_fullscreen.html
Executable file → Normal file
0
app/templates/groups/groups_list.html
Executable file → Normal file
0
app/templates/groups/manage_group.html
Executable file → Normal file
0
app/templates/players/add_player.html
Executable file → Normal file
0
app/templates/players/edit_player.html
Executable file → Normal file
0
app/templates/players/edited_media.html
Executable file → Normal file
0
app/templates/players/manage_player.html
Executable file → Normal file
0
app/templates/players/player_fullscreen.html
Executable file → Normal file
0
app/templates/players/player_page.html
Executable file → Normal file
0
app/templates/players/players_list.html
Executable file → Normal file
0
app/templates/playlist/manage_playlist.html
Executable file → Normal file
0
app/utils/__init__.py
Executable file → Normal file
0
app/utils/group_player_management.py
Executable file → Normal file
0
app/utils/logger.py
Executable file → Normal file
120
app/utils/nginx_config_reader.py
Normal file
@@ -0,0 +1,120 @@
|
||||
"""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
Executable file → Normal file
0
app/utils/uploads.py
Executable file → Normal file
@@ -1,27 +0,0 @@
|
||||
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
Executable file → Normal file
@@ -26,19 +26,19 @@ services:
|
||||
networks:
|
||||
- digiserver-network
|
||||
|
||||
# Caddy reverse proxy with automatic HTTPS
|
||||
caddy:
|
||||
image: caddy:2-alpine
|
||||
container_name: digiserver-caddy
|
||||
# Nginx reverse proxy with HTTPS support
|
||||
nginx:
|
||||
image: nginx:alpine
|
||||
container_name: digiserver-nginx
|
||||
ports:
|
||||
- "80:80"
|
||||
- "443:443"
|
||||
- "443:443/udp" # HTTP/3 support
|
||||
- "2019:2019" # Caddy admin API
|
||||
volumes:
|
||||
- ./data/Caddyfile:/etc/caddy/Caddyfile:ro
|
||||
- ./data/caddy-data:/data
|
||||
- ./data/caddy-config:/config
|
||||
- ./nginx.conf:/etc/nginx/nginx.conf:ro
|
||||
- ./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}
|
||||
@@ -46,6 +46,12 @@ services:
|
||||
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
|
||||
|
||||
|
||||
0
fix_player_user_schema.py
Executable file → Normal file
30
generate_nginx_certs.sh
Executable file
@@ -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"
|
||||
157
https_manager.py
@@ -1,157 +0,0 @@
|
||||
"""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
|
||||
|
||||
echo "🔧 Initializing data folder..."
|
||||
mkdir -p data/{app,instance,uploads,caddy-data,caddy-config}
|
||||
mkdir -p data/{app,instance,uploads}
|
||||
|
||||
echo "📁 Copying app folder..."
|
||||
rm -rf data/app
|
||||
@@ -16,14 +16,10 @@ rm -rf data/migrations
|
||||
cp -r migrations data/
|
||||
|
||||
echo "🔧 Copying utility scripts..."
|
||||
cp https_manager.py player_auth_module.py fix_player_user_schema.py data/
|
||||
|
||||
echo "📄 Copying Caddyfile..."
|
||||
cp Caddyfile data/
|
||||
cp fix_player_user_schema.py data/
|
||||
|
||||
echo "🔐 Setting permissions..."
|
||||
chmod 755 data/{app,instance,uploads,caddy-data,caddy-config}
|
||||
chmod 644 data/Caddyfile
|
||||
chmod 755 data/{app,instance,uploads}
|
||||
chmod -R 755 data/app/
|
||||
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
|
||||
|
||||
0
migrations/add_player_user_table.py
Executable file → Normal file
0
migrations/migrate_player_user_global.py
Executable file → Normal file
21
nginx-custom-domains.conf
Normal file
@@ -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;
|
||||
# }
|
||||
# }
|
||||
117
nginx.conf
Normal file
@@ -0,0 +1,117 @@
|
||||
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
Executable file → Normal file
0
old_code_documentation/DOCKER.md
Executable file → Normal file
0
old_code_documentation/HTTPS_SETUP.md
Executable file → Normal file
0
old_code_documentation/IMPLEMENTATION_OPTIONAL_LIBREOFFICE.md
Executable file → Normal file
84
old_code_documentation/NGINX_SETUP_QUICK.md
Normal file
@@ -0,0 +1,84 @@
|
||||
# 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`
|
||||