# ============================================================================= # FLORIAN — Feuerwehr-Verwaltungsplattform # Kopiere diese Datei nach ".env" und passe die Werte an: # cp .env.example .env # Alles, was hier steht, wird von docker-compose.yml und von lib/env.ts gelesen. # lib/env.ts validiert beim Start mit Zod — fehlt eine Pflichtvariable, startet # die App gar nicht erst, statt später halb zu funktionieren. # ============================================================================= # ----------------------------------------------------------------------------- # Allgemein # ----------------------------------------------------------------------------- # development | production | test — steuert Logging, Fehlerseiten und Caching. NODE_ENV=development # Öffentliche Basis-URL der Anwendung, ohne abschließenden Schrägstrich. # Muss exakt der Adresse entsprechen, unter der Nutzer die App aufrufen — # Auth.js baut daraus die OIDC-Redirect-URI. APP_URL=http://localhost:3100 # Zeitzone für alle serverseitigen Fristen- und Terminberechnungen. # Nicht ändern, außer die Wehr liegt außerhalb Deutschlands. TZ=Europe/Berlin # Host-Ports fuer die Entwicklung. Bewusst nicht die Standardports, # damit FLORIAN neben anderen lokalen Stacks laufen kann. APP_PORT=3100 GOTENBERG_PORT=3101 MAILPIT_UI_PORT=8125 MAILPIT_SMTP_PORT=1125 ADMINER_PORT=8081 # ----------------------------------------------------------------------------- # Traefik / Domains (nur für den Produktionsbetrieb relevant) # In der Entwicklung greift docker-compose.override.yml und veröffentlicht die # Dienste direkt auf localhost — Traefik wird dort nicht gebraucht. # ----------------------------------------------------------------------------- # Hostname der Anwendung hinter Traefik, z. B. florian.beispielwehr.de APP_DOMAIN=florian.localhost # Hostname der MinIO-S3-API (Datei-Uploads, presignte URLs). MINIO_DOMAIN=s3.florian.localhost # Hostname der MinIO-Weboberfläche (Administration der Buckets). MINIO_CONSOLE_DOMAIN=minio.florian.localhost # Hostname des Traefik-Dashboards. Leer lassen, um es nicht zu veröffentlichen. TRAEFIK_DASHBOARD_DOMAIN=traefik.florian.localhost # E-Mail-Adresse für die ACME-Zertifikate (Let us Encrypt). ACME_EMAIL=kommandant@beispielwehr.de # Traefik-Entrypoint für HTTPS. "websecure" ist der Standard aus dieser Datei. TRAEFIK_ENTRYPOINT=websecure # ----------------------------------------------------------------------------- # PostgreSQL 17 + PostGIS # ----------------------------------------------------------------------------- POSTGRES_USER=florian # Vor dem ersten Start ersetzen: openssl rand -base64 24 POSTGRES_PASSWORD=bitte_aendern_postgres POSTGRES_DB=florian # Port, unter dem Postgres auf dem Host erreichbar ist (nur Entwicklung). POSTGRES_PORT=5442 # Verbindungszeichenfolge der Anwendung. Läuft über den Datenbankbenutzer # "florian_app", für den Row Level Security AKTIV ist — dieser Zugang sieht nur # Daten der Organisation, die per SET LOCAL app.current_organisation gesetzt # wurde (siehe src/lib/db.ts). DATABASE_URL=postgresql://florian_app:bitte_aendern_app@postgres:5432/florian?schema=public # Passwort des Anwendungsbenutzers. Muss zu DATABASE_URL passen und wird beim # ersten Start von docker/postgres/10-init-app-role.sh gesetzt. POSTGRES_APP_PASSWORD=bitte_aendern_app # Verbindung für Migrationen und Seed. Nutzt den Eigentümer-Zugang, der RLS # umgehen darf. Niemals im Anwendungscode verwenden. DIRECT_DATABASE_URL=postgresql://florian:bitte_aendern_postgres@postgres:5432/florian?schema=public # ----------------------------------------------------------------------------- # Redis (Warteschlangen für BullMQ, Rate-Limiting) # ----------------------------------------------------------------------------- # Vor dem ersten Start ersetzen: openssl rand -base64 24 REDIS_PASSWORD=bitte_aendern_redis REDIS_URL=redis://:bitte_aendern_redis@redis:6379 # Port auf dem Host (nur Entwicklung). REDIS_PORT=6389 # Anzahl paralleler Jobs je Worker-Prozess. WORKER_CONCURRENCY=5 # ----------------------------------------------------------------------------- # MinIO (S3-kompatibler Objektspeicher — ALLE Dateien liegen hier, nie im FS) # ----------------------------------------------------------------------------- MINIO_ROOT_USER=florian # Mindestens 8 Zeichen, vor dem ersten Start ersetzen. MINIO_ROOT_PASSWORD=bitte_aendern_minio # Endpunkt, den App und Worker intern ansprechen — im Compose-Netz der # Dienstname, außerhalb der externe Hostname. S3_ENDPOINT=minio S3_PORT=9000 # true, sobald MinIO hinter Traefik mit TLS läuft. S3_USE_SSL=false S3_ACCESS_KEY=florian S3_SECRET_KEY=bitte_aendern_minio S3_REGION=eu-central-1 # Bucket für alle Nutzdateien (Prüfprotokolle, Fotos, Rechnungen, Exporte). S3_BUCKET=florian # Öffentlich erreichbare Basis-URL für presignte Download-Links. In der # Entwicklung http://localhost:9010, in Produktion https://$MINIO_DOMAIN S3_PUBLIC_URL=http://localhost:9010 # Gültigkeitsdauer presignter Links in Sekunden (Standard: 15 Minuten). S3_URL_TTL=900 # Ports auf dem Host (nur Entwicklung): API und Weboberfläche. MINIO_API_PORT=9010 MINIO_CONSOLE_PORT=9011 # ----------------------------------------------------------------------------- # Gotenberg (PDF-Erzeugung für Prüfprotokolle, Berichte, Rechnungen) # ----------------------------------------------------------------------------- GOTENBERG_URL=http://gotenberg:3000 # Zeitlimit je PDF-Auftrag in Sekunden. GOTENBERG_TIMEOUT=30 # ----------------------------------------------------------------------------- # Auth.js — Sitzungsverwaltung # ----------------------------------------------------------------------------- # Signiert die Sitzungs-Cookies. Zwingend erforderlich, pro Installation neu: # openssl rand -base64 32 AUTH_SECRET=bitte_aendern_mindestens_32_zeichen_lang # Muss hinter einem Reverse Proxy (Traefik) auf true stehen, damit Auth.js die # X-Forwarded-Header auswertet und korrekte Redirect-URIs erzeugt. AUTH_TRUST_HOST=true # Lebensdauer einer Sitzung in Sekunden (Standard: 8 Stunden). AUTH_SESSION_MAX_AGE=28800 # ----------------------------------------------------------------------------- # OIDC gegen authentik # Die authentik-Instanz wird SEPARAT betrieben und ist nicht Teil dieses Stacks. # In authentik anzulegen: Provider "OAuth2/OpenID" (Client-Typ: confidential), # Redirect-URI exakt $APP_URL/api/auth/callback/authentik # Scopes: openid profile email — plus einen Gruppen-Scope, wenn Rollen aus # authentik-Gruppen vorbelegt werden sollen (siehe AUTH_OIDC_GROUP_CLAIM). # ----------------------------------------------------------------------------- # false blendet den OIDC-Knopf aus; dann bleibt nur der lokale Login. Sinnvoll # für den Erststart, bevor authentik konfiguriert ist. AUTH_OIDC_ENABLED=false # Issuer-URL des Providers, OHNE /.well-known/openid-configuration. # Bei authentik: https:///application/o// AUTH_OIDC_ISSUER=https://auth.beispiel.de/application/o/florian/ AUTH_OIDC_CLIENT_ID= AUTH_OIDC_CLIENT_SECRET= # Beschriftung des Anmeldeknopfes in der Oberfläche. AUTH_OIDC_NAME=Anmeldung über authentik # Claim, aus dem die Gruppenzugehörigkeit gelesen wird. In authentik über ein # Scope-Mapping bereitzustellen. Leer lassen, um das Mapping abzuschalten — # dann werden Rollen ausschließlich in FLORIAN gepflegt. AUTH_OIDC_GROUP_CLAIM=groups # Zuordnung authentik-Gruppe -> FLORIAN-Rolle, kommagetrennt als "gruppe:ROLLE". # Wirkt nur als VORBELEGUNG beim ersten Login; danach ist die in FLORIAN # gepflegte Rolle führend und wird nicht mehr überschrieben. AUTH_OIDC_GROUP_MAPPING=feuerwehr-kommandant:KOMMANDANT,feuerwehr-geraetewart:GERAETEWART,feuerwehr-atemschutz:ATEMSCHUTZGERAETEWART,feuerwehr-kassier:KASSIER,feuerwehr-schriftfuehrer:SCHRIFTFUEHRER,feuerwehr-ausbilder:AUSBILDER,feuerwehr-mitglied:MITGLIED # true legt einen in authentik bekannten Nutzer beim ersten Login automatisch # als Person an. false verlangt, dass die Person vorher in FLORIAN existiert # und über die E-Mail-Adresse verknüpft wird. AUTH_OIDC_AUTO_PROVISION=true # Organisation (Slug), der automatisch angelegte Personen zugeordnet werden. AUTH_OIDC_STANDARD_ORGANISATION=ff-musterhausen # ----------------------------------------------------------------------------- # Lokaler E-Mail/Passwort-Login (Rückfalloption für Erststart und Notbetrieb) # ----------------------------------------------------------------------------- # Nach der Einrichtung von authentik auf false setzen, damit nur noch OIDC geht. AUTH_LOCAL_ENABLED=true # Zugangsdaten des ersten Administrators, angelegt vom Seed-Skript. # Nach dem ersten Login das Passwort in der Oberfläche ändern. SEED_ADMIN_EMAIL=admin@beispielwehr.de SEED_ADMIN_PASSWORT=Feuerwehr2026 # bcrypt-Kostenfaktor. 12 ist ein guter Kompromiss aus Sicherheit und Tempo. AUTH_BCRYPT_ROUNDS=12 # ----------------------------------------------------------------------------- # Terminal-/Kiosk-Anmeldung im Gerätehaus (PIN und RFID) # ----------------------------------------------------------------------------- # Schaltet den Kiosk-Modus samt Terminal-Login frei. KIOSK_ENABLED=true # Gemeinsames Geheimnis, mit dem sich ein Terminal-Gerät gegenüber dem Server # ausweist, bevor überhaupt eine PIN oder ein Token akzeptiert wird: # openssl rand -hex 32 KIOSK_DEVICE_SECRET=bitte_aendern_kiosk_geheimnis # Länge der Personen-PIN. 4 ist bequem, 6 ist sicherer. KIOSK_PIN_LAENGE=6 # Nach wie vielen Fehlversuchen eine PIN gesperrt wird. KIOSK_MAX_FEHLVERSUCHE=5 # Sperrdauer nach zu vielen Fehlversuchen, in Sekunden. KIOSK_SPERRDAUER=300 # Automatische Abmeldung am Terminal nach Untätigkeit, in Sekunden. KIOSK_IDLE_TIMEOUT=120 # ----------------------------------------------------------------------------- # E-Mail-Versand (optional, hinter lib/integrations/mail.ts abstrahiert) # Ohne MAIL_ENABLED=true wird nur ins Log geschrieben — praktisch für Tests. # ----------------------------------------------------------------------------- MAIL_ENABLED=false MAIL_HOST=smtp.beispiel.de MAIL_PORT=587 MAIL_SECURE=false MAIL_USER= MAIL_PASSWORD= MAIL_FROM=FLORIAN # ----------------------------------------------------------------------------- # Telegram-Benachrichtigungen (optional, abschaltbar) # ----------------------------------------------------------------------------- TELEGRAM_ENABLED=false TELEGRAM_BOT_TOKEN= TELEGRAM_CHAT_ID= # ----------------------------------------------------------------------------- # LLM-Anbindung (optional; nur selbstgehostete Endpunkte, kein Cloud-Zwang) # ----------------------------------------------------------------------------- LLM_ENABLED=false # OpenAI-kompatibler Endpunkt, z. B. eine lokale Ollama- oder vLLM-Instanz. LLM_BASE_URL=http://ollama:11434/v1 LLM_API_KEY= LLM_MODELL=qwen2.5:14b # ----------------------------------------------------------------------------- # Datenschutz und Aufbewahrung (DSGVO) # ----------------------------------------------------------------------------- # Aufbewahrungsfrist für Einsatz- und Prüfdokumentation in Jahren. AUFBEWAHRUNG_JAHRE=10 # Aufbewahrungsfrist für den Audit-Log in Tagen. Der Log ist append-only; # Älteres wird vom Worker exportiert, bevor es entfernt wird. AUDIT_AUFBEWAHRUNG_TAGE=3650 # Frist in Tagen, nach der ein ausgetretenes Mitglied anonymisiert wird. PERSON_ANONYMISIERUNG_TAGE=365 # ----------------------------------------------------------------------------- # Telemetrie bleibt aus. Nicht ändern. # ----------------------------------------------------------------------------- NEXT_TELEMETRY_DISABLED=1 CHECKPOINT_DISABLE=1