# CheckPoint Ehrenamt — Deployment & Betrieb > Flask/Gunicorn · Docker · cpe.bujour.info · Stand: Juni 2026 --- ## Überblick CheckPoint Ehrenamt läuft als Docker-Container auf dem EU-VPS hinter Caddy. Das Image wird direkt auf dem VPS aus dem geklonten Forgejo-Repo gebaut — kein Container-Registry, kein CI/CD. **URL:** https://cpe.bujour.info **Repo:** https://git.bujour.de/patsy/CP_EHRENAMT **Code auf VPS:** `~/apps/checkpoint/` **Stack:** `~/stacks/checkpoint/` --- ## Stack-Struktur ``` ~/stacks/checkpoint/ ├── compose.yaml └── .env ← SECRET_KEY (nicht im Git) ~/apps/checkpoint/ ├── Dockerfile ├── wsgi.py ├── gunicorn.conf.py ├── seed.py ├── requirements.txt ├── app/ └── instance/ ← DB + Uploads (Docker Volume) ``` --- ## compose.yaml ```yaml services: checkpoint: build: /home/patsy/apps/checkpoint container_name: checkpoint restart: unless-stopped environment: - CP_ENV=production - SECRET_KEY=${SECRET_KEY} volumes: - checkpoint_data:/app/instance networks: - proxy expose: - "8000" volumes: checkpoint_data: networks: proxy: external: true ``` --- ## Erstes Deployment (Einmalig) ```bash # 1. Repo klonen git clone ssh://git@git.bujour.de:2222/patsy/CP_EHRENAMT.git ~/apps/checkpoint # 2. Secret generieren python3 -c "import secrets; print('SECRET_KEY=' + secrets.token_urlsafe(48))" \ > ~/stacks/checkpoint/.env # 3. Image bauen und Container starten cd ~/stacks/checkpoint docker compose build docker compose up -d # 4. Datenbank seeden (einmalig) docker exec checkpoint python seed.py # 5. Ersten Admin anlegen (einmalig) docker exec -e SECRET_KEY=$(grep SECRET_KEY ~/stacks/checkpoint/.env | cut -d= -f2) \ checkpoint flask --app wsgi create-admin "" "" ``` --- ## Update einspielen ```bash cd ~/apps/checkpoint git pull cd ~/stacks/checkpoint docker compose build docker compose up -d ``` Neue Tabellen werden beim Start automatisch via `db.create_all()` angelegt. **Achtung:** Bestehende Tabellen werden nicht migriert — bei Schema-Änderungen vorher Backup ziehen und ggf. manuell migrieren. --- ## Weitere Admins anlegen ```bash docker exec -e SECRET_KEY=$(grep SECRET_KEY ~/stacks/checkpoint/.env | cut -d= -f2) \ checkpoint flask --app wsgi create-admin "" "" ``` --- ## Datenbank-Backup (manuell) ```bash docker exec checkpoint sqlite3 /app/instance/checkpoint.sqlite \ ".backup '/app/instance/checkpoint-backup-$(date +%Y%m%d).sqlite'" ``` Das Backup liegt im Volume unter `/app/instance/` und kann von dort kopiert werden. --- ## Logs ```bash # Live-Logs docker logs checkpoint -f # Letzte 100 Zeilen docker logs checkpoint --tail 100 ``` --- ## Fehlersuche | Problem | Ursache | Lösung | |---|---|---| | 500 nach Deploy | Fehlendes `SECRET_KEY` | `.env` prüfen, Container neu starten | | Login funktioniert nicht | `CP_ENV` nicht gesetzt | `docker exec checkpoint env \| grep CP_ENV` | | App nicht erreichbar | Caddy oder Container down | `docker ps`, dann Caddy-Reload | | „database is locked" | Zu viele Worker für SQLite | `workers` in `gunicorn.conf.py` auf 2 senken | --- ## Technischer Stack | Komponente | Entscheidung | |---|---| | Backend | Python 3.13 + Flask | | WSGI | gunicorn (3 Worker, gthread) | | Datenbank | SQLite mit WAL-Modus | | Templating | Jinja2, server-rendered | | CSS | Selbst gebaut, kein Framework | | JavaScript | Minimal, Vanilla (nur Chat-Polling + Sidebar) | | CSRF | Selbst gebaut (Session-Token, kein Flask-WTF) | | Hosting | IONOS EU-VPS, Docker, Caddy (TLS automatisch) |