Konfiguration
Konfiguriert wird an drei Stellen, in dieser Rangfolge: CLI-Flags
schlagen Umgebungsvariablen, und die schlagen die config.json.
Alles, was den Betrieb einer Kundenseite betrifft — Empfänger, Origins, PoW-Bits, Kontingente — steht dagegen nicht hier, sondern pro Mandant in der Datenbank (Bedienung).
CLI-Flags
Abschnitt betitelt „CLI-Flags“| Flag | Bedeutung |
|---|---|
-data <dir> | Datenverzeichnis für config.json, Datenbank und Logs. Default: Verzeichnis des Binaries; im Container typischerweise /data. |
-config <datei> | Pfad zu einer config.json außerhalb des Datenverzeichnisses. |
-debug | Hebt das Log-Level zur Laufzeit auf debug an, unabhängig von log_level. |
-demo | Demo-Modus: lokaler SMTP-Sink plus Demo-Mandanten. Nichts für den Produktivbetrieb. |
-version | Version, Build-Nummer und Build-Zeitpunkt ausgeben und beenden. |
Umgebungsvariablen
Abschnitt betitelt „Umgebungsvariablen“Gedacht für Container, wo eine gemountete config.json unhandlich ist:
| Variable | Wirkung |
|---|---|
FORMGW_DATA | Datenverzeichnis (wie -data) |
FORMGW_HOST | Listen-Adresse, überschreibt host |
FORMGW_PORT | Listen-Port, überschreibt port |
FORMGW_CROWDSEC_URL | LAPI-URL; gesetzt ⇒ die Meldung ist automatisch aktiv |
FORMGW_CROWDSEC_MACHINE_ID | Watcher-Login, überschreibt crowdsec.machine_id |
FORMGW_CROWDSEC_PASSWORD | Watcher-Passwort (Docker Secret), überschreibt crowdsec.password |
TZ | Zeitzone für Logs und Zeitstempel, z. B. Europe/Berlin |
TZ wirkt auch in minimalen Containern und unter Windows — die
Zeitzonendatenbank ist ins Binary eingebettet.
config.json
Abschnitt betitelt „config.json“Entsteht beim ersten Start mit sicheren Zufallswerten und Dateirechten
0600. Vollständiges Beispiel:
{ "host": "127.0.0.1", "port": 8080, "database_path": "gateway.db", "jwt_secret": "…", "encryption_key": "…", "access_token_ttl_minutes": 60, "admin_initial_password": "", "log_level": "info", "access_log": true, "api_key_rate_limit_per_minute": 120, "login_max_attempts": 10, "trusted_proxies": [], "proxy_header": "X-Forwarded-For", "crowdsec": { "enabled": false, "lapi_url": "http://127.0.0.1:8080", "machine_id": "form-gateway", "password": "…", "score_threshold": 100, "window_minutes": 10, "ban_duration": "4h", "decision_type": "ban", "origin": "crowdsec", "scenario": "techeve/form-gateway", "insecure_skip_verify": false }}| Schlüssel | Default | Bedeutung |
|---|---|---|
host | 127.0.0.1 | Listen-Adresse. Bewusst lokal — für direkten Zugriff ohne Proxy auf 0.0.0.0 setzen. |
port | 8080 | Listen-Port. Admin-UI und Public API teilen ihn sich. |
trusted_proxies | [] | IPs/CIDRs der eigenen Reverse-Proxys, deren X-Forwarded-For geglaubt wird. Kurzformen: loopback, private, linklocal. |
proxy_header | X-Forwarded-For | Header mit der Client-IP hinter dem Proxy. |
Datenbank
Abschnitt betitelt „Datenbank“| Schlüssel | Bedeutung |
|---|---|
database_path | Pfad zur SQLite-Datei, relativ zum Datenverzeichnis oder absolut. |
database_dsn | Gesetzt ⇒ PostgreSQL statt SQLite, z. B. postgres://user:pass@host:5432/db. Hat Vorrang vor database_path. |
Secrets
Abschnitt betitelt „Secrets“| Schlüssel | Bedeutung |
|---|---|
jwt_secret | Signiert die Admin-Access-Tokens (HS256). Wird beim ersten Start zufällig erzeugt; unter 32 Zeichen verweigert das Gateway den Start. |
encryption_key | base64-kodierte 32 Bytes. Verschlüsselt SMTP-Passwörter und Signing-Secrets in der Datenbank. |
admin_initial_password | Nur beim allerersten Seeding relevant. Leer ⇒ es wird ein Zufallspasswort erzeugt und einmalig auf der Konsole ausgegeben. Danach wirkungslos. |
Beide Werte niemals einchecken. Wer die Secrets rotieren will, sollte
wissen, dass ein neues jwt_secret alle Sessions beendet und ein neuer
encryption_key die bestehenden verschlüsselten Felder unbrauchbar
macht.
Sessions und API-Keys
Abschnitt betitelt „Sessions und API-Keys“| Schlüssel | Default | Bedeutung |
|---|---|---|
access_token_ttl_minutes | 60 | Lebensdauer eines Admin-JWT. Nach Ablauf antwortet der Server 401 und das Frontend loggt automatisch aus (kein Refresh-Token-Flow). |
api_key_rate_limit_per_minute | 120 | Requests pro API-Key und Minute; 0 schaltet ab. Gilt nur für die Admin-API — die Public API hat ihre eigene Pipeline. |
login_max_attempts | 10 | Fehlversuche bei POST /auth/login je 5-Minuten-Fenster, getrennt gezählt pro Client-IP und pro Benutzername; darüber 429 mit Retry-After. Erfolgreiche Logins zählen nicht mit. 0 schaltet ab — nicht empfohlen: Der Endpunkt ist unauthentifiziert und jeder Versuch kostet 64 MiB argon2-Speicher. |
CrowdSec (Angriffe an die Firewall melden)
Abschnitt betitelt „CrowdSec (Angriffe an die Firewall melden)“Erkennt das Gateway ein Angriffsmuster, kann es die IP an eine CrowdSec Local API (LAPI) melden. Ein dort registrierter Bouncer sperrt sie dann in der vorgelagerten Firewall — der nächste Request erreicht den Service gar nicht mehr. Details und Einrichtung: Sicherheit → CrowdSec.
| Schlüssel | Default | Bedeutung |
|---|---|---|
crowdsec.enabled | false | Schaltet die Meldung ein. |
crowdsec.lapi_url | — | Basis-URL der LAPI, ohne /v1, z. B. http://127.0.0.1:8080. |
crowdsec.machine_id | — | Watcher-Login, angelegt mit cscli machines add form-gateway --password <pw>. |
crowdsec.password | — | Passwort dieses Watchers. Secret — besser per FORMGW_CROWDSEC_PASSWORD. |
crowdsec.score_threshold | 100 | Summe der Signal-Gewichte, ab der gemeldet wird. |
crowdsec.window_minutes | 10 | Beobachtungsfenster pro IP. |
crowdsec.ban_duration | 4h | Sperrdauer der Decision — zugleich Cooldown: dieselbe IP wird in dieser Zeit nicht erneut gemeldet. |
crowdsec.decision_type | ban | Remediation für den Bouncer, z. B. auch captcha. |
crowdsec.origin | crowdsec | Origin der Decision in cscli decisions list. Muss ein CrowdSec-bekannter Wert sein. |
crowdsec.scenario | techeve/form-gateway | Szenario-Name in CrowdSec. |
crowdsec.insecure_skip_verify | false | TLS-Prüfung überspringen — nur für eine LAPI mit selbstsigniertem Zertifikat im eigenen Netz. |
Logging
Abschnitt betitelt „Logging“| Schlüssel | Default | Bedeutung |
|---|---|---|
log_level | info | debug, info, warn oder error. |
access_log | true | Protokolliert jeden API-Request mit Methode, Pfad, Status, Dauer, IP und Username; 4xx als WARN, 5xx als ERROR. |
Passwörter, Tokens, Signing-Secrets und vollständige Formularinhalte landen nie im Log. Client-IPs speichert die Datenbank ausschließlich als gekürzten SHA-256-Hash.
Änderungen übernehmen
Abschnitt betitelt „Änderungen übernehmen“Die config.json wird beim Start gelesen — nach einer Änderung das
Gateway neu starten:
sudo systemctl restart form-gateway # systemddocker compose restart # DockerIst die Datei fehlerhaft, startet das Gateway nicht und nennt den Grund (zu kurzes Secret, ungültiger Port, unbekanntes Log-Level). Die Fehlermeldungen und was dahintersteckt: Installation.