eggrd/ docs

Configuration reference

Every key EdgeGuard reads from edgeguard.toml — 151 of them across 21 tables. Types, defaults and descriptions are generated from src/config.rs, so this page cannot describe a binary that does not exist. If a key is listed here, the parser accepts it.

None of it is required to start. edgeguard init writes a working file and edgeguard doctor tells you what it would do with it before any traffic arrives. Begin there and come back for the one key you need.

[server]

Listener, upstream, and the private ops port.

KeyTypeDefaultWhat it does
portinteger8080Public listen port. Overridden by the PORT env var.
app_portinteger3000Internal port the wrapped/upstream app listens on. Overridden by APP_PORT.
upstreamstring""Full upstream base URL. Overridden by UPSTREAM. If empty, derived from app_port.
trust_forwarded_forbooleanfalseTrust the X-Forwarded-For header for client identity. Enable ONLY when EdgeGuard sits behind a trusted proxy/load balancer that sets it (e.g. a PaaS edge). When false (default) the peer socket address is used, so clients can't spoof their IP to defeat per-IP rate limiting or forge access-log entries.
admin_portinteger0Private listener port for the internal /__edgeguard/* ops endpoints (health, readiness, metrics). 0 (default) keeps them on the public port. When non-zero, EdgeGuard binds a second, plain-HTTP listener on admin_addr:admin_port that serves those endpoints, and the public port serves only the proxy (plus the browser-facing CSP report sink) — so metrics/health aren't exposed on the internet. Overridden by ADMIN_PORT. (Point your platform's health check at this port when you enable it.)
admin_addrstring"127.0.0.1"Address the private admin listener binds when admin_port is set. Defaults to 127.0.0.1 (same-host only — e.g. a sidecar scraper); set to 0.0.0.0 to expose it on a private network interface (rely on your network policy to keep it off the internet).

[auth]

Who is allowed through the front door.

KeyTypeDefaultWhat it does
modestring"none""none" | "basic" | "apikey" | "jwt". Selects the gate applied to every proxied request; the internal /__edgeguard/* endpoints are always exempt.
realmstring"EdgeGuard"Realm shown in the WWW-Authenticate challenge on a 401, i.e. the name the browser's password prompt displays. Only used when mode = "basic".
userstableBTreeMap::new()username -> password. Value may be plaintext (dev) or a $argon2... PHC hash. Used when mode = "basic".
api_keysstring listvec![]Accepted API keys (compared in constant time). Used when mode = "apikey". A request may present a key either as Authorization: Bearer <key> or in api_key_header. Overridable from the env via EDGEGUARD_API_KEYS (comma-separated) so keys need not live in the config file.
api_key_headerstring"X-API-Key"Header carrying the API key (in addition to Authorization: Bearer), default X-API-Key. Used when mode = "apikey".
jwtJwtCfgJwtCfg::default()JWT verification policy. Used when mode = "jwt".

[auth.jwt]

JWT verification, when auth mode is jwt.

KeyTypeDefaultWhat it does
algorithmstring"HS256"Expected signature algorithm, e.g. "HS256", "RS256", "ES256". The token's own alg header must match this (we never trust the token to pick its own algorithm — that is the classic JWT downgrade/alg=none foot-gun).
secretstring""Shared secret for HS* algorithms. Prefer the EDGEGUARD_JWT_SECRET env var over putting it in the config file.
public_key_pemstring""Static PEM public key (SPKI or PKCS#1) for RS*/ES*/PS* verification, as an alternative to jwks_url.
jwks_urlstring""JWKS endpoint to fetch verification keys from (RS*/ES*/PS*). Keys are cached and selected by the token's kid.
jwks_cache_secsinteger300How long (seconds) to cache a fetched JWKS before refetching. Default 300.
issuerstring""If set, the token's iss claim must equal this.
audiencestring""If set, the token's aud claim must contain this.
leeway_secsinteger60Clock-skew leeway (seconds) applied to exp/nbf validation. Default 60.

[ratelimit]

How much any one caller may ask for.

KeyTypeDefaultWhat it does
enabledbooleantrueMaster switch for rate limiting. On by default: an unlimited front door is not a front door. Turn it off only when something ahead of EdgeGuard already limits.
ratestring"60/min"Default per-client-IP limit, e.g. "60/min", "10/sec", "1000/hour".
burstinteger20How many requests may arrive at once before rate applies. The bucket refills at rate, so this is the size of a legitimate spike you are willing to absorb.
routeslist of tablesvec![]Per-route overrides. A request whose path starts with path uses that route's limit (still keyed per client IP) instead of the global one; the longest matching prefix wins, so /api/admin/ can be stricter than /api/.
per_keyPerKeyRateLimitPerKeyRateLimit::default()An additional limit keyed by the authenticated principal (API-key id or JWT subject) rather than IP, so a single credential can't fan out across many IPs. Only applies to authenticated requests.
storestring"local"Where limiter state lives: "local" (default) is the in-process governor limiter (fast, no dependency, but per-replica). "redis" shares GCRA state across replicas via a Redis store, so N instances enforce one global limit. "memory" uses the same shared-store code path backed by an in-process map (a single-replica/testing backend). All three honor the same rate/burst/route/per-key settings above.
redis_urlstring"redis://127.0.0.1:6379"Redis connection URL for store = "redis", e.g. redis://host:6379 or (TLS) rediss://host:6379. Prefer the EDGEGUARD_REDIS_URL env var over this file.
redis_prefixstring"edgeguard"Key prefix/namespace for the shared store, so multiple EdgeGuard deployments can share one Redis without colliding. Keys look like <prefix>:ip:<addr>.
fail_openbooleanfalseWhat to do when the shared store is unreachable. false (default) fails closed — a store error returns 503, so an outage can't silently disable rate limiting. true fails open — a store error allows the request (favor availability over strict limiting). Only relevant for store = "redis".

[ratelimit.per_key]

Per-principal limits layered on the global one.

KeyTypeDefaultWhat it does
enabledbooleanfalseApply a second, per-principal limit on top of the global one. Off by default, because it only means something once requests are authenticated.
ratestring"1000/hour"Sustained rate per authenticated principal, same syntax as ratelimit.rate (e.g. "1000/hour"). Applies per key, not per IP.
burstinteger100Burst allowance per principal. See ratelimit.burst.

[validation]

Request and response size and time bounds.

KeyTypeDefaultWhat it does
max_bodystring"2MiB"e.g. "2MiB". Requests with a larger body are rejected with 413.
max_response_bodystring"0"Cap on the upstream response body EdgeGuard buffers, e.g. "16MiB". "0" disables the cap (unbounded). Protects against an upstream OOM-ing the proxy; raise it if you proxy large downloads.
upstream_timeoutstring"30s"Max time to wait for the upstream response and to read its body, e.g. "30s", "500ms", "2m". "0" disables the timeout. Bounds a stalled upstream so it can't pin a handler task indefinitely; on elapse the proxy returns 504.
max_header_bytesstring"0"Cap on the total size of incoming request headers (sum of name + value bytes), e.g. "32KiB". "0" disables the cap (default). Requests over the limit get 431. This is a policy limit enforced by EdgeGuard on top of hyper's own transport-level header cap.
allow_methodsstring listvec![]Allowed HTTP methods; empty list means allow all.
stream_passthroughbooleanfalseStream (don't buffer) responses whose Content-Type is text/event-stream. Off by default: the proxy normally buffers the whole upstream body so it can cap size (max_response_body) and account exact egress bytes. That buffering defeats Server-Sent Events / chunked streaming — the client only sees the body once the upstream finishes. Turn this on to forward SSE responses frame-by-frame as they arrive (preserving time-to-first-byte). When a response is streamed this way the max_response_body cap and the body-read deadline don't apply (the connect/first-byte upstream_timeout still does); egress bytes are tallied as frames flow. Non-SSE responses are unaffected.
websocket_passthroughbooleanfalseTunnel WebSocket (and other Upgrade) connections through to the upstream. Off by default: the normal path strips the hop-by-hop Upgrade/Connection headers, so an upgrade request would be forwarded as a plain HTTP request and the handshake would fail. When on, an authenticated, rate-limited upgrade request is forwarded *with* its upgrade headers and, on the upstream's 101 Switching Protocols, EdgeGuard splices the two connections into a raw bidirectional tunnel. Response hardening / WAF body inspection don't apply to a tunneled connection (there is no buffered response). Non-upgrade requests are unaffected.
compress_responsesbooleanfalsegzip-compress responses for clients that send Accept-Encoding: gzip. Off by default. Skips already-compressed content types and (always) text/event-stream, so SSE streaming is never buffered by the compressor. Applied at the listener, so toggling it needs a restart (it is not part of the hot-reloadable policy).

[headers]

Response hardening: CSP, HSTS, cookies, leaky headers.

KeyTypeDefaultWhat it does
hstsbooleantrueSend Strict-Transport-Security, telling browsers to refuse plain HTTP for this host in future. Only meaningful once the site is genuinely HTTPS-only: a browser that has seen it cannot be talked out of it for the max-age.
cspstring"default-src 'self'"Content-Security-Policy value. The default is deliberately strict and will block inline scripts and third-party assets; widen it once you know what the app loads, and use csp_report_only while you find out.
csp_report_onlybooleanfalseSend the CSP as Content-Security-Policy-Report-Only instead of enforcing it. Lets you roll out / tighten a policy by collecting violations first without breaking the page.
csp_report_uristring""If set, a report-uri <value> directive is appended to the CSP so browsers POST violation reports there. Point it at EdgeGuard's own sink ("/__edgeguard/csp-report") to have them logged, or at any external collector.
referrer_policystring"no-referrer"Referrer-Policy value. The default sends no referrer at all, so internal URLs cannot leak to third parties through ordinary navigation.
permissions_policystring"geolocation=(), microphone=(), camera=()"Permissions-Policy value. The default denies geolocation, microphone and camera, which an app that needs them must explicitly re-enable.
frame_optionsstring"DENY"X-Frame-Options value: DENY, SAMEORIGIN, or empty to omit the header. Clickjacking protection for browsers predating CSP frame-ancestors.
force_secure_cookiesbooleantrueAdd Secure to every Set-Cookie the upstream returns, so cookies are never sent over plain HTTP. See httponly_cookies for the separate HttpOnly control.
httponly_cookiesbooleantrueAdd HttpOnly to Set-Cookie responses that lack it. On by default. Turn off (or use httponly_cookie_exempt) for apps that intentionally expose a cookie to JavaScript — e.g. a double-submit CSRF token the frontend must read from document.cookie.
httponly_cookie_exemptstring list[]Cookie NAMES that must never get HttpOnly, even when httponly_cookies is on. The surgical exemption for a readable double-submit CSRF cookie, e.g. ["doneyet_csrf"]. Names match exactly (cookies are case-sensitive).
stripstring listvec!["Server".into(), "X-Powered-By".into()]Response headers to strip (case-insensitive), e.g. ["Server", "X-Powered-By"].

[waf]

Pattern-based request rejection.

KeyTypeDefaultWhat it does
modestring"off""off" (default) | "report" | "block". report evaluates rules and logs/counts matches but forwards the request anyway; block rejects a matching request with 403.
sqlibooleantrueEnable the built-in SQL-injection heuristic ruleset.
xssbooleantrueEnable the built-in cross-site-scripting heuristic ruleset.
path_traversalbooleantrueEnable the built-in path-traversal heuristic ruleset.
inspect_pathbooleantrueInspect the request path + query string (matched raw and percent-decoded). Default true.
inspect_headersbooleanfalseInspect request header values. Off by default: header bytes (cookies, tokens, opaque blobs) are noisy and prone to false positives.
inspect_bodybooleanfalseInspect the request body (already capped by validation.max_body). Off by default.
ruleslist of tablesvec![]Operator-defined deny patterns, evaluated alongside the enabled built-in rulesets.

[access]

IP allow and deny lists.

KeyTypeDefaultWhat it does
allowstring list--CIDRs/IPs allowed in. Empty = allow all (subject to deny).
denystring list--CIDRs/IPs always rejected (takes precedence over allow).

[cors]

Cross-origin policy.

KeyTypeDefaultWhat it does
enabledbooleanfalseAnswer CORS preflights and decorate responses. Off by default: a proxy that adds permissive CORS headers by surprise is a security hole, not a convenience.
allow_originsstring listvec![]Allowed request origins, matched exactly (scheme + host + port), e.g. ["https://app.example.com"]. The single entry ["*"] allows any origin — but a wildcard cannot be combined with allow_credentials = true (the Fetch spec forbids it), so that combination is rejected at startup.
allow_methodsstring listvec![]Methods advertised in the preflight Access-Control-Allow-Methods. Empty = a sensible default set (GET, POST, PUT, PATCH, DELETE, OPTIONS, HEAD).
allow_headersstring listvec![]Request headers advertised in Access-Control-Allow-Headers. Empty = reflect whatever the browser asks for in Access-Control-Request-Headers (the common, permissive default).
expose_headersstring listvec![]Response headers the browser is allowed to read, advertised in Access-Control-Expose-Headers. Empty = none beyond the CORS-safelisted set.
allow_credentialsbooleanfalseSend Access-Control-Allow-Credentials: true so the browser may send cookies / HTTP auth. Requires explicit allow_origins (no "*").
max_agestring"600s"How long a browser may cache the preflight result, e.g. "600s", "1h". "0" omits the Access-Control-Max-Age header (the browser uses its own short default).

[tls]

TLS termination with a supplied certificate.

KeyTypeDefaultWhat it does
enabledboolean--Terminate TLS in EdgeGuard itself. Leave off when something upstream already does (a load balancer, a platform edge) and EdgeGuard only sees plaintext behind it.
cert_pathstring--PEM certificate chain (leaf first). When ACME is enabled this is where the obtained certificate is written/read.
key_pathstring--PEM private key (PKCS#8/PKCS#1/SEC1).
acmeAcmeCfg--Automatic certificate issuance. See [tls.acme].

[tls.acme]

Automatic certificates over ACME HTTP-01.

KeyTypeDefaultWhat it does
enabledbooleanfalseObtain and renew a certificate automatically over ACME HTTP-01 instead of reading cert_path/key_path from disk. Requires port 80 to be reachable from the CA.
domainsstring listvec![]Domains to request a certificate for (the first is the primary CN).
emailstring""Contact email for the ACME account (registration + expiry notices).
directory_urlstring"https://acme-staging-v02.api.letsencrypt.org/directory"ACME directory URL. Defaults to Let's Encrypt staging so a misconfiguration can't burn the strict production rate limits; switch to production explicitly.
cache_dirstring"./acme"Directory for the cached ACME account key (so renewals reuse the same account).
accept_tosbooleanfalseYou must set this to true to signify acceptance of the ACME provider's Terms of Service; EdgeGuard refuses to register otherwise.

[llm]

LLM gateway: metering, budgets, key vault, DLP.

KeyTypeDefaultWhat it does
enabledbooleanfalseTurn on the LLM gateway: token metering, cost attribution, budgets, the key vault and DLP. Off by default, and irrelevant unless the upstream is an LLM API.
api_stylestring"openai"Wire format. Only "openai" is understood today (the default).
modelstableBTreeMap::new()Per-model price book, keyed by the model string clients send. Prices are USD per 1,000,000 tokens. Example: [llm.models."gpt-4o"] input_per_1m = 2.5 / output_per_1m = 10.0.
on_unpriced_modelstring"count"What to do with a request whose model is not in [llm.models]: "count" (default — meter tokens, omit cost, forward the request) or "block" (reject 402 before it reaches the upstream, so an unpriced model is never served at a silent $0). "block" only bites when a price book is configured — a metering-only deployment (empty [llm.models]) never rejects.
budgetslist of tables[]Hard token/cost budgets (gateway L1). Empty by default (no enforcement — L0 metering only). Each [[llm.budgets]] is a ceiling enforced fail-closed via reserve→reconcile. See [BudgetCfg].
storestring"memory"Budget store backend: "memory" (single replica / default) or "redis" (shared across replicas — required for a true fleet-wide cap). "local" is treated as "memory".
redis_urlstring""Redis URL when store = "redis", e.g. redis://127.0.0.1:6379. Note: EDGEGUARD_REDIS_URL only overrides ratelimit.redis_url, not this key — set it here (or via pushed policy).
redis_prefixstring"edgeguard"Key prefix for budget keys in Redis (namespacing a shared server). Defaults to edgeguard.
fail_openbooleanfalseOn a budget-store error, allow the request (true) or reject it 503 (false, the default — fail-closed, so an outage can't silently uncap spend).
default_max_tokensinteger1024Completion tokens to assume when a request omits max_tokens, used only for the *reserve* estimate (the reservation is reconciled to actual usage afterward). Default 1024.
team_headerstring"x-edgeguard-team"Request header carrying the team / tag a request is attributed to, for the per-team budget scope and team chargeback. Case-insensitive; default x-edgeguard-team. A request without it falls into the shared _none team bucket.
keyslist of tables[]BYO-key vault + egress governance (gateway L2). Empty by default (no vault). Each [[llm.keys]] maps a client-facing virtual key to a real provider key (injected upstream, never returned to the client) plus an optional per-key model egress allowlist. When any key is configured, every proxied request must present a known virtual key. See [KeyEntryCfg].
dlpDlpCfgDlpCfg::default()Edge DLP — PII / secret detection + redaction (gateway L3). Off by default. See [DlpCfg].
telemetryTelemetryCfgTelemetryCfg::default()OTLP span emission (gateway L4) — SDK-free tracing to an OTel-native store. Off by default. See [TelemetryCfg].

[[llm.budgets]]

Hard spend or token caps. Repeatable.

KeyTypeDefaultWhat it does
namestring""Identifier (also the metric/log label and part of the store key). Required, non-empty.
scopestring"global"Keying dimension: "global", "key" (per authenticated principal), or "model".
unitstring"tokens""tokens" (prompt + completion) or "usd" (cost via the price book).
limitnumber0.0The ceiling, in unit: a token count, or — for unit = "usd" — dollars (e.g. 25.0).
windowstring"24h"Reset window, e.g. "1h", "24h", "30d". The budget resets at each window boundary.

[[llm.keys]]

Virtual key to provider key mapping. Repeatable.

KeyTypeDefaultWhat it does
virtual_keystring--The secret the client presents (Authorization: Bearer <virtual_key>). Required.
provider_keystring--The real upstream provider secret injected on the way out. Required. Prefer sourcing this from a pushed control-plane policy / secret store rather than committing it.
allowed_modelsstring list--Allowed model names for this key (egress allowlist). Empty = unrestricted; non-empty = only these models may be requested (others get 403).
labelstring--Optional label for logs/metrics/audit (never the secret). Defaults to a positional id.

[llm.dlp]

Detect and block or redact sensitive strings.

KeyTypeDefaultWhat it does
modestring"off"off | report | block | redact. Default off.
redact_stylestring"full"How a span is rewritten in redact mode: full ([REDACTED:<cat>], default) | mask (keep last 4) | hash (stable opaque token). See [crate::dlp::RedactStyle].
scan_requestbooleantrueScan the inbound request body (the prompt). Default true.
scan_responsebooleantrueScan the (buffered) response body and, in report mode, streamed frames. Default true.
stream_redactbooleanfalseIn redact mode, also rewrite *streamed* SSE frames (not just buffered bodies). Deterministic detectors only — NER never runs on the stream. Off by default: streaming redaction can only rewrite spans the carry buffer fully contains, so enable it deliberately. See [crate::dlp].
reversiblebooleanfalseReversible masking (redact mode only). When on, an inbound finding is replaced with a stable placeholder token (<edgeguard-<cat>-<n>>) instead of an irreversible [REDACTED] tag, and the placeholder→original map is kept for the request so the response is unmasked (buffered *and* streamed) back to the original value. The provider never sees the PII; the client gets its own data back — the round-trip an unmask keyed on shared state gets wrong. Off by default. When on, the response is unmasked rather than re-scanned/redacted (restore, not detect).
detect_emailbooleantrueBuilt-in detectors.
detect_credit_cardbooleantrueDetect card numbers. Pair with luhn_validate_credit_card to require a valid checksum, which removes most false positives from ordinary long digit strings.
luhn_validate_credit_cardbooleantrueRequire the Luhn checksum before flagging a digit run as a card (cuts false positives). Default true.
detect_secretsbooleantrueAWS keys, provider-style xx-… keys, and private-key blocks.
detect_ssnbooleantrueUS SSN (NNN-NN-NNNN). Default true.
detect_phonebooleanfalsePhone numbers. Off by default — false-positives on ordinary numeric runs.
detect_ibanbooleanfalseIBAN account numbers. Off by default — false-positives on uppercase+digit tokens.
detect_high_entropybooleanfalseHigh-entropy token sweep (catch-all). Off by default — can false-positive.
detect_prompt_injectionbooleanfalsePrompt-injection / jailbreak heuristics for agent traffic (a small, high-precision built-in deny set — "ignore previous instructions", "reveal your system prompt", etc.), reported under the prompt_injection category. Off by default (opt-in, report-first) since instructions to a model are legitimate traffic; enable and watch the counter before moving to block.
entropy_min_leninteger24Minimum token length the entropy sweep considers.
entropy_thresholdnumber4.0Per-character Shannon-entropy threshold (bits) for the entropy sweep.
gazetteer_termsstring list[]Dictionary deny-list: literal terms matched case-insensitively (Aho-Corasick), reported under the gazetteer category. The fast, many-term path for known names / codenames / identifiers.
custom_patternsstring list[]Extra regexes (linear-time regex syntax), all reported under the custom category.
nerNerCfgNerCfg::default()Optional ML NER family ([llm.dlp.ner]). Requires the ner cargo feature; catches person/address/org spans regex can't. See [NerCfg].

[llm.dlp.ner]

Optional ML entity detection for DLP. Requires the ner build feature.

KeyTypeDefaultWhat it does
enabledbooleanfalseTurn the NER family on. Requires the ner feature.
model_pathstring""Path to the ONNX model file.
tokenizer_pathstring""Path to the HuggingFace tokenizer.json.
labelsstring list[]Per-class label list in model id order (e.g. ["O","B-PER","I-PER","B-LOC", …]). Used to map argmax class ids back to entity labels.
thresholdnumber0.5Confidence floor in [0.0, 1.0]; spans below it are dropped. Default 0.5.
max_seq_leninteger256Max tokens fed to the model per scan (longer inputs are truncated). Default 256.

[llm.models]

Per-model prices, USD per 1M tokens.

KeyTypeDefaultWhat it does
input_per_1mnumber--USD per 1,000,000 prompt (input) tokens for this model, as billed by the provider.
output_per_1mnumber--USD per 1,000,000 completion (output) tokens for this model.
cached_per_1mnumber--USD per 1M cached prompt tokens. 0.0 = inherit input_per_1m.
reasoning_per_1mnumber--USD per 1M reasoning tokens. 0.0 = inherit output_per_1m.

[telemetry]

Logging and OpenTelemetry export.

KeyTypeDefaultWhat it does
enabledbooleanfalseMaster switch. Default false.
endpointstring""OTLP/HTTP traces endpoint, e.g. http://127.0.0.1:4318/v1/traces. Required when enabled.
sample_ratenumber1.0Fraction of LLM requests to emit a span for, 0.01.0 (deterministic per-trace sampling — the same trace always gets the same verdict). Default 1.0 (all).
service_namestring"edgeguard"service.name resource attribute on emitted spans. Default edgeguard.
capture_contentbooleanfalseCapture the (DLP-redacted) prompt/response as input.value/output.value on the span. Off by default — content leaves the gateway only when this is explicitly enabled, and when an [llm.dlp] engine is configured the captured content is redacted before it is emitted.
max_content_bytesinteger8192Cap on each captured content field in bytes (truncated past this). Default 8192.
timeout_msinteger2000Per-emit timeout for the background POST, in milliseconds. Default 2000.

[alerts]

Outbound notification of budget events.

KeyTypeDefaultWhat it does
enabledbooleanfalseMaster switch. Default false.
webhook_urlstring""Slack incoming-webhook URL (or any endpoint accepting { "text": … }). Required when enabled.
budget_consumed_thresholdnumber0.9Fire when a budget's consumed ratio (used/limit) reaches this (0.01.0+). Default 0.9.
timeout_msinteger2000Per-emit timeout for the background POST, in milliseconds. Default 2000.

[control_plane]

Managed-plane enrolment. Optional.

KeyTypeDefaultWhat it does
enabledbooleanfalseEnrol this instance with a managed control plane for pushed policy and quota. Off by default; EdgeGuard is fully functional without one.
urlstring""Base URL of the control plane, e.g. https://cp.example.
tenant_idstring""This edge's tenant id at the control plane.
edge_tokenstring""Per-tenant edge token (Bearer). Prefer EDGEGUARD_CP_EDGE_TOKEN.
poll_intervalstring"30s"How often to poll for policy, e.g. "30s".
report_intervalstring"60s"How often to flush a metrics delta, e.g. "60s".
forward_cspbooleantrueForward received CSP reports to the control plane (default true).
enforce_quotabooleanfalseEnforce the configured quota as a hard stop: poll the control plane's /v3/edge/{id}/quota and, while the edge is over its quota, reject the edge's traffic with 429 (a Retry-After reset hint). Off by default — opt in to turn the rate signal into a hard cap. Prefer EDGEGUARD_CP_QUOTA_ENFORCE.
quota_poll_intervalstring"30s"How often to poll the quota verdict, e.g. "30s". A failed poll keeps the last verdict, so a control-plane blip neither over- nor under-enforces.

Generated by scripts/build-config-reference.py from src/config.rs. Editing this file by hand accomplishes nothing — the next run overwrites it. Change the doc comment in the source instead.