# Umgebungsvariablen

Lalabase wird über Umgebungsvariablen konfiguriert — in der Container-Installation über
die `.env`-Datei.

## Pflicht-Variablen

```bash
# Basis
RAILS_ENV=production
SECRET_KEY_BASE=<generiert via bin/rails secret>

# Datenbank
DATABASE_URL=postgres://lalabase:passwort@db:5432/lalabase_production

# Cache
REDIS_URL=redis://redis:6379/0

# Verschlüsselung gespeicherter Zugangsdaten (KI-Schlüssel, Repository-Tokens)
# Erzeugen mit: bin/rails db:encryption:init
ACTIVE_RECORD_ENCRYPTION_PRIMARY_KEY=<generiert>
ACTIVE_RECORD_ENCRYPTION_DETERMINISTIC_KEY=<generiert>
ACTIVE_RECORD_ENCRYPTION_KEY_DERIVATION_SALT=<generiert>
```

<div class="docs-callout docs-callout--warning">
  <div class="docs-callout__title">Wichtig</div>
  <p>Ohne die drei <code>ACTIVE_RECORD_ENCRYPTION_*</code>-Variablen startet Lalabase in Produktion nicht. Sichere die Werte zusätzlich außerhalb des Servers (z.&nbsp;B. im Passwortmanager): Ein Datenbank-Backup ist ohne sie nur teilweise lesbar — die verschlüsselten Spalten bleiben dann Ciphertext.</p>
</div>

## Betreiber und Rechtsseiten

Betreiber und Rechtsseiten sind keine Umgebungsvariablen. Du trägst sie nach dem ersten
Anmelden im Admin-Bereich unter **Systemeinstellungen → Betreiber und Rechtsseiten** ein:
den Namen des Betreibers und die Adressen von Impressum, Datenschutzerklärung und AGB.

Lalabase zeigt sie in der Fußzeile der Anmeldeseite und der Seiten ohne Anmeldung, in der
Zustimmung beim Annehmen einer Einladung, beim Einschalten der KI und im Datenexport.
Mit Betreiber steht in der Fußzeile `© <Jahr> <Name>`, ohne ihn der reine Text
`powered by Lalabase`. Ein leeres Adressfeld zeigt keinen Link. Jede Adresse muss
vollständig sein und mit `https://` oder `http://` beginnen, sonst speichert das Formular
nichts.

**Wenn du keine eigene Website hast**, kannst du den Text stattdessen direkt eintragen:
unter jedem Adressfeld steht ein Textfeld. Lalabase liefert die Seite dann selbst aus,
unter `/legal/imprint`, `/legal/privacy` und `/legal/terms`, und verlinkt sie an denselben
Stellen. Markdown ist erlaubt (Überschriften, Listen, Links); eingebettetes HTML wird
entfernt, weil die Seite öffentlich erreichbar ist.

Eine eingetragene **Adresse hat Vorrang** vor dem Text. Zwei Fassungen derselben
Datenschutzerklärung fangen irgendwann an, sich zu unterscheiden.

Bleiben Adresse und Text leer, gibt es weder Seite noch Link. Für eine Instanz, die nur
dein Team benutzt, ist das der Normalfall: eine Impressumspflicht entsteht erst, wenn du
den Dienst öffentlich anbietest.

## Registrierung über eine eigene Website (optional)

Läuft deine Anmeldeseite in einem eigenen Programm, kann es Konten über eine Schnittstelle
anlegen. Ohne diese Variable gibt es die Schnittstelle nicht: der Endpunkt antwortet dann wie
jede unbekannte Adresse. Für den Eigenbetrieb brauchst du sie in der Regel nicht, dort legst du
Nutzer im Admin-Bereich an oder lädst sie ein.

```bash
# Erzeugen mit: openssl rand -hex 32
LALABASE_PROVISIONING_SECRET=<generiert>

# Nur während eines Wechsels: das vorherige Geheimnis bleibt zusätzlich gültig
LALABASE_PROVISIONING_SECRET_PREVIOUS=<vorheriger Wert>
```

Mit gesetztem Geheimnis gibt der Endpunkt außerdem einen Einmal-Link zurück, mit dem die
Website den neuen Nutzer anmeldet, ohne dass er sein Passwort erneut eingeben muss.

Das Geheimnis braucht mindestens 64 Zeichen. Ist es kürzer, bleibt die Schnittstelle zu und
Lalabase schreibt beim Start einen Hinweis ins Log: das Symptom sieht sonst genauso aus wie
„gar nicht eingerichtet“. Wechseln ohne Ausfall: neues Geheimnis eintragen, das alte nach
`_PREVIOUS`, dann die Website umstellen und `_PREVIOUS` wieder entfernen.

Damit `/users/sign_up` niemanden mehr auf das eigene Formular dieser Instanz führt, trägst
du zusätzlich die Adresse deiner Anmeldeseite ein:

```bash
LALABASE_SIGNUP_URL=https://deine-seite.example/signup
```

Ohne diese Variable bleibt alles wie bisher, und das ist der Normalfall für den
Eigenbetrieb. Mit ihr leitet Lalabase `/users/sign_up` dorthin weiter, vorübergehend
(302), damit du die Weiterleitung durch Entfernen der Variable wieder loswirst.

Zwei Dinge bleiben bewusst hier: **Eingeladene** und das **Absenden** des Formulars.
Ein Einladungslink trägt einen Token, den eine fremde Anmeldeseite nicht einlösen kann;
sie würde eine neue Organisation anlegen statt der Einladung zu folgen. Und ein Formular,
das jemand noch offen hat, soll sich abschicken lassen, statt die Eingaben zu verlieren.

Die Adresse muss vollständig sein und mit `https://` oder `http://` beginnen. Ein anderer
Wert wird ignoriert, Lalabase schreibt beim Start einen Hinweis ins Log, und das eigene
Formular antwortet weiter.

Am besten zeigt die Adresse auf einen Einstieg **ohne Sprachkürzel**: welche Sprache
jemand bekommt, entscheidet dann die Seite, die ihre eigenen Adressen kennt.

## KI-Schlüssel (BYOK)

Lalabase folgt dem **Bring-your-own-Key**-Prinzip: du hinterlegst deinen eigenen
Provider-Schlüssel, damit keine Daten über fremde Konten laufen.

```bash
OPENAI_API_KEY=sk-...
```

<div class="docs-callout docs-callout--tip">
  <div class="docs-callout__title">Tipp</div>
  <p>Bewahre Secrets außerhalb der Versionsverwaltung auf. Die <code>.env</code> gehört in die <code>.gitignore</code>.</p>
</div>

## E-Mail

Für Benachrichtigungen per E-Mail trägst du deine SMTP-Zugangsdaten ein:

```bash
SMTP_ADDRESS=smtp.example.com
SMTP_PORT=587
SMTP_USERNAME=lalabase@example.com
SMTP_PASSWORD=<dein-passwort>
```

**Ohne funktionierenden Mailversand kann sich niemand neu registrieren.** Wer sich
anmeldet, bekommt eine Bestätigungsmail und hat drei Tage Zeit, den Link darin
anzuklicken. Danach ist der Zugang gesperrt, bis die Adresse bestätigt ist — kommt
die Mail nie an, gibt es kein Weiterkommen. Prüfe den Versand deshalb direkt nach
der Installation mit einer Testregistrierung.

Nicht betroffen sind Nutzer, die du im Adminbereich selbst anlegst, und Eingeladene,
die über einen Einladungslink kommen: Beide gelten sofort als bestätigt und bekommen
keine Bestätigungsmail.

### Mail-Authentifizierung (SPF, DKIM, DMARC)

Korrekte SMTP-Zugangsdaten sorgen nur dafür, dass deine Mails **abgeschickt** werden.
Ob sie auch **ankommen**, entscheidet etwas anderes: drei Einträge im DNS deiner
Domain. Fehlen sie, stuft Gmail oder Outlook die Bestätigungsmail als Spam ein oder
verwirft sie stillschweigend. Die Registrierung sieht dann aus wie ein Fehler in
Lalabase, obwohl der Versand einwandfrei lief.

| Eintrag | Was er leistet |
|---|---|
| **SPF** | Listet die Server, die in deinem Namen senden dürfen |
| **DKIM** | Signiert jede ausgehende Mail kryptografisch |
| **DMARC** | Sagt dem Empfänger, was bei fehlgeschlagener Prüfung zu tun ist — und schickt dir Berichte darüber |

Angelegt werden sie beim DNS-Anbieter deiner Domain, nicht in Lalabase. Die meisten
Mail-Hoster bieten dafür eine Oberfläche an, die den passenden Eintrag selbst erzeugt.

**Reihenfolge ist wichtig, sonst sperrst du dich selbst aus:**

1. **DKIM aktivieren.** Risikofrei — eine fehlende Signatur kann keine Mail zustellen,
   eine vorhandene nur helfen. Prüfe anschließend selbst, ob der Schlüssel wirklich im
   DNS steht: `dig TXT <selektor>._domainkey.<deine-domain>`. Die Statusanzeige mancher
   Hoster hinkt der Realität hinterher.
2. **SPF setzen**, zunächst mit dem neutralen Abschluss `?all`. Nimm nur Server auf, die
   tatsächlich zustellen. Der Server, auf dem Lalabase läuft, gehört in der Regel **nicht**
   dazu: Die App übergibt ihre Mails an den SMTP-Server aus `SMTP_ADDRESS`, tritt dem
   Empfänger gegenüber also nie selbst auf. Eine überflüssige Freigabe ist im
   Kompromittierungsfall ein Einfallstor für Mails in deinem Namen.
3. **DMARC anlegen** mit `p=none` und einer `rua=`-Adresse. `p=none` ändert an der
   Zustellung nichts, schaltet aber die Berichte ein. **Ohne `rua=` ist der Eintrag
   wirkungslos** — du bekommst keine Rückmeldung und erfährst nie, ob deine Einträge
   greifen. Die Adresse sollte auf derselben Domain liegen, sonst verlangt die
   Spezifikation dort einen zusätzlichen Autorisierungs-Record.
4. **Messen.** Schick dir eine Testmail an ein Postfach bei einem großen Anbieter und
   sieh dir die Kopfzeilen an (in Gmail: „Original anzeigen"). Dort steht:

   ```
   Authentication-Results: ... spf=pass ... dkim=pass ... dmarc=pass
   ```

5. **Erst wenn `spf=pass` dort steht**, ziehe den SPF-Abschluss von `?all` auf `~all`.
   Vorher wäre das schädlich: `?all` heißt „keine Aussage", `~all` und `-all` heißen
   „verdächtig" beziehungsweise „ablehnen". Verschärfst du, bevor dein echter Sendeweg
   freigegeben ist, lehnst du deine eigene Post ab.

Nach einigen Wochen sauberer DMARC-Berichte kannst du `p=none` auf `p=quarantine` und
später `p=reject` hochziehen. Fang niemals bei `reject` an.

<div class="docs-callout docs-callout--tip">
  <div class="docs-callout__title">Tipp</div>
  <p>Forensische DMARC-Berichte (<code>ruf=</code>) besser leer lassen. Sie enthalten Volltextkopien fremder fehlgeschlagener Mails, und die großen Anbieter verschicken sie ohnehin nicht.</p>
</div>
