# Referenz für die PRODUKTIV-Env-Variablen (Coolify, docker-compose.coolify[.prebuilt].yml). # ECHTE Secrets NUR in Coolify eintragen – diese Datei enthält nur Platzhalter. # Unterschiede zum Testserver: HTTPS-AUTH_URL, KEIN Demo-Seed, stattdessen Bootstrap-Admin, # RLS scharf. Betriebsdoku: docs/craftvia/DEPLOY.md # --- Datenbank (Service "postgres") --- POSTGRES_USER=craftvia POSTGRES_PASSWORD=CHANGE_ME_starkes_db_passwort POSTGRES_DB=craftvia DATABASE_URL=postgresql://craftvia:CHANGE_ME_starkes_db_passwort@postgres:5432/craftvia?schema=public # --- Row Level Security scharfschalten (F-04) --- # RLS_ENFORCED=true – app und craftvia-worker verbinden sich als eingeschränkte Rolle # craftvia_app (NOBYPASSRLS) und setzen app.tenant_id pro Transaktion; FORCE ROW LEVEL # SECURITY macht die Policies dann scharf. Ist der Kontext nicht gesetzt, sieht craftvia_app # NULL Zeilen – daher NUR mit korrekt gesetztem RLS_DATABASE_URL einschalten (sonst # bricht die App beim Start bewusst ab). # WICHTIG: Die Owner-/Migrate-Rolle in DATABASE_URL MUSS BYPASSRLS/Superuser sein # (Migrationen, Seed, Mail-/Backup-Worker und der mandantenübergreifende Login-Lookup # laufen darüber). craftvia_app wird von der Baseline-Migration NOLOGIN angelegt und in # Prod EINMALIG mit LOGIN + starkem Passwort versehen: # ALTER ROLE craftvia_app WITH LOGIN PASSWORD ''; RLS_ENFORCED=true RLS_DATABASE_URL=postgresql://craftvia_app:CHANGE_ME_starkes_craftvia_app_passwort@postgres:5432/craftvia?schema=public # --- Redis (Service "redis") --- # F-18: Redis läuft mit requirepass. NUR REDIS_PASSWORD setzen – REDIS_URL wird in den # Coolify-Compose-Dateien daraus abgeleitet (redis://:${REDIS_PASSWORD}@redis:6379). REDIS_PASSWORD=CHANGE_ME_starkes_redis_passwort # --- Objektspeicher (Service "garage", S3-kompatibel) --- # Bucket/Key legt der Init-Job "garage-provision" an (Admin-API). Format erzwungen: # S3_ACCESS_KEY = "GK" + 24 Hex -> echo "GK$(openssl rand -hex 12)" # S3_SECRET_KEY = 64 Hex -> openssl rand -hex 32 S3_ENDPOINT=http://garage:3900 S3_ACCESS_KEY=GK000000000000000000000000 S3_SECRET_KEY=CHANGE_ME_openssl_rand_hex_32 S3_BUCKET=craftvia-documents S3_REGION=us-east-1 # Garage-Daemon-Secrets (LITERAL in Coolify setzen, nicht via ${...}). GARAGE_RPC_SECRET=CHANGE_ME_openssl_rand_hex_32 GARAGE_ADMIN_TOKEN=CHANGE_ME_openssl_rand_hex_32 # GARAGE_ZONE=dc1 # GARAGE_CAPACITY_BYTES=100000000000 # --- Backup-Zielspeicher (optional) --- # Ziel der Backup-/DSGVO-Artefakte ist im Betreiber-Portal (/admin/backup) waehlbar # (Lokal/S3) und wird verschluesselt in der DB gehalten. Praezedenz: DB-Config → # Env (S3_*/BACKUP_LOCAL_DIR) → lokaler Default. Fuer „Lokal" mountet die Compose-Datei # das persistente Volume `backups` auf /app/.backups (app + backup-worker). BACKUP_LOCAL_DIR=/app/.backups # Optionaler eigener Backup-Bucket (nur wenn der Backup-Store auf S3 laeuft). # BACKUP_S3_BUCKET= # Verschluesselung der Backup-Artefakte (AES-256-GCM); leer = AUTH_SECRET. Je Umgebung # eigener Wert, alte Keys bis Retention-Ende aufbewahren. BACKUP_ENC_KEY=CHANGE_ME_openssl_rand_hex_32 # --- Auth (Auth.js v5) – Produktiv über HTTPS --- # AUTH_SECRET: openssl rand -base64 32 (frisch, NICHT der Testwert) AUTH_SECRET=CHANGE_ME_openssl_rand_base64_32 # PASSWORD_PEPPER (Härtung §1): openssl rand -hex 32 — frisch je Umgebung, NICHT rotierbar, nie ins Artefakt. PASSWORD_PEPPER=CHANGE_ME_openssl_rand_hex_32 # MFA_ENC_KEY: TOTP-Secrets at-rest (leer = aus AUTH_SECRET). ⚠ Nach dem Setzen nicht mehr ändern. MFA_ENC_KEY=CHANGE_ME_openssl_rand_hex_32 AUTH_URL=https://app.craftvia.example # AUTH_TRUST_HOST ist im Compose fest auf true (hinter dem Coolify-Proxy) – nicht nötig. # Passkeys/WebAuthn: leer = aus AUTH_URL abgeleitet. # WEBAUTHN_ORIGIN=https://app.craftvia.example # WEBAUTHN_RP_ID=app.craftvia.example # --- E-Mail (produktives SMTP-Relay; SPF/DKIM/DMARC der Absenderdomain vorher einrichten) --- SMTP_HOST= SMTP_PORT=587 # true = implizites TLS (465), false = STARTTLS (587); leer = aus Port abgeleitet. SMTP_SECURE= SMTP_USER= SMTP_PASSWORD= SMTP_FROM=no-reply@craftvia.example MAIL_FROM_NAME=Craftvia MAIL_REPLY_TO= # Basis für absolute Links in Mails/PDFs; leer = AUTH_URL. APP_BASE_URL=https://app.craftvia.example # --- KI: Auftragsimport-Extraktion & Lotse (Anthropic) --- # Ohne ANTHROPIC_API_KEY: graceful degradation (manuelle Erfassung, kein Lotse-Entwurf). AI_EXTRACTION_PROVIDER=anthropic ANTHROPIC_API_KEY= # Leer = Default-Modell aus src/server/ai/client.ts ANTHROPIC_MODEL= # --- KI: Transkription von Sprachnotizen (Whisper-kompatible API) --- # Ohne TRANSCRIPTION_API_KEY bleibt die Transkription deaktiviert (Status "disabled"). TRANSCRIPTION_PROVIDER=openai-compatible TRANSCRIPTION_API_URL=https://api.openai.com/v1/audio/transcriptions TRANSCRIPTION_API_KEY= TRANSCRIPTION_MODEL=whisper-1 # --- KI: Kostenbremse & Aufbewahrung --- # Tokens (ein + aus) je Mandant je Kalendermonat; darüber lehnen Lotse und # Import-Extraktion ab. 0 = unbegrenzt. AI_MONTHLY_TOKEN_LIMIT=0 # --- Craftvia: Testphase (L15, docs/craftvia/TESTPHASE.md) --- # Längste selbst gewählte Testphase in Tagen (1–365); Vorbelegung im Wizard heute + 14. TRIAL_MAX_DAYS=30 # Kontakt in Banner und Testphasen-Mails (Vollversion/Verlängerung); leer = allgemeiner Hinweis. TRIAL_CONTACT_EMAIL= # Nach N Tagen leert/pseudonymisiert ein Worker-Job Ein-/Ausgaben im KI-Protokoll # (AiGeneration). Frist mit dem DSB abstimmen. AI_GENERATION_RETENTION_DAYS=180 # --- Craftvia: API-Rate-Limits (je Nutzer, Anfragen pro Minute) --- API_RATE_LIMIT_PER_MINUTE=300 # /api/v1/sync, /api/v1/uploads, /api/v1/field/** API_FIELD_RATE_LIMIT_PER_MINUTE=1200 # --- Craftvia: Offline/PWA --- OFFLINE_MAX_DAYS=7 # --- Craftvia: optionaler Malware-Scan (ClamAV clamd) --- CLAMAV_HOST= CLAMAV_PORT=3310 # PDF_CHROMIUM_PATH ist im Worker-Image/Compose fest /usr/bin/chromium – nicht setzen. # --- Demo-Seed: in PROD AUS lassen! --- RUN_DEMO_SEED=false # --- Erst-Admin-Bootstrap (statt Demo-Seed) --- # Beim ersten Deploy true setzen -> migrate-Job legt Plattform-Admin + ersten Mandanten an # (idempotent). Danach auf false setzen oder stehen lassen (No-op, wenn vorhanden). BOOTSTRAP_ADMIN=true BOOTSTRAP_ADMIN_EMAIL=admin@craftvia.example BOOTSTRAP_ADMIN_PASSWORD=CHANGE_ME_initiales_admin_passwort BOOTSTRAP_ADMIN_NAME=Craftvia Admin BOOTSTRAP_TENANT_NAME=Musterbetrieb GmbH BOOTSTRAP_TENANT_SLUG=musterbetrieb BOOTSTRAP_TENANT_SHORT=Musterbetrieb BOOTSTRAP_TENANT_SECTOR=