Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Configuration Reference

This page documents runtime-relevant configuration fields and defaults.

Topic Wire Format

  • Topic wire subjects always use . as separator.
  • Per-schema topic.separator is no longer used.
  • Token values are percent-encoded for reserved chars (., *, >, %) before writing to backend subjects.

See Topic Encoding for rules and examples.

application

FieldTypeDefaultNotes
hoststringnoneBind address.
portu16noneBind port.
base_urlstringhttp://localhostUsed in generated CloudEvent source links.
static_files_pathstring/app/staticStatic asset root for homepage assets.

logging

FieldTypeDefaultNotes
levelstringimplementation defaultExample: info, debug, warn, error.
formatstringimplementation defaultKept for compatibility; output is OTel-aligned JSON.

auth

Authentication is optional. When disabled (default), all API endpoints are publicly accessible only if schemas do not define stream auth rules. Startup fails if global auth is disabled while a schema sets auth.required=true or non-empty auth.read_roles/auth.write_roles.

When enabled:

  • Admin endpoints always require a valid JWT and an admin role.
  • Stream endpoints (notify, watch, replay) enforce authentication only when the target schema has auth.required: true.
  • Schema endpoints (/api/v1/schema) are always public.
  • In trusted_proxy mode, Aviso validates Authorization: Bearer <jwt> locally with jwt_secret.
FieldTypeDefaultNotes
enabledboolfalseSet to true to enable authentication.
mode"direct"|"trusted_proxy""direct"direct: forward credentials to auth-o-tron. trusted_proxy: validate forwarded JWT locally.
auth_o_tron_urlstring""auth-o-tron base URL. Required when enabled=true and mode=direct.
jwt_secretstring""Shared HMAC secret for JWT validation. Required when enabled=true. Not exposed via /api/v1/schema endpoints and redacted when auth settings are serialized or logged.
admin_rolesmap<string, string[]>{}Realm-scoped roles for admin endpoints (/api/v1/admin/*). Must contain at least one realm with non-empty roles when enabled=true.
timeout_msu645000Timeout for auth-o-tron requests (milliseconds). Must be > 0.

Per-stream auth (notification_schema.<event_type>.auth)

FieldTypeDefaultNotes
requiredboolMust be explicitly set whenever an auth block is present. When true, the stream requires authentication.
read_rolesmap<string, string[]>Realm-scoped roles for read access (watch/replay). When omitted, any authenticated user can read. Use ["*"] as the role list to grant realm-wide access.
write_rolesmap<string, string[]>Realm-scoped roles for write access (notify). When omitted, only users matching global admin_roles can write. Use ["*"] as the role list to grant realm-wide access.
pluginsstring[](none)Optional list of authorization plugins to run after role-based checks. Currently supported: "ecpds" (requires --features ecpds build). On a build without the required feature, startup fails with a clear error pointing at the offending stream. (Silent skip would widen access.) Empty plugins: [] is rejected; omit the field instead. Plugins only run when auth.required is true.

See Authentication for detailed setup, client usage, and error responses.

ecpds

Optional ECPDS destination authorization. Only available when built with --features ecpds. When configured, streams can reference the "ecpds" plugin in their auth.plugins list to enforce destination-level access control on watch and replay requests.

FieldTypeDefaultNotes
usernamestringnoneService account username used for HTTP Basic Auth to ECPDS. Must not be empty.
passwordstringnoneService account password. Redacted to [REDACTED] in Debug output (and therefore in any structured-log dump of the configuration). Must not be empty. The /api/v1/schema endpoint never exposes the top-level ecpds block at all, only per-event identifier and payload fields, so the password is not reachable through it.
serversstring[]noneList of ECPDS server base URLs. Use https:// for any reachable host: the plugin authenticates with HTTP Basic Auth, so plain http:// to a real host would put the service-account password and per-user destination lookups on the wire without TLS. Plain http:// is accepted only for loopback (127.0.0.1, [::1], localhost) for local testing; a typo from https:// to http:// on a non-loopback host fails closed at startup. Each URL must parse with no query string and no fragment. Path prefixes (e.g. https://proxy.example/ecpds-api/) are accepted. The plugin appends /ecpds/v1/destination/list?id=<username> itself.
match_keystringnoneIdentifier field to match against the user's destination list (e.g. "destination"). Must be a single bare identifier name (no whitespace, / or NUL) and must be present in the schema's identifier with required: true (so the value is guaranteed before the plugin runs). It does NOT need to appear in topic.key_order; the plugin reads the value from the request's canonicalized identifier params, not from topic routing.
target_fieldstring"name"JSON field to extract from each ECPDS destination record. Records that lack this field are silently skipped (logged at info as auth.ecpds.fetch.skipped_record).
cache_ttl_secondsu64300How long (in seconds) to cache a user's destination list before re-fetching. Must be > 0.
max_entriesu6410000Maximum number of distinct usernames held in the cache; eviction policy is moka's TinyLFU. Must be > 0.
request_timeout_secondsu6430Total wall-clock budget for a single ECPDS HTTP request: DNS lookup, TCP connect, TLS handshake, request send, AND response body read must all complete within this. (reqwest::ClientBuilder::timeout is a total deadline that starts when the request is issued; tune this as an upper bound that includes connection setup, not just response time.) Must be > 0.
connect_timeout_secondsu645Sub-budget within request_timeout_seconds for the dial-through-TLS-handshake phase only (DNS + TCP connect + TLS). If this elapses first the request fails with a connect timeout; otherwise the remainder of request_timeout_seconds covers request send and response body. Must be > 0.
partial_outage_policy"strict"|"any_success""strict"How tolerant the merge is when one configured server fails. The destination list itself is always the union of per-server responses. strict: every server must respond successfully or the call fails with 503. any_success: take the union of whichever servers responded; only fails if no server responded. See ECPDS Destination Authorization for the failure-tolerance trade-off.

See ECPDS Destination Authorization for setup and runtime behavior, and the ECPDS runbook for operational triage.

metrics

Optional Prometheus metrics endpoint. When enabled, a separate HTTP server serves /metrics on an internal port for scraping by Prometheus/ServiceMonitor. This keeps metrics isolated from the public API.

FieldTypeDefaultNotes
enabledboolfalseEnable the metrics endpoint.
hoststring"127.0.0.1"Bind address for the metrics server. Defaults to loopback to avoid public exposure.
portu16noneRequired when enabled=true. Must differ from application.port.

Exposed metrics:

MetricTypeLabelsDescription
aviso_notifications_totalcounterevent_type, statusTotal notification requests.
aviso_sse_connections_activegaugeendpoint, event_typeCurrently active SSE connections.
aviso_sse_connections_totalcounterendpoint, event_typeTotal SSE connections opened.
aviso_sse_unique_users_activegaugeendpointDistinct users with active SSE connections.
aviso_auth_requests_totalcountermode, outcomeAuthentication attempts.

A binary built with --features ecpds registers the following five metrics. The unlabelled counters and the gauge appear as Prometheus series at process startup. The two labelled counters (access_decisions_total, fetch_total) are pre-initialised at startup with every documented outcome value, so each outcome label appears as a series at zero before any ECPDS traffic; this lets alert rules of the form rate(metric{outcome="error"}[5m]) > 0 start evaluating on a known-zero baseline rather than on a missing series.

MetricTypeLabelsDescription
aviso_ecpds_cache_hits_totalcounter(none)ECPDS destination cache hits (requests served from cache without an upstream call).
aviso_ecpds_cache_misses_totalcounter(none)ECPDS destination cache misses (requests not served from cache). Includes coalesced waiters that did not trigger an upstream call themselves; aviso_ecpds_fetch_total is the right metric for "actual upstream calls".
aviso_ecpds_cache_sizegauge(none)Number of usernames in the ECPDS destination cache, sampled from moka after eviction passes. Expired entries are pruned by moka asynchronously, so this gauge can briefly include not-yet-pruned expired entries until the next pending-tasks run.
aviso_ecpds_access_decisions_totalcounteroutcomeAccess decisions. outcome ∈ {allow, deny_destination, deny_match_key_missing, unavailable, admin_bypass, error}.
aviso_ecpds_fetch_totalcounteroutcomeUpstream fetch outcomes (recorded once per access check whose request actually ran the upstream call; coalesced waiters do not contribute). outcome ∈ {success, http_401, http_403, http_4xx, http_5xx, invalid_response, unreachable}.

Process-level metrics (CPU, memory, open FDs) are automatically collected on Linux.

notification_backend

FieldTypeDefaultNotes
kindstringnonejetstream or in_memory.
in_memoryobjectoptionalUsed when kind = in_memory.
jetstreamobjectoptionalUsed when kind = jetstream.

notification_backend.in_memory

FieldTypeDefaultNotes
max_history_per_topicusize1Retained messages per topic in memory.
max_topicsusize10000Max tracked topics before LRU-style eviction.
enable_metricsboolfalseEnables extra internal metrics logs.

See InMemory Backend for operational caveats.

notification_backend.jetstream

FieldTypeDefaultRuntime usage summary
nats_urlstringnats://localhost:4222NATS connection URL.
tokenstring?NoneToken auth; NATS_TOKEN env fallback.
timeout_secondsu64?30NATS connection timeout for each startup connect attempt (> 0).
retry_attemptsu32?3Startup connect attempts before backend init fails (> 0).
max_messagesi64?NoneStream message cap.
max_bytesi64?NoneStream size cap in bytes.
retention_timestring?NoneDefault stream max age (s, m, h, d, w; for example 30d).
storage_typestring?filefile or memory (parsed as typed enum at config load).
replicasusize?NoneStream replicas.
retention_policystring?limitslimits/interest/workqueue (parsed as typed enum at config load).
discard_policystring?oldold/new (parsed as typed enum at config load).
enable_auto_reconnectbool?trueEnables/disables NATS client reconnect behavior.
max_reconnect_attemptsu32?5Mapped to NATS max_reconnects (0 => unlimited).
reconnect_delay_msu64?2000Reconnect delay and startup connect retry backoff (> 0).
publish_retry_attemptsu32?5Retry attempts for transient publish channel closed failures (> 0).
publish_retry_base_delay_msu64?150Base backoff in milliseconds for publish retries (> 0).

See JetStream Backend for detailed behavior.

notification_schema.<event_type>.payload

Schema-level payload contract for notify requests.

FieldTypeExampleNotes
requiredbooltrueWhen true, /notification rejects requests without payload.

Behavior details and edge cases are documented in Payload Contract.

notification_schema.<event_type>.storage_policy

Optional per-schema storage settings validated at startup against selected backend capabilities.

FieldTypeExampleNotes
retention_timestring7d, 12h, 30mDuration literal (s, m, h, d, w).
max_messagesinteger100000Must be > 0.
max_sizestring512Mi, 2GSize literal (K, Ki, M, Mi, G, Gi, T, Ti).
allow_duplicatesbooltrueBackend support is capability-gated.
compressionbooltrueBackend support is capability-gated.

Field behavior:

  • retention_time overrides backend-level retention for the schema stream.
  • max_messages overrides backend-level message cap for the schema stream.
  • max_size overrides backend-level byte cap for the schema stream.
  • allow_duplicates = false maps to one message per subject (latest kept); true removes this cap.
  • compression = true enables stream compression when backend supports it.

Startup behavior:

  • Invalid retention_time/max_size format fails startup.
  • Unsupported fields for selected backend fail startup.
  • Validation happens before backend initialization.
  • With in_memory, all storage_policy fields are currently unsupported (startup fails if provided).

Runtime application behavior:

  • storage_policy is applied on stream create and reconciled for existing JetStream streams when those streams are accessed by Aviso.
  • Aviso-managed stream subject binding is also reconciled to the expected <base>.> pattern.
  • Mutable fields (retention/limits/compression/duplicates/replicas) are updated when drift is detected.
  • Recreate stream(s) only when you need historical data physically rewritten with new settings.

Example:

notification_backend:
  kind: jetstream
  jetstream:
    nats_url: "nats://localhost:4222"
    publish_retry_attempts: 5
    publish_retry_base_delay_ms: 150

notification_schema:
  dissemination:
    topic:
      base: "diss"
      key_order: ["destination", "target", "class", "expver", "domain", "date", "time", "stream", "step"]
    storage_policy:
      retention_time: "7d"
      max_messages: 2000000
      max_size: "10Gi"
      allow_duplicates: true
      compression: true

watch_endpoint

FieldTypeDefaultNotes
sse_heartbeat_interval_secu6430SSE heartbeat period.
connection_max_duration_secu643600Maximum live watch duration.
replay_batch_sizeusize100Historical fetch batch size.
max_historical_notificationsusize10000Replay cap for historical delivery.
replay_batch_delay_msu64100Delay between historical replay batches.
concurrent_notification_processingusize15Live stream CloudEvent conversion concurrency.

Custom config file path

Set AVISOSERVER_CONFIG_FILE to use a specific config file instead of the default search cascade:

AVISOSERVER_CONFIG_FILE=/path/to/config.yaml cargo run

When set, only this file is loaded as a file source (startup fails if it does not exist). The default locations (./configuration/config.yaml, /etc/aviso_server/config.yaml, $HOME/.aviso_server/config.yaml) are skipped. AVISOSERVER_* field-level overrides still apply on top.

Environment override examples

AVISOSERVER_APPLICATION__HOST=0.0.0.0
AVISOSERVER_APPLICATION__PORT=8000
AVISOSERVER_NOTIFICATION_BACKEND__KIND=jetstream
AVISOSERVER_NOTIFICATION_BACKEND__JETSTREAM__NATS_URL=nats://localhost:4222
AVISOSERVER_NOTIFICATION_BACKEND__JETSTREAM__TOKEN=secret
AVISOSERVER_WATCH_ENDPOINT__REPLAY_BATCH_SIZE=200
AVISOSERVER_AUTH__ENABLED=true
AVISOSERVER_AUTH__JWT_SECRET=secret
AVISOSERVER_METRICS__ENABLED=true
AVISOSERVER_METRICS__PORT=9090