docs / proxy/configuration
Proxy configuration
Every environment variable, threshold, and fallback behaviour the proxy exposes.
⏱ 10 min read
Environment variables
| VARIABLE | REQUIRED | DEFAULT | DESCRIPTION |
|---|---|---|---|
| EKMIRE_API_KEY | yes | — | Project API key. |
| EKMIRE_UPSTREAM | yes | — | Upstream app URL, e.g. http://app:3000. |
| EKMIRE_CLOUD | no | https://api.ekmire.com | Control plane endpoint. |
| EKMIRE_TARPIT_THRESHOLD_MS | no | 800 | Sub-millisecond requests below this are treated as automated. |
| EKMIRE_TARPIT_CONSECUTIVE | no | 3 | Consecutive matches before tarpit engages. |
| EKMIRE_SEMANTIC_BLOCK_SCORE | no | 0.85 | LLM risk score above which requests block. |
| EKMIRE_SEMANTIC_LOG_SCORE | no | 0.60 | Score above which requests are logged but not blocked. |
| EKMIRE_SEMANTIC_FALLBACK | no | pass | When LLM is unavailable: pass or block. |
| EKMIRE_LLM_TIMEOUT_MS | no | 1500 | LLM call timeout. Above this, fallback applies. |
| EKMIRE_SCRAPER_POISON | no | true | Inject zero-width watermarks into responses served to known scrapers. |
Full Docker Compose example
services:
ekmire-proxy:
image: ghcr.io/flux8labs/ekmire-proxy:latest
ports: ["8080:8080"]
environment:
EKMIRE_API_KEY: ${EKMIRE_API_KEY}
EKMIRE_UPSTREAM: http://app:3000
EKMIRE_SEMANTIC_BLOCK_SCORE: "0.85"
EKMIRE_SEMANTIC_FALLBACK: pass
EKMIRE_TARPIT_THRESHOLD_MS: "800"
depends_on: [app]
app:
build: .
expose: ["3000"]
environment:
DATABASE_URL: ${DATABASE_URL}Threshold tuning
The semantic block score is the threshold above which a request is blocked outright. Lower this if you are missing attacks. Raise this if you are seeing false positives.
The semantic log score is the threshold above which a request is recorded as suspicious but allowed through. Use the gap between log and block to triage borderline cases without false-positive churn.
Most production deployments converge on block=0.85, log=0.60. Aggressive deployments push block down to 0.75; lenient deployments raise it to 0.92.
Semantic fallback
When the LLM provider is unavailable or exceeds EKMIRE_LLM_TIMEOUT_MS, the proxy falls back to the configured behaviour:
pass(default) — the request proceeds. Deterministic rules still run. Use when availability matters more than catching the semantic layer.block— the request is blocked with a 503. Use only when you would rather have an outage than ship an unanalysed payload. This is a serious choice; review carefully.
WARNINGIf you set fallback to
block and your LLM provider goes down, every request to your app is blocked. Test with chaos drills before enabling in production.