Skip to content

Setup (lokal)

Development-Stack auf der Workstation. Production (Server, Traefik, mTLS): Deployment. Compose-Kurzbefehle beider Welten: README im Projektroot.

Voraussetzungen

  • Docker + Docker Compose
  • Optional: Python 3 mit QGIS-Bindings (nur für scripts/setup_qgis_forms.py) oder Docker-Image qgis/qgis
  • QGIS 3.x / 4.x zum Testen der Formulare und der Karte

Konfiguration

cp .env.example .env
vim .env

Wichtige Variablen:

Variable Bedeutung
POSTGRES_DB / POSTGRES_USER / POSTGRES_PASSWORD Superuser im Container
POSTGRES_PORT Host-Port → Container 5432 (Default 3401, nur lokal/Dev)
LINETRA_PG_HOST / LINETRA_PG_PORT Host/Port für QGIS: lokal localhost:3401; Server PgBouncer …:5432
POSTGRES_IMAGE Default postgis/postgis:17-3.5
REDIS_URL Broker (redis://redis:6379/0)
FILE_STORAGE_DIR Rohinput / Exporte (/var/linetra/files, uid 1000 / appuser)
LINETRA_PG_SSLMODE Lokal disable; Server/QGIS verify-full
PGBOUNCER_PORT Host-Port des mTLS-Proxys (Default 5432)
LINETRA_APP_USER / LINETRA_APP_PASSWORD Edit-Rolle für QGIS
LINETRA_READONLY_USER / LINETRA_READONLY_PASSWORD Nur-Lesen-Rolle
LINETRA_QGIS_USER User für Form-Setup-Skript

.env nicht committen.

Zusätzliche Web-CMS-Variablen: SESSION_SECRET, CORS_ORIGINS, COOKIE_SECURE, DATABASE_HOST / DATABASE_PORT (Compose-intern postgres:5432), NEXT_PUBLIC_APP_URL, LOG_LEVEL (debug / info / warning / error / critical, Default info; DEBUG=true hebt auf debug), LOG_BUFFER_SIZE (50–5000, Default 500) für Settings → Log. info ist die grobe Normalstufe (Start/Stop, Login, …); HTTP-Access von Uvicorn erscheint erst bei debug und nur in den Container-Logs, nicht im Ringspeicher.

Gleiche Production-Datenbank

Die lokale FastAPI kann PostGIS auf dem NAS über PgBouncer mTLS nutzen (derselbe Weg wie QGIS). Production-FastAPI bleibt intern postgres:5432.

Auf dem Server (einmalig, CA liegt schon dort):

./scripts/pki/issue-client-cert.sh edit workstation
./scripts/pki/issue-client-cert.sh read workstation-read

Dateien auf die Workstation kopieren nach pgbouncer/certs/workstation/:

Datei auf dem NAS Datei lokal
pgbouncer/certs/ca.crt ca.crt
pgbouncer/certs/clients/workstation.crt + .key edit.crt / edit.key
pgbouncer/certs/clients/workstation-read.crt + .key read.crt / read.key

In der lokalen .env (nicht auf dem Server):

DATABASE_HOST=linetra.nasarek.dev
DATABASE_PORT=5432
DATABASE_SSLMODE=verify-full
DATABASE_SSLROOTCERT=/certs/ca.crt
DATABASE_SSLCERT_EDIT=/certs/edit.crt
DATABASE_SSLKEY_EDIT=/certs/edit.key
DATABASE_SSLCERT_READ=/certs/read.crt
DATABASE_SSLKEY_READ=/certs/read.key

LINETRA_APP_PASSWORD / LINETRA_READONLY_PASSWORD müssen zu Production passen. Alembic und create_app_roles.sh weiter auf dem Server ausführen. Redis und /var/linetra/files bleiben lokal.

Dann denselben Dev-up -d --build. Details: ADR-0013.

Development

Bind-Mount und Reload. Immer beide Compose-Dateien — --profile dev allein startet das Production-Backend. docker-compose.override.yml nicht mitgeben (sonst Traefik-Netz und unpublished Postgres).

docker compose -f docker-compose.yml -f docker-compose.dev.yml --profile dev up -d --build
./scripts/create_app_roles.sh
docker compose -f docker-compose.yml -f docker-compose.dev.yml --profile dev exec backend uv run alembic upgrade head
python3 scripts/setup_qgis_forms.py   # optional: Formulare + Styles

Denselben up -d --build-Befehl für jeden späteren Rebuild. Alembic-DDL läuft als POSTGRES_USER (linetra_edit hat nur DML). Bei Permission denied unter /app/.venv den Stack mit beiden -f-Dateien neu starten, damit venv-init das Volume appuser (uid 1000) zuordnet.

  • Frontend: http://localhost:3000 · Backend: http://localhost:8000/api/v1/health
  • QGIS: localhost:3401, User linetra_edit, SSL aus
  • Schema: Alembic (upgrade head). Optional Dump: LINETRA_BACKUP=/path/to/dump.sql ./scripts/restore_db.sh.
  • Stammdaten: qgis/linetra_stammdaten.qgz (optional). Karte: Plugin, Views qgis_<kind>.

Backend-Tests (Development-Image):

docker compose -f docker-compose.yml -f docker-compose.dev.yml --profile dev exec backend uv run pytest -q

Production

Server: Runtime-Images, Traefik, PgBouncer — kein docker-compose.dev.yml. Ablauf und Rebuild: Deployment.

./scripts/pki/init-ca.sh                    # CA + Serverzertifikat; nötig für QGIS-Cert-ZIP
./scripts/pki/issue-client-cert.sh edit     # optional CLI-Cert; sonst Settings → Nutzer
./scripts/deploy_server.sh                  # compose mtls+production + App-Rollen
docker compose exec backend uv run --no-dev alembic upgrade head
./scripts/alembic_upgrade_all.sh
./scripts/pki/verify-mtls.sh                # Abnahme, nachdem mtls läuft

Nützliche Skripte

Host-Skripte, cwd Projektroot. Kurzkommentare stehen auch in den Dateiköpfen.

Skript Was es tut
scripts/create_app_roles.sh Postgres-Rollen linetra_edit / linetra_read aus .env — QGIS und API, nicht die Web-Konten
scripts/ensure_app_users.sh Tabelle app_users (Web-Login). Bootstrap-User seeden beim Backend-Start, solange die Tabelle leer ist
scripts/deploy_server.sh Production-Bootstrap: ggf. init-ca.sh, Compose mtls+production, App-Rollen. Danach Alembic
scripts/alembic_upgrade_all.sh Control-Alembic plus Tenant-Head auf jeder aktiven Mandanten-DB
scripts/restore_db.sh Optionaler SQL-Dump-Import (nicht der Scratch-Start). LINETRA_BACKUP=/path/to.dump.sql
scripts/pki/init-ca.sh Interne CA + PgBouncer-Serverzertifikat → pgbouncer/certs/ (Backend-Mount /certs für QGIS-Cert-ZIP)
scripts/pki/issue-client-cert.sh CLI-Clientzertifikat edit\|read [name]pgbouncer/certs/clients/. Kollegen: Einstellungen → Nutzer → QGIS-Cert-ZIP
scripts/pki/verify-mtls.sh Abnahme: Login mit clients/edit.crt, Abweisung ohne Cert
scripts/setup_qgis_forms.py Drag&Drop-Formulare → .qgz + layer_styles