Skip to main content

CLI & Configuration Reference

The elchi-shield binary is configured entirely at process start: command-line flags, with ELCHI_SHIELD_* environment-variable fallbacks, and an optional process-config file for sink settings. Policies are not configured here — they arrive as files in the watched directory (see Deploying Policies to Edges).

Precedence: flag → environment variable → default. Each flag's env var is ELCHI_SHIELD_ plus the flag name upper-cased with dashes as underscores (e.g. --config-dirELCHI_SHIELD_CONFIG_DIR), with two exceptions noted below.

Identity & config

FlagDefaultPurpose
--instance-id<hostname>-shieldInstance identity stamped on metrics, logs, and audit events
--config-dir/etc/elchi/elchi-shield/conf.dDirectory of policy config files to watch and hot-reload
--config-file(empty)Optional process-config YAML for the audit/metrics sink settings (DSN, OTLP endpoint, …); flags/env override it. Separate from --config-dir (policies)

Transport

FlagDefaultPurpose
--extproc-networkunixext_proc listener network: unix or tcp
--extproc-addr/etc/elchi/elchi-shield/extproc.sockSingle-listener ext_proc address (socket path or host:port). Installers typically use /run/elchi-shield/extproc.sock
--extproc-listener(none)Per-listener ext_proc socket, repeatable: id=network:addr (e.g. lst1=unix:/etc/elchi/elchi-shield/lst1.sock). Env: ELCHI_SHIELD_EXTPROC_LISTENERS (comma-separated)
--http-addr127.0.0.1:9001HTTP address for health/metrics — must be loopback
--allow-non-loopbackfalseDangerous: permit binding TCP to non-loopback addresses (exposes the sidecar)
--listener-id(empty)Envoy listener id this instance serves; the fallback listener metric label when Envoy sends no request attribute
Loopback only

Shield refuses to bind non-loopback TCP (for both ext_proc and the HTTP server) unless --allow-non-loopback is set. The sidecar inspects data-plane traffic and must never be reachable off-box; prefer Unix domain sockets, which are local by construction. See Wiring Shield into Envoy.

Limits & behavior

FlagDefaultPurpose
--max-body-bytes1048576 (1 MiB)Hard fallback body cap when a policy specifies none; an over-limit body is blocked, non-skippably
--xff-trusted-hops0Trusted reverse proxies in front of Envoy; the client IP is read this many hops in from the right of X-Forwarded-For (0 = the immediate hop Envoy appends — the secure default; the spoofable leftmost token is never trusted)
--max-inflight-body-bytes268435456 (256 MiB)Cap on total body bytes buffered across all concurrent streams (0 = unbounded); over-budget bodies are truncated → blocked
--watch-debounce300msConfig watcher debounce window (coalesces multi-file writes into one reload)
--default-allowtruePosture when no policy matches a request: allow (true) or deny (false)

Audit

FlagDefaultPurpose
--audit-exporter(auto)Audit sink: none | clickhouse | otel. Default: clickhouse if a DSN is set, otel if an OTLP endpoint is set, else none — there is no local-file sink
--audit-clickhouse-dsn(empty)ClickHouse DSN (the default audit sink when set)
--audit-clickhouse-table(empty)Audit table name (empty = elchi_shield_audit)
--audit-clickhouse-batch-size0Insert batch size (0 = default 500)
--audit-clickhouse-flush-interval1sTime-based flush so low-traffic rows land promptly (0 = size-only flushing)
--audit-clickhouse-ttl-days0Audit row TTL in days (0 = default 7, matching the collector's retention)
--audit-otel-endpoint(empty)OTLP endpoint for the otel audit exporter
--audit-otel-insecurefalseUse an insecure (plaintext) OTLP connection for audit
--audit-max-per-sec0Global cap on non-finding (allow-stream) audit events/sec (0 = unlimited). Findings are always audited

Metrics

FlagDefaultPurpose
--metrics-otlp-endpoint(empty)Push metrics to this OTel Collector (OTLP/gRPC host:port); empty = scrape /metrics only
--metrics-otlp-insecurefalsePlaintext gRPC to the metrics collector
--metrics-otlp-interval15sMetrics push interval

Runtime & diagnostics

FlagDefaultPurpose
--log-levelinfodebug, info, warn, error
--log-formatjsonjson or text
--log-sourcefalseInclude source file:line in logs (auto-on at debug level)
--pproftrueExpose /debug/pprof/* on the loopback HTTP server
--mem-limit-bytes0Soft memory limit (GOMEMLIMIT) in bytes; the GC reins in before the kernel OOM-kills the sidecar (0 = unset). Env: ELCHI_SHIELD_MEM_LIMIT. Set it well above --max-inflight-body-bytes
--gogc0GC target percent; higher = less frequent GC, more throughput, more heap. Pair with --mem-limit-bytes. 0 = runtime/GOGC default
--block-profile-rate0runtime.SetBlockProfileRate (0 = off); opt-in contention profiling
--mutex-profile-fraction0runtime.SetMutexProfileFraction (0 = off)
--shutdown-timeout15sGraceful shutdown timeout (drain ext_proc streams, flush audit)
--versionPrint the version and exit

The validate subcommand

elchi-shield validate /etc/elchi/elchi-shield/conf.d

Runs the config parse → validate → merge pipeline against a directory and reports every problem with file + field attribution (e.g. api.yaml: domains[2].routes[0].match.path_regex: invalid regex), touching no running state. elchi-client invokes it on every staged config bundle as a pre-commit gate — against the same binary version that will run the config — before committing files into the live directory (see Deploying Policies to Edges). The installer also runs it as a non-fatal ExecStartPre.

Exit codes: 0 = valid (an empty directory is valid — it means "clear"), 1 = invalid (errors on stderr), 2 = usage error.

Scope: parse and schema/field validation. Engine compilation (Coraza ruleset build, data-file loading) is not run here; a compile-stage failure is still caught at the real reload, where the last-good config stays active.

On-disk paths

PathWhat it is
/etc/elchi/elchi-shield/conf.d/The watched policy directory (--config-dir), managed by elchi-client
/etc/elchi/elchi-shield/extproc.sockDefault ext_proc UDS path (flag default); the installer uses /run/elchi-shield/extproc.sock (a systemd RuntimeDirectory) instead
/etc/elchi/elchi-shield/audit.envRestricted EnvironmentFile holding the ClickHouse DSN (installer-managed; the DSN may carry credentials, so it never appears in the unit file)
/etc/elchi/bin/elchi-shieldThe binary (installer layout)
/etc/systemd/system/elchi-shield.serviceThe hardened systemd unit

Operational quick checks on an edge:

systemctl status elchi-shield
journalctl -u elchi-shield -f
curl -s http://127.0.0.1:9001/healthz
curl -s http://127.0.0.1:9001/configz | jq

For the metric catalog, audit schema, and health endpoints behind --http-addr, see Metrics, Audit & Health.