Configuration overview
Configuration is read from a single file in TOML or YAML. The format is chosen from the path’s extension: .yaml / .yml → YAML; .toml and anything else (including a missing extension) → TOML. Pass the file path as the positional CONFIG argument or via HUGINN_CONFIG_PATH:
huginn-proxy config.tomlhuginn-proxy config.yamlHUGINN_CONFIG_PATH=config.yaml huginn-proxyValidate a config file without starting the proxy:
huginn-proxy --validate config.tomlhuginn-proxy --validate config.yamlhuginn-proxy --validate --strict config.yaml # non-zero exit if any config warningPrint the validated, effective configuration as deterministic JSON (implies --validate, then exits):
huginn-proxy --print-effective-config config.tomlhuginn-proxy --validate --print-effective-config config.yamlIncludes defaults, normalizations, and fallbacks. Header values and CSP policy are replaced with <redacted>; certificate/key/CA paths appear only as configured/not-configured booleans. Diagnostics go to stderr so stdout stays valid JSON for jq or CI.
Strict keys: unknown or misplaced keys are rejected at every nesting level during startup, --validate, and hot reload (they are never silently ignored). This catches typos and YAML indentation mistakes; a failed reload keeps the currently active config.
Config warnings: load, --validate, and hot reload also emit non-fatal WARNs for likely mistakes (over-broad trusted_proxies, self-defeating rate_limit, security overrides that drop parent protection, etc.). --validate prints a warning count; --strict exits non-zero on any warning (useful in CI).
Hot reload: dynamic sections update on SIGHUP or the filesystem watcher ([reload].watch, default true) without dropping connections. Static sections require a process restart. Invalid reloads keep the current config. See the SETTINGS.md reference on GitHub for the static/dynamic split per section.
Environment variables
Section titled “Environment variables”These apply to the huginn-proxy process. They do not change how TOML vs YAML is detected: that is always from the config file path you pass (positional argument or HUGINN_CONFIG_PATH): extension .yaml / .yml → YAML, .toml or other → TOML.
| Variable | Role |
|---|---|
HUGINN_CONFIG_PATH |
Path to the config file when you do not pass it as the sole CLI argument (equivalent to huginn-proxy /path/to/config). |
RUST_LOG |
Overrides log filtering at the Rust tracing layer; can override [logging].level. See Logging. |
File watching and debounce live in the config file under [reload] (not env vars): watch (default true) and debounce_secs (default 60). See SETTINGS.md — [reload].
eBPF (TCP SYN path): when the proxy uses pinned BPF maps, it reads HUGINN_EBPF_PIN_PATH (must match the agent) and optionally HUGINN_EBPF_RECONNECT_POLL_SECS. Map capacity (HUGINN_EBPF_SYN_MAP_MAX_ENTRIES) is agent-only: the proxy reads it from the pinned syn_meta map. Capture backend (HUGINN_EBPF_CAPTURE: xdp-native / xdp-skb / tc) is agent-only. See eBPF TCP setup.
Canonical field tables and copy-paste snippets: SETTINGS.md (same content as the shipped reference in the repo).
Use the pages below for narrative, behavior, and examples alongside the reference.
Top-level keys
Section titled “Top-level keys”Rough split: static blocks need a process restart to take effect; dynamic blocks reload on SIGHUP or the config file watcher (see SETTINGS.md for edge cases).
Static (restart required)
Section titled “Static (restart required)”| Key | Page / notes |
|---|---|
[listen] |
Listen (including proxy_protocol) |
[tls] |
TLS (transport options only; cert/key paths are per domain) |
[fingerprint] |
Fingerprinting |
[timeout] |
Timeout |
[logging] |
Logging |
[telemetry] |
Telemetry |
[reload] |
Filesystem watch / debounce (SETTINGS.md) |
Dynamic (hot-reloadable)
Section titled “Dynamic (hot-reloadable)”| Key | Page / notes |
|---|---|
preserve_host |
Top-level bool: Routes (forwarding Host upstream) |
[[backends]] |
Backends |
[[domains]] |
Routes (hostname matching, TLS certs, nested routes, per-domain client_ca_path) |
[security.trusted_proxies] |
Security (cidrs + insecure for XFF / PROXY client-IP resolution) |
[security.ip_filter] |
IP filtering |
[security.rate_limit] |
Rate limiting |
[security.headers] |
Security (HSTS, CSP, custom: reloadable) |
[headers] |
Headers |
[backend_pool] |
Backends |
[security] also includes max_connections (Security), which is static (restart required). Treat [security] as mixed; use the pages above for each subsection.
Scope and override summary
Section titled “Scope and override summary”Security policies and headers can be set at three scopes (global, domain, and route), and each policy has its own override semantics:
| Policy | Global | Domain | Route | Semantics |
|---|---|---|---|---|
ip_filter |
yes | yes | yes | Whole-block replace |
rate_limit |
yes | yes | yes | Whole-block replace |
security.headers (HSTS, CSP, custom) |
yes | yes | yes | Whole-block replace |
[headers] (add / remove) |
yes | yes | yes | Additive cascade |
fingerprinting |
no | yes | yes | Route, domain, or default true |
trusted_proxies |
yes | no | no | Global only |
max_connections |
yes | no | no | Global only (static) |
Whole-block replace: the most specific scope that defines a block wins entirely. A partial override drops the parent’s other keys. For example, a route rate_limit with only requests_per_second and no enabled = true disables rate limiting for that route. Re-state every key you need.
Additive cascade: global, domain, and route headers accumulate in order; for a given header name the most specific scope wins.
The proxy logs a WARN at load and on every hot reload when an override drops a parent-enabled protection.
See Security and Rate limiting for examples.
Examples (repository only)
Section titled “Examples (repository only)”Full config samples are not copied into this site: they would drift from the repo and are tedious to keep in sync. Use the checked-in files as the source of truth:
- Smallest end-to-end file: the “Complete minimal example” in SETTINGS.md (TOML and YAML at the bottom of that document).
- Full-featured reference (listen, TLS, routes, headers, fingerprinting, security, telemetry, etc.):
examples/config/compose.yamlandcompose.tomlin the same folder.
Related
Section titled “Related”- How it works: request path through the proxy
- Quick start: first request end-to-end