The Arion configuration file is a single YAML document, passed with --config, whose top-level keys tune the process and carry the proxy resources inside envoy_bootstrap.
Top-level keys
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
runtime | object | no | see below | Worker cores, Tokio runtimes and scheduler tuning. |
logging | object | no | stdout, error | Process log level and destination. |
access_logging | object | no | unset | Access-log pipeline tuning, rotation and custom operators. |
metrics | object | no | unset | Metric partition keys, renames and custom metrics. |
timezone | object | no | UTC | Local timezone for log timestamps. |
envoy_bootstrap | object | no | unset | Proxy resources in Envoy Bootstrap form. The canonical dialect. |
bootstrap | object | no | empty | Proxy resources in Arion's native form. Mutually exclusive with envoy_bootstrap. |
Setting both bootstrap and envoy_bootstrap fails with only one of 'bootstrap' and 'envoy_bootstrap' may be set. If neither is present, the file contributes no proxy resources; a bootstrap must then come from the --with-envoy-bootstrap flag (see Command line), which also replaces either key when both a file and the flag are given.
runtime
Values here are overridden by environment variables, then by command-line flags, in that order of precedence (environment wins).
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
num_cpus | integer ≥ 1 | no | detected CPUs | Cores to use. Detection honours container cgroup CPU limits (v1 and v2, quota rounded up). |
num_runtimes | integer ≥ 1 | no | 1 | Number of Tokio worker runtimes the cores are split across. |
num_service_threads | integer ≥ 1 | no | 1 | Threads for background service tasks. |
global_queue_interval | integer ≥ 1 | no | Tokio default | Scheduler ticks between global queue polls. |
event_interval | integer | no | Tokio default | Scheduler ticks between I/O event polls. |
max_io_events_per_tick | integer ≥ 1 | no | Tokio default | Maximum I/O events processed per tick. |
affinity_strategy | object | no | unset | Pin worker threads to cores: type: auto, or type: nodes / type: runtimes with map, a list of core-id lists. |
codemode.pool_capacity | integer ≥ 1 | no | 128 | Sandboxes the whole process can run at once for MCP code mode. A listener's max_concurrent_executions cannot exceed it. Needs the codemode build feature. |
codemode.max_memory_bytes | integer ≥ 1 | no | 67108864 (64 MiB) | Largest memory any one code-mode sandbox may use. A listener's memory_limit_bytes cannot exceed it. |
runtime:
num_cpus: 2
num_runtimes: 2
event_interval: 31
affinity_strategy:
type: auto
codemode:
pool_capacity: 64
max_memory_bytes: 33554432
The codemode values size one sandbox pool shared by every code-mode listener in the process. It is created when the first code-mode listener loads.
logging
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
log_level | string | no | error | A tracing filter directive, e.g. info or arion_lib=debug,info. The RUST_LOG environment variable overrides it. |
log_directory | string | no | . | Directory for the log file when log_file is set. |
log_file | string | no | unset | File name for process logs. When set, logs move from stdout to an hourly-rotated file. |
logging:
log_level: "info"
log_directory: /var/log/arion
log_file: arion.logaccess_logging
Tunes the shared access-log pipeline. The log destinations and formats themselves are configured per listener and per HTTP connection manager inside envoy_bootstrap — see access logs.
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
num_instances | integer ≥ 1 | no | 1 | Number of access-log writer instances. |
queue_length | integer ≥ 1 | no | 1024 | Queue length per writer between workers and the log writer. |
log_rotation | string | no | unset | Rotation frequency for file sinks: minutely, hourly or daily. |
log_max_size | integer | no | unset | Maximum size in bytes before a file rotates. |
max_log_files | integer ≥ 1 | no | 10 | Rotated files kept before the oldest is deleted. |
blocking | bool | yes | — | When true, workers block if the queue is full instead of dropping entries. |
incoming_request_header | string | no | unset | Header holding a base64-encoded JSON object, read when the request arrives; its keys feed custom_operators. |
ext_proc_request_header | string | no | unset | Same, read from the ext_proc request exchange. |
upstream_request_header | string | no | unset | Same, read when the request leaves for the upstream. |
incoming_response_header | string | no | unset | Same, read when the upstream response arrives. |
ext_proc_response_header | string | no | unset | Same, read from the ext_proc response exchange. |
downstream_response_header | string | no | unset | Same, read when the response is sent downstream. |
wasm_header | string | no | unset | Same, read from WASM filter output. |
custom_operators | list of strings | no | [] | Operator names usable in access-log format strings, filled from the captured JSON objects. |
access_logging:
blocking: false
num_instances: 2
queue_length: 4096
log_rotation: daily
max_log_files: 14
incoming_request_header: x-arion-metadata
custom_operators: [TENANT, PLAN]metrics
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
user_key | object | no | unset | Partition key for user metrics: source is !HeaderName <name> or Sni, plus an optional attribute_name. |
custom_keys | list | no | [] | Additional partition keys for custom metrics; each entry has source: !HeaderName <name> and optional attribute_name. |
rename | map | no | {} | Renames emitted metrics, old name to new name. |
custom_metrics | object | no | empty | Per-hook metric lists under incoming_request, ext_proc_request, upstream_request, incoming_response, ext_proc_response, downstream_response and wasm. Each entry is a !Counter, !Gauge or !Histogram with name, description, header_name, optional attribute_name, and buckets for histograms (numbers, or MAX). |
metrics:
user_key:
source: !HeaderName x-user-id
attribute_name: user
custom_metrics:
upstream_request:
- !Counter
name: api_requests
description: Requests forwarded upstream
header_name: x-api-key
attribute_name: api_key
See the metrics list for what Arion emits.
timezone
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
local | string | yes | — | IANA timezone name, e.g. Europe/Paris. Empty or UTC keeps UTC. Daylight-saving transitions are tracked in the background. |
timezone:
local: Europe/Parisenvoy_bootstrap
Contains a standard Envoy Bootstrap: node, admin, static_resources with listeners, clusters and secrets, and dynamic_resources for xDS. Field-level reference lives with each resource: listeners, routes, clusters, secrets, and the supported-configuration matrix for the full accepted subset.
envoy_bootstrap:
static_resources:
listeners:
- name: listener_http
address:
socket_address: { address: 0.0.0.0, port_value: 8080 }
filter_chains:
- name: default
filters:
- name: http
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager
codec_type: HTTP1
http_filters:
- name: envoy.filters.http.router
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.http.router.v3.Router
route_config:
name: main
virtual_hosts:
- name: backend
domains: ["*"]
routes:
- match: { prefix: "/" }
route: { cluster: api }
clusters:
- name: api
type: STATIC
connect_timeout: 0.25s
lb_policy: ROUND_ROBIN
load_assignment:
endpoints:
- lb_endpoints:
- endpoint:
address:
socket_address: { address: 127.0.0.1, port_value: 5678 }
The bootstrap key accepts the same resources in Arion's native serialization; that form is documented only on the native bootstrap page.
Unknown and unsupported fields
- Top level: keys other than the seven above are ignored during deserialization.
- Inside
envoy_bootstrap: parsing is strict. Unknown or misspelled field names fail to deserialize, and the error names the YAML path. Both protobuf snake_case (filter_chains) and JSON camelCase (filterChains) spellings are accepted. - Known Envoy fields that Arion does not implement are refused at load with an
unsupported fielderror rather than silently ignored — this is the compatibility promise. A field marked unsupported only errors when it is actually set to a non-default value.