Rewrite QUICK_DEPLOYMENT.md for Caddy-based architecture
- Replace Nginx references throughout with Caddy - Update architecture diagram to show Caddy - Update container details (caddy:2-alpine, ports 8080/8443) - Update volume paths (caddy-data, caddy-config, caddy-logs) - Add rebuild guide for code changes (docker build + restart) - Add quick-test method (docker cp + pkill -HUP) - Simplify commands section (docker compose not docker-compose) - Remove Nginx-specific troubleshooting - Add Caddy validation and reload commands
This commit is contained in:
+186
-450
@@ -5,188 +5,156 @@
|
|||||||
DigiServer is deployed using Docker Compose with the following architecture:
|
DigiServer is deployed using Docker Compose with the following architecture:
|
||||||
|
|
||||||
```
|
```
|
||||||
Internet (User)
|
Internet (User) — Port 8080 (HTTP) / 8443 (HTTPS)
|
||||||
↓
|
↓
|
||||||
Nginx Reverse Proxy (Port 80/443)
|
Caddy Reverse Proxy (auto HTTPS, gzip, security headers)
|
||||||
↓
|
↓
|
||||||
Internal Docker Network
|
Internal Docker Network (digiserver-network)
|
||||||
↓
|
↓
|
||||||
Flask App (Gunicorn on Port 5000)
|
Flask App (Gunicorn on Port 5000)
|
||||||
↓
|
↓
|
||||||
SQLite Database
|
SQLite Database
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Caddy is used instead of Nginx because it:
|
||||||
|
- **Auto-provisions Let's Encrypt certificates** — no manual certbot
|
||||||
|
- **Simpler config** — a `Caddyfile` replaces the verbose `nginx.conf`
|
||||||
|
- **Built-in HTTP/2, gzip, security headers**
|
||||||
|
- **Admin API** (port 2019) — Flask reloads Caddy config dynamically
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 🚀 Complete Deployment Workflow
|
## 🚀 Quick Start
|
||||||
|
|
||||||
### **1️⃣ Clone & Setup**
|
### **1️⃣ Clone & Setup**
|
||||||
```bash
|
```bash
|
||||||
# Copy the app folder from repository
|
|
||||||
git clone <repository>
|
git clone <repository>
|
||||||
cd digiserver-v2
|
cd digiserver-v2
|
||||||
|
|
||||||
# Copy environment file and modify as needed
|
|
||||||
cp .env.example .env
|
|
||||||
|
|
||||||
# Edit .env with your configuration:
|
|
||||||
nano .env
|
|
||||||
```
|
```
|
||||||
|
|
||||||
**Configure in .env:**
|
### **2️⃣ Start Containers**
|
||||||
```env
|
|
||||||
SECRET_KEY=your-secret-key-change-this
|
|
||||||
ADMIN_USERNAME=admin
|
|
||||||
ADMIN_PASSWORD=your-secure-password
|
|
||||||
DOMAIN=your-domain.com
|
|
||||||
EMAIL=admin@your-domain.com
|
|
||||||
IP_ADDRESS=192.168.0.111
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### **2️⃣ Deploy via Script**
|
|
||||||
```bash
|
```bash
|
||||||
# Run the deployment script
|
docker compose up -d
|
||||||
./deploy.sh
|
|
||||||
```
|
```
|
||||||
|
|
||||||
This automatically:
|
This automatically:
|
||||||
1. ✅ Creates `data/` directories (instance, uploads, nginx-ssl, etc.)
|
1. ✅ Builds the Flask app image from `Dockerfile`
|
||||||
2. ✅ Copies nginx configs from repo root to `data/`
|
2. ✅ Creates persistent data directories (`data/instance`, `data/uploads`, etc.)
|
||||||
3. ✅ Starts Docker containers
|
3. ✅ Starts Caddy reverse proxy on ports **8080** (HTTP) and **8443** (HTTPS)
|
||||||
4. ✅ Initializes database
|
4. ✅ Initializes the database on first run (auto-creates admin user)
|
||||||
5. ✅ Runs all migrations
|
5. ✅ Runs all required migrations
|
||||||
6. ✅ Configures HTTPS with SSL certificates
|
|
||||||
7. ✅ Displays access information
|
|
||||||
|
|
||||||
**Output shows:**
|
**Access the app at:** `http://localhost:8080`
|
||||||
- Access URLs (HTTP/HTTPS)
|
|
||||||
- Default credentials
|
|
||||||
- Next steps for configuration
|
|
||||||
|
|
||||||
---
|
### **3️⃣ First-Time Login**
|
||||||
|
|
||||||
### **3️⃣ Network Migration (When Network Changes)**
|
|
||||||
|
|
||||||
When moving the server to a different network with a new IP:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Migrate to the new network IP
|
|
||||||
./migrate_network.sh 10.55.150.160
|
|
||||||
|
|
||||||
# Optional: with custom hostname
|
|
||||||
./migrate_network.sh 10.55.150.160 digiserver-secured
|
|
||||||
```
|
```
|
||||||
|
URL: http://localhost:8080
|
||||||
This automatically:
|
Username: admin
|
||||||
1. ✅ Regenerates SSL certificates for new IP
|
Password: admin123
|
||||||
2. ✅ Updates database HTTPS configuration
|
|
||||||
3. ✅ Restarts nginx and app containers
|
|
||||||
4. ✅ Verifies HTTPS connectivity
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### **4️⃣ Normal Operations**
|
|
||||||
|
|
||||||
**Restart containers:**
|
|
||||||
```bash
|
|
||||||
docker compose restart
|
|
||||||
```
|
|
||||||
|
|
||||||
**Stop containers:**
|
|
||||||
```bash
|
|
||||||
docker compose down
|
|
||||||
```
|
|
||||||
|
|
||||||
**View logs:**
|
|
||||||
```bash
|
|
||||||
docker compose logs -f
|
|
||||||
```
|
|
||||||
|
|
||||||
**View container status:**
|
|
||||||
```bash
|
|
||||||
docker compose ps
|
|
||||||
```
|
```
|
||||||
|
⚠️ **CHANGE PASSWORD IMMEDIATELY IN PRODUCTION!**
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 📦 Container Architecture
|
## 📦 Container Architecture
|
||||||
|
|
||||||
### **Container 1: digiserver-app (Flask)**
|
### **Container 1: digiserver-app (Flask)**
|
||||||
- **Image**: Built from Dockerfile (Python 3.13)
|
| Property | Value |
|
||||||
- **Port**: 5000 (internal only)
|
|----------|-------|
|
||||||
- **Volumes**:
|
| **Image** | Built from `Dockerfile` (Python 3.13-slim) |
|
||||||
- `./data:/app` - Persistent application data
|
| **Container name** | `digiserver-v2` |
|
||||||
- `./data/instance:/app/instance` - Database & configuration
|
| **Exposed port** | `5000` (internal — proxied by Caddy) |
|
||||||
- `./data/uploads:/app/app/static/uploads` - User uploads
|
| **Mapped port** | `5000:5000` (for direct dev access) |
|
||||||
- **Startup**: Automatically initializes database on first run
|
| **Entrypoint** | `docker-entrypoint.sh` (init DB → gunicorn) |
|
||||||
- **Health Check**: Every 30 seconds
|
| **Workers** | 4 gunicorn workers, 120s timeout |
|
||||||
|
|
||||||
### **Container 2: nginx (Reverse Proxy)**
|
**Volumes (persistent data):**
|
||||||
- **Image**: nginx:alpine
|
| Host path | Container path | Purpose |
|
||||||
- **Ports**: 80 & 443 (exposed to internet)
|
|-----------|---------------|---------|
|
||||||
- **Volumes**:
|
| `./data/instance` | `/app/instance` | SQLite database |
|
||||||
- `nginx.conf` - Main configuration
|
| `./data/uploads` | `/app/app/static/uploads` | Media uploads |
|
||||||
- `./data/nginx-ssl/` - SSL certificates
|
|
||||||
- `./data/nginx-logs/` - Access/error logs
|
> **Code is baked into the Docker image** — see [Rebuild](#-rebuild-after-code-changes) below.
|
||||||
- `./data/certbot/` - Let's Encrypt challenges
|
|
||||||
- **Startup**: Waits for Flask app to start
|
### **Container 2: caddy (Reverse Proxy)**
|
||||||
- **Health Check**: Every 30 seconds
|
| Property | Value |
|
||||||
|
|----------|-------|
|
||||||
|
| **Image** | `caddy:2-alpine` |
|
||||||
|
| **Container name** | `digiserver-caddy` |
|
||||||
|
| **HTTP** | `8080 → 80` (inside container) |
|
||||||
|
| **HTTPS** | `8443 → 443` (inside container) |
|
||||||
|
| **Admin API** | `2019` (internal, for dynamic reloads) |
|
||||||
|
|
||||||
|
**Volumes:**
|
||||||
|
| Host path | Container path | Purpose |
|
||||||
|
|-----------|---------------|---------|
|
||||||
|
| `./data/Caddyfile` | `/etc/caddy/Caddyfile:rw` | Caddy config (rewritable by Flask) |
|
||||||
|
| `./data/caddy-data` | `/data` | Let's Encrypt certs & keys |
|
||||||
|
| `./data/caddy-config` | `/config` | Caddy JSON config |
|
||||||
|
| `./data/caddy-logs` | `/var/log/caddy` | Access logs |
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 🔧 Deployment Steps Explained
|
## 🚀 Full Automated Deployment
|
||||||
|
|
||||||
### **Step 1: Start Containers**
|
|
||||||
```bash
|
```bash
|
||||||
docker-compose up -d
|
./deploy.sh
|
||||||
```
|
```
|
||||||
- Builds Flask app image (if needed)
|
|
||||||
- Starts both containers
|
This runs the complete workflow:
|
||||||
- Waits for containers to be healthy
|
1. Creates `data/` directories (`instance`, `uploads`, `caddy-*`)
|
||||||
|
2. Starts containers (`docker compose up -d`)
|
||||||
|
3. Initialises database and admin user
|
||||||
|
4. Runs all database migrations
|
||||||
|
5. Enables HTTPS via Flask Admin
|
||||||
|
6. Validates Caddy configuration
|
||||||
|
7. Prints access URLs and credentials
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🔧 Deployment Steps (Manual)
|
||||||
|
|
||||||
|
### **Step 1: Build & Start**
|
||||||
|
```bash
|
||||||
|
docker compose up -d
|
||||||
|
```
|
||||||
|
- Builds Flask app image (layer cached)
|
||||||
|
- Creates `digiserver-network` bridge
|
||||||
|
- Starts `digiserver-app`, then `caddy`
|
||||||
|
|
||||||
### **Step 2: Database Initialization** (docker-entrypoint.sh)
|
### **Step 2: Database Initialization** (docker-entrypoint.sh)
|
||||||
When Flask container starts:
|
On container start the entrypoint automatically:
|
||||||
1. Create required directories
|
1. Creates required directories
|
||||||
2. Check if database exists
|
2. Checks for existing `dashboard.db`
|
||||||
3. If NOT exists:
|
3. If absent — creates tables and seeds admin user
|
||||||
- Initialize SQLite database (dashboard.db)
|
4. Starts Gunicorn (4 workers, 120s timeout)
|
||||||
- Create admin user from environment variables
|
|
||||||
4. Start Gunicorn server (4 workers, 120s timeout)
|
|
||||||
|
|
||||||
### **Step 3: Run Migrations**
|
### **Step 3: Run Migrations**
|
||||||
```bash
|
```bash
|
||||||
docker-compose exec -T digiserver-app python /app/migrations/[migration_name].py
|
docker compose exec -T digiserver-app python /app/migrations/<name>.py
|
||||||
```
|
```
|
||||||
Applied migrations:
|
Key migrations:
|
||||||
- `add_https_config_table.py` - HTTPS settings
|
- `add_https_config_table.py` — HTTPS settings table
|
||||||
- `add_player_user_table.py` - Player user management
|
- `add_player_user_table.py` — Player user management
|
||||||
- `add_email_to_https_config.py` - Email configuration
|
- `add_email_to_https_config.py` — Email field
|
||||||
- `migrate_player_user_global.py` - Global settings
|
- `migrate_player_user_global.py` — Global settings
|
||||||
|
- `add_url_to_content.py` — Web link support
|
||||||
|
- `add_deployment_fields_to_player.py` — Deployment tracking
|
||||||
|
|
||||||
### **Step 4: Configure HTTPS**
|
### **Step 4: Configure HTTPS**
|
||||||
- SSL certificates stored in `./data/nginx-ssl/`
|
Via Admin UI (recommended):
|
||||||
- Pre-generated self-signed certs for development
|
1. Go to **Admin → HTTPS Config**
|
||||||
- Ready for Let's Encrypt integration
|
2. Enter hostname, domain, email, IP, port
|
||||||
|
3. Caddy auto-provisions a Let's Encrypt certificate
|
||||||
|
|
||||||
### **Step 5: Reverse Proxy Routing** (nginx.conf)
|
Via CLI:
|
||||||
```
|
```bash
|
||||||
HTTP (80):
|
docker compose exec -T digiserver-app python /app/https_manager.py enable \
|
||||||
• Redirect all traffic to HTTPS
|
<hostname> <domain> <email> <ip_address> <port>
|
||||||
• 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)
|
### **Step 5: ProxyFix Middleware** (app/app.py)
|
||||||
Extracts real client information from Nginx headers:
|
Flask extracts real client info from Caddy headers:
|
||||||
- `X-Forwarded-For` → Real client IP
|
- `X-Forwarded-For` → Real client IP
|
||||||
- `X-Forwarded-Proto` → Protocol (http/https)
|
- `X-Forwarded-Proto` → Protocol (http/https)
|
||||||
- `X-Forwarded-Host` → Original hostname
|
- `X-Forwarded-Host` → Original hostname
|
||||||
@@ -194,173 +162,118 @@ Extracts real client information from Nginx headers:
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 📂 Directory Structure & Persistence
|
## 🔄 Rebuild After Code Changes
|
||||||
|
|
||||||
```
|
Because the application code is baked into the Docker image, update it with:
|
||||||
/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
|
```bash
|
||||||
# Network Configuration
|
# 1. Rebuild the image
|
||||||
HOSTNAME=digiserver
|
docker build --no-cache -t digiserver-v2-digiserver-app .
|
||||||
DOMAIN=digiserver.example.com
|
|
||||||
IP_ADDRESS=192.168.0.121
|
|
||||||
|
|
||||||
# SSL/HTTPS
|
# 2. Replace the running container
|
||||||
EMAIL=admin@example.com
|
docker stop digiserver-v2 && docker rm digiserver-v2
|
||||||
|
docker compose up -d digiserver-app
|
||||||
# Flask Configuration
|
|
||||||
SECRET_KEY=your-secret-key-here
|
|
||||||
FLASK_ENV=production
|
|
||||||
|
|
||||||
# Admin User
|
|
||||||
ADMIN_USERNAME=admin
|
|
||||||
ADMIN_PASSWORD=admin123
|
|
||||||
```
|
```
|
||||||
|
|
||||||
Then start with:
|
**Quick test (no rebuild)** — copy files into the running container:
|
||||||
```bash
|
```bash
|
||||||
docker-compose up -d
|
docker cp <local_file> digiserver-v2:/app/<path>
|
||||||
|
docker exec digiserver-v2 pkill -HUP -f gunicorn
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🌐 Network Migration
|
||||||
|
|
||||||
|
When the server moves to a different network / IP:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./migrate_network.sh 10.55.150.160
|
||||||
|
# Optional: ./migrate_network.sh 10.55.150.160 digiserver-secured
|
||||||
|
```
|
||||||
|
|
||||||
|
This regenerates SSL certificates, updates the database HTTPS config, and restarts both containers.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📂 Directory Structure
|
||||||
|
|
||||||
|
```
|
||||||
|
digiserver-v2/
|
||||||
|
├── app/ (Flask application code)
|
||||||
|
│ ├── app.py (App factory)
|
||||||
|
│ ├── blueprints/ (Route definitions)
|
||||||
|
│ ├── models/ (SQLAlchemy models)
|
||||||
|
│ ├── templates/ (Jinja2 templates)
|
||||||
|
│ ├── static/uploads/ (Media files on disk)
|
||||||
|
│ └── utils/ (Helpers)
|
||||||
|
├── data/ (PERSISTENT — survives restarts)
|
||||||
|
│ ├── instance/dashboard.db (SQLite database)
|
||||||
|
│ ├── uploads/ (Media files)
|
||||||
|
│ ├── Caddyfile (Caddy config)
|
||||||
|
│ ├── caddy-data/ (Let's Encrypt certificates)
|
||||||
|
│ ├── caddy-config/ (Caddy JSON config)
|
||||||
|
│ └── caddy-logs/ (Access logs)
|
||||||
|
├── migrations/ (One-shot DB scripts)
|
||||||
|
├── old_code_documentation/ (Legacy Nginx files, etc.)
|
||||||
|
├── docker-compose.yml (Service definitions)
|
||||||
|
├── Dockerfile (Flask image build)
|
||||||
|
├── deploy.sh (Full automated deploy)
|
||||||
|
├── migrate_network.sh (Re-config after IP change)
|
||||||
|
└── docker-entrypoint.sh (Container startup)
|
||||||
```
|
```
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 🛠️ Common Commands
|
## 🛠️ Common Commands
|
||||||
|
|
||||||
### **Start/Stop Containers**
|
### **Containers**
|
||||||
```bash
|
```bash
|
||||||
# Start containers
|
docker compose up -d # Start all services
|
||||||
docker-compose up -d
|
docker compose down # Stop all services
|
||||||
|
docker compose restart # Restart all
|
||||||
# Stop containers
|
docker compose restart caddy # Restart only Caddy
|
||||||
docker-compose down
|
|
||||||
|
|
||||||
# Restart containers
|
|
||||||
docker-compose restart
|
|
||||||
|
|
||||||
# Restart specific container
|
|
||||||
docker-compose restart digiserver-app
|
|
||||||
docker-compose restart nginx
|
|
||||||
```
|
```
|
||||||
|
|
||||||
### **View Logs**
|
### **Logs**
|
||||||
```bash
|
```bash
|
||||||
# All containers
|
docker compose logs -f # Follow all
|
||||||
docker-compose logs
|
docker compose logs -f digiserver-app # Flask only
|
||||||
|
docker compose logs -f caddy # Caddy only
|
||||||
# Follow logs (real-time)
|
docker compose logs --tail=50 digiserver-app
|
||||||
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**
|
### **Status**
|
||||||
```bash
|
```bash
|
||||||
# Show running containers
|
docker compose ps
|
||||||
docker-compose ps
|
|
||||||
|
|
||||||
# Show container details
|
|
||||||
docker-compose ps -a
|
|
||||||
|
|
||||||
# Check container health
|
|
||||||
docker ps --format="table {{.Names}}\t{{.Status}}"
|
docker ps --format="table {{.Names}}\t{{.Status}}"
|
||||||
```
|
```
|
||||||
|
|
||||||
### **Database Operations**
|
### **Database**
|
||||||
```bash
|
```bash
|
||||||
# Access database shell
|
docker compose exec digiserver-app sqlite3 /app/instance/dashboard.db
|
||||||
docker-compose exec digiserver-app sqlite3 /app/instance/dashboard.db
|
docker compose exec digiserver-app cp /app/instance/dashboard.db \
|
||||||
|
/app/instance/dashboard.db.backup
|
||||||
# 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**
|
### **Caddy**
|
||||||
```bash
|
```bash
|
||||||
# Validate Nginx configuration
|
docker exec digiserver-caddy caddy validate --config /etc/caddy/Caddyfile
|
||||||
docker exec digiserver-nginx nginx -t
|
docker exec digiserver-caddy caddy reload --config /etc/caddy/Caddyfile
|
||||||
|
|
||||||
# Reload Nginx (without restart)
|
|
||||||
docker exec digiserver-nginx nginx -s reload
|
|
||||||
|
|
||||||
# View Nginx logs
|
|
||||||
docker-compose logs -f nginx
|
|
||||||
```
|
```
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 🔒 SSL Certificate Management
|
## 🔒 HTTPS / SSL
|
||||||
|
|
||||||
|
Caddy automatically provisions Let's Encrypt certificates when a public domain is configured. For development with self-signed certificates:
|
||||||
|
|
||||||
### **Generate New Self-Signed Certificate**
|
|
||||||
```bash
|
```bash
|
||||||
bash generate_nginx_certs.sh 192.168.0.121 365
|
bash generate_nginx_certs.sh 192.168.0.121 365
|
||||||
docker-compose restart nginx
|
docker compose restart caddy
|
||||||
```
|
```
|
||||||
|
|
||||||
Parameters:
|
> **Note:** `generate_nginx_certs.sh` has been moved to `old_code_documentation/` but still works.
|
||||||
- `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
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -368,197 +281,20 @@ Parameters:
|
|||||||
|
|
||||||
### **Containers not starting?**
|
### **Containers not starting?**
|
||||||
```bash
|
```bash
|
||||||
# Check docker-compose logs
|
docker compose logs
|
||||||
docker-compose logs
|
|
||||||
|
|
||||||
# Check system resources
|
|
||||||
docker stats
|
docker stats
|
||||||
|
|
||||||
# Restart Docker daemon
|
|
||||||
sudo systemctl restart docker
|
|
||||||
```
|
```
|
||||||
|
|
||||||
### **Application not responding?**
|
### **App not responding?**
|
||||||
```bash
|
```bash
|
||||||
# Check app container health
|
docker compose ps
|
||||||
docker-compose ps
|
curl http://localhost:5000/ # Bypass Caddy, hit Flask directly
|
||||||
|
docker compose logs -f digiserver-app
|
||||||
# View app logs
|
|
||||||
docker-compose logs -f digiserver-app
|
|
||||||
|
|
||||||
# Test Flask directly
|
|
||||||
docker-compose exec digiserver-app curl http://localhost:5000/
|
|
||||||
```
|
```
|
||||||
|
|
||||||
### **HTTPS not working?**
|
### **Caddy / HTTPS issues?**
|
||||||
```bash
|
```bash
|
||||||
# Verify Nginx config
|
docker exec digiserver-caddy caddy validate --config /etc/caddy/Caddyfile
|
||||||
docker exec digiserver-nginx nginx -t
|
ls -la ./data/caddy-data/certificates/
|
||||||
|
docker compose restart caddy
|
||||||
# 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
|
|
||||||
|
|||||||
Reference in New Issue
Block a user