Files
digiserver-v2/QUICK_DEPLOYMENT.md
T
ske087 052751b599 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
2026-07-21 10:09:26 +03:00

8.5 KiB

DigiServer v2 - Quick Deployment Guide

📋 Overview

DigiServer is deployed using Docker Compose with the following architecture:

Internet (User) — Port 8080 (HTTP) / 8443 (HTTPS)
    ↓
Caddy Reverse Proxy (auto HTTPS, gzip, security headers)
    ↓
Internal Docker Network (digiserver-network)
    ↓
Flask App (Gunicorn on Port 5000)
    ↓
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

🚀 Quick Start

1️⃣ Clone & Setup

git clone <repository>
cd digiserver-v2

2️⃣ Start Containers

docker compose up -d

This automatically:

  1. Builds the Flask app image from Dockerfile
  2. Creates persistent data directories (data/instance, data/uploads, etc.)
  3. Starts Caddy reverse proxy on ports 8080 (HTTP) and 8443 (HTTPS)
  4. Initializes the database on first run (auto-creates admin user)
  5. Runs all required migrations

Access the app at: http://localhost:8080

3️⃣ First-Time Login

URL:      http://localhost:8080
Username: admin
Password: admin123

⚠️ CHANGE PASSWORD IMMEDIATELY IN PRODUCTION!


📦 Container Architecture

Container 1: digiserver-app (Flask)

Property Value
Image Built from Dockerfile (Python 3.13-slim)
Container name digiserver-v2
Exposed port 5000 (internal — proxied by Caddy)
Mapped port 5000:5000 (for direct dev access)
Entrypoint docker-entrypoint.sh (init DB → gunicorn)
Workers 4 gunicorn workers, 120s timeout

Volumes (persistent data):

Host path Container path Purpose
./data/instance /app/instance SQLite database
./data/uploads /app/app/static/uploads Media uploads

Code is baked into the Docker image — see Rebuild below.

Container 2: caddy (Reverse Proxy)

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

🚀 Full Automated Deployment

./deploy.sh

This runs the complete workflow:

  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

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)

On container start the entrypoint automatically:

  1. Creates required directories
  2. Checks for existing dashboard.db
  3. If absent — creates tables and seeds admin user
  4. Starts Gunicorn (4 workers, 120s timeout)

Step 3: Run Migrations

docker compose exec -T digiserver-app python /app/migrations/<name>.py

Key migrations:

  • add_https_config_table.py — HTTPS settings table
  • add_player_user_table.py — Player user management
  • add_email_to_https_config.py — Email field
  • 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

Via Admin UI (recommended):

  1. Go to Admin → HTTPS Config
  2. Enter hostname, domain, email, IP, port
  3. Caddy auto-provisions a Let's Encrypt certificate

Via CLI:

docker compose exec -T digiserver-app python /app/https_manager.py enable \
    <hostname> <domain> <email> <ip_address> <port>

Step 5: ProxyFix Middleware (app/app.py)

Flask extracts real client info from Caddy headers:

  • X-Forwarded-For → Real client IP
  • X-Forwarded-Proto → Protocol (http/https)
  • X-Forwarded-Host → Original hostname
  • X-Forwarded-Port → Original port

🔄 Rebuild After Code Changes

Because the application code is baked into the Docker image, update it with:

# 1. Rebuild the image
docker build --no-cache -t digiserver-v2-digiserver-app .

# 2. Replace the running container
docker stop digiserver-v2 && docker rm digiserver-v2
docker compose up -d digiserver-app

Quick test (no rebuild) — copy files into the running container:

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:

./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

Containers

docker compose up -d          # Start all services
docker compose down           # Stop all services
docker compose restart        # Restart all
docker compose restart caddy  # Restart only Caddy

Logs

docker compose logs -f                    # Follow all
docker compose logs -f digiserver-app     # Flask only
docker compose logs -f caddy              # Caddy only
docker compose logs --tail=50 digiserver-app

Status

docker compose ps
docker ps --format="table {{.Names}}\t{{.Status}}"

Database

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

Caddy

docker exec digiserver-caddy caddy validate --config /etc/caddy/Caddyfile
docker exec digiserver-caddy caddy reload --config /etc/caddy/Caddyfile

🔒 HTTPS / SSL

Caddy automatically provisions Let's Encrypt certificates when a public domain is configured. For development with self-signed certificates:

bash generate_nginx_certs.sh 192.168.0.121 365
docker compose restart caddy

Note: generate_nginx_certs.sh has been moved to old_code_documentation/ but still works.


🐛 Troubleshooting

Containers not starting?

docker compose logs
docker stats

App not responding?

docker compose ps
curl http://localhost:5000/    # Bypass Caddy, hit Flask directly
docker compose logs -f digiserver-app

Caddy / HTTPS issues?

docker exec digiserver-caddy caddy validate --config /etc/caddy/Caddyfile
ls -la ./data/caddy-data/certificates/
docker compose restart caddy