Skip to content

Configuration reference

Yagra is configured entirely through environment variables. There is no configuration file.

The binaries read their environment once at process start, so changing a value means restarting the affected container.

With the bundled compose files you set variables in a .env file next to the compose file. See the installation guide for the initial setup.

There are two kinds of variables on this page:

  • Variables read by the binaries (yagra-core, yagra-poller, or both). These work in any deployment, whether or not you use the bundled compose files.
  • Compose-only variables, consumed by Docker Compose or the bundled NATS server configuration when interpolating the compose files. The binaries never see them. They are listed in their own section at the end.

Secrets are files, not values. The three secret-bearing variables — YAGRA_KEK_FILE, YAGRA_SESSION_KEY_FILE, and YAGRA_NATS_CALLOUT_SEED_FILE — carry the path to a mounted file.

The secret itself never appears in an environment value, so it is not exposed through docker inspect or the process environment.

Boolean variables (YAGRA_ENABLE_HA) are true for 1, true, yes, or on (case-insensitive), and false for anything else, including unset.

Two are on by default and read the other way round — 0, false, no or off turns them off, and anything else (including unset) leaves them on: YAGRA_ENABLE_MCP (see its row under MCP) and YAGRA_STORE_FORWARD (see its row under store-and-forward).

In the tables below, a dash (—) in the Default column means the variable has no default. The Purpose cell describes what happens without it.

Variables read by the yagra-core binary — orchestration, scheduling, and the northbound REST API.

Each kind of data lives in the store built for it — see the architecture overview.

Core needs PostgreSQL, the bus, and VictoriaMetrics to run in live mode. The other stores are optional.

Variable Default Purpose
YAGRA_DATABASE_URL — (required) PostgreSQL connection URL for the metadata store. The connection is retried 30 times at 2 s intervals at startup.
YAGRA_TSDB_URL — (required) VictoriaMetrics base URL — the time-series metrics store.
YAGRA_REDIS_URL unset Redis URL for the volatile poller liveness/assignment mirror. Unset, blank, or unreachable ⇒ core degrades to a no-op mirror with a one-time log — never fatal. The mirror is rebuildable, so losing Redis is safe.
YAGRA_LOGS_URL unset VictoriaLogs base URL — the searchable passive-event store. Unset ⇒ passive events stay entirely in PostgreSQL.
YAGRA_CLICKHOUSE_URL unset ClickHouse HTTP URL — the traffic-flow store. Unset ⇒ the flow receiver is disabled and the flow API returns 503.
YAGRA_PG_MAX_CONNECTIONS 20 Connection-pool ceiling for the whole core process. With high availability enabled, the leader’s advisory-lock connection is one extra on top of this pool — size PostgreSQL’s max_connections accordingly.
YAGRA_VM_WRITERS one per core, up to 4 How many tasks write metrics to VictoriaMetrics. Samples are sharded by node, so one node’s series still arrives in order. The queue below is the tier’s total and is divided among these tasks, not repeated per task. Set 1 for the single-writer behaviour of earlier releases. A larger number is clamped to 4, and the clamp is logged.
YAGRA_RESULT_QUEUE_CAP 16384 How many poll results core may hold while VictoriaMetrics is slow to accept writes. Everything past this is dropped. That is by design — metrics are the best-effort tier and the next poll refills the sample — but a drop is still a gap in the graphs. Size it from yagra_vm_backlog_needed_high_water on your own deployment: that metric reports how deep an unbounded queue would have gone. Memory cost is linear, roughly 21 KB per queued result on a node with 24 ports. A larger number is clamped to 131072, and the clamp is logged.
Variable Default Purpose
YAGRA_API_ADDR 0.0.0.0:8080 Bind address for the REST API. Also read by the container health check to derive its probe port.
YAGRA_ADMIN_PASSWORD unset First-boot password for the admin account, consulted only when the account is first seeded. Unset or blank ⇒ core generates a random one-time bootstrap password and logs it once — there is no well-known default password.
YAGRA_SESSION_KEY_FILE unset Path to a mounted HMAC session-signing key (64 hex characters or 32 raw bytes). Enables stateless signed session tokens that survive core restarts and work across an HA pair. Unset ⇒ opaque per-process tokens.
YAGRA_PAT_OIDC_IDLE_DAYS 30 How long an API token owned by an SSO-provisioned account survives its owner not signing in. Yagra is never told when an identity provider disables an account, so the owner going quiet is the only signal available; local- and service-account-owned tokens are unaffected. Clamped to 1–365; it cannot be switched off.
YAGRA_KEK_FILE unset Path to the mounted key-encryption key (KEK) that envelope-encrypts monitoring credentials at rest.

The WebUI is served over HTTPS by default.

Core holds the certificate of record in PostgreSQL, envelope-encrypted under the same KEK as every other secret, and materializes it into a volume the web container reads. See Security for the full picture.

Variable Default Purpose
YAGRA_TLS_DIR unset Directory core materializes the certificate bundle into, for the web container’s nginx to read. Unset ⇒ nothing is written — the shape for a deployment that terminates TLS somewhere else. The bundled compose files set it to /var/lib/yagra/tls.
YAGRA_TLS_SELF_SIGNED_SANS unset Comma-separated names the bootstrap self-signed certificate covers. Unset ⇒ loopback plus the container’s hostname. Nothing inside the container can know the address you will actually type, so either set this or regenerate from Settings ▸ TLS with the right names.
YAGRA_API_BIND unset (⇒ 0.0.0.0) Host interface core’s plaintext API port is published on. Core reads it too, but only so Settings ▸ TLS can report whether that port is still reachable from the LAN — it does not change what core binds inside the container. Set it to 127.0.0.1 after moving Prometheus scrapes, webhook senders and API scripts to the TLS edge.

These four are read by the web container’s entrypoint, not by either Rust binary:

Variable Default Purpose
YAGRA_WEB_TLS on off / false / 0 serves plain HTTP on the container’s 8080 instead — the supported shape when a reverse proxy or load balancer already terminates HTTPS in front of it.
YAGRA_WEB_TLS_CERT /etc/nginx/certs/server.pem Path to the combined chain + key bundle inside the web container. One file holds both, so a certificate can never be read alongside a key that does not match it.
YAGRA_WEB_TLS_WAIT_SECS 90 How long the entrypoint waits for that file before giving up. Timing out is a hard failure: TLS was requested, so the container refuses to start rather than silently downgrading to plaintext.
YAGRA_WEB_TLS_RELOAD_SECS 15 How often the entrypoint hashes the bundle to notice an imported or regenerated certificate. A change is applied with nginx -s reload, and only after nginx -t passes — a bad certificate leaves the previous configuration serving rather than taking the UI down.
Variable Default Purpose
YAGRA_POLL_INTERVAL_SECS 300 Initial default polling interval in seconds, clamped to 10–3600. First boot only: the value seeds the stored setting once; from then on the value in the WebUI settings is authoritative and this variable is ignored.
YAGRA_SNMP_COMMUNITY unset Fallback SNMP v2c community for nodes without a bound credential. Unset or empty ⇒ no fallback — such nodes need a credential assigned.
YAGRA_MERAKI_POOL default Poller pool that Meraki cloud-poll jobs are routed to.

The environment-configured Webhook and email channels are always-on defaults. They fire alongside any notification channels configured in the WebUI.

Variable Default Purpose
YAGRA_WEBHOOK_URL unset Default alert notification Webhook — fires for every alert. Unset or empty ⇒ no environment Webhook channel.
YAGRA_SMTP_HOST unset SMTP relay host for the default email channel. The channel is enabled only when YAGRA_SMTP_HOST, YAGRA_SMTP_FROM, and YAGRA_SMTP_TO are all set.
YAGRA_SMTP_PORT 465 SMTP port. The default is implicit TLS (SMTPS).
YAGRA_SMTP_FROM unset Email From address. Must parse as a valid mailbox or the channel is dropped.
YAGRA_SMTP_TO unset Email To address. Must parse as a valid mailbox.
YAGRA_SMTP_USER unset SMTP auth username. Credentials are applied only when both YAGRA_SMTP_USER and YAGRA_SMTP_PASS are set.
YAGRA_SMTP_PASS unset SMTP auth password.
YAGRA_POOL_COVERAGE_ALERT_AFTER_SECS 300 How long a poller pool must hold nodes with no live poller before Yagra raises a critical alert about its own monitoring coverage. A poller announces its own departure, so an ordinary rolling restart raises the condition instantly — this debounce is what keeps that from paging anyone. 0 disables the alert; the yagra_pools_without_live_poller and yagra_pool_nodes_without_live_poller gauges are exported either way.

See the high-availability guide for the full active/passive setup.

Variable Default Purpose
YAGRA_ENABLE_HA false Opt-in active/passive core pair with leader election over a PostgreSQL advisory lock. Off ⇒ single active core, identical to the non-HA behavior.
YAGRA_CORE_ID unset Human-readable id of this core instance, shown in HA logs and diagnostics. Unset ⇒ a generic label.

The MCP tool surface for AI clients, served by default. See the MCP server page.

Variable Default Purpose
YAGRA_ENABLE_MCP true Mount the MCP tool surface at /mcp. Set false to unmount it, after which requests to /mcp return 404. Authentication on /mcp is always required, even when the public dashboard is enabled — so the surface being on exposes nothing until an API token is minted.
YAGRA_MCP_ALLOWED_HOSTS unset Optional comma-separated host[:port] allowlist that pins the Host header on /mcp (DNS-rebinding hardening). Unset or empty ⇒ any Host is accepted; the mandatory Bearer authentication remains the gate.

Caps on Troubleshoot analysis jobs and AI root-cause-analysis (RCA) generations. RCA generations call an external LLM, so the RCA caps also bound spend.

Variable Default Purpose
YAGRA_ANALYSIS_MAX_CONCURRENT 4 Cap on concurrently running Troubleshoot analysis jobs.
YAGRA_ANALYSIS_RATE_PER_MIN 30 Cap on new analysis jobs admitted per minute (sliding 60 s window).
YAGRA_RCA_MAX_CONCURRENT 2 Cap on simultaneous AI RCA generations.
YAGRA_RCA_RATE_PER_MIN 10 Cap on new RCA generations per minute (sliding 60 s window).
YAGRA_RCA_CACHE_SECS 900 RCA report cache lifetime in seconds. Forcing a regeneration bypasses the cache but not the rate caps.
YAGRA_RCA_MAX_TURNS 6 How many tool-calling turns an LLM root-cause analysis may take before it has to answer. Since v0.1.23 the analysis can call the read-only MCP tools to look things up for itself; setting this to 1 restores the previous single-shot behaviour exactly — no tools are offered and the request sent to the provider is byte-identical to before.
YAGRA_RCA_TASK_BUDGET_SECS 240 Wall-clock ceiling in seconds for one root-cause analysis, including its tool calls. Hitting the bound returns the model’s last answer rather than failing the request.

The flow store connection itself is YAGRA_CLICKHOUSE_URL — see Backing stores above.

These variables tune retention and IP→ASN enrichment. See the traffic-flow feature page.

Variable Default Purpose
YAGRA_FLOW_RETENTION_DAYS 30 Flow-record retention in days (applied as a ClickHouse TTL), clamped to 1–3650.
YAGRA_CLICKHOUSE_SYSTEM_LOG_RETENTION_DAYS 7 Retention in days for ClickHouse’s own system.*_log tables, clamped to 0–3650. Stock ClickHouse gives them no TTL, so they grow without bound. 0 leaves system.* untouched — use it when YAGRA_CLICKHOUSE_URL points at a ClickHouse this deployment does not own.
YAGRA_IPASN_DB unset Path to an offline iptoasn.com TSV dataset for flow IP→ASN enrichment. Unset ⇒ enrichment is off and only exporter-provided AS numbers are used. A missing or unreadable file logs a warning and disables enrichment — never fatal.
YAGRA_IPASN_RELOAD_SECS 0 Period in seconds for hot-reloading the IP→ASN dataset without a restart. 0 ⇒ load once at startup, no reload task.

When the bus is exposed to remote pollers, core can act as the NATS Auth Callout service. It then mints per-poller bus credentials, scoped to exactly the subjects that poller needs.

Since v0.3.2 there is nothing to set up. Turning on “Accept remote pollers” turns this on with it: the signing key is generated on first start and kept sealed in the database, and its public half is written into the bus’s own configuration by the same one-shot that writes the rest of it.

Variable Default Purpose
YAGRA_NATS_POLLER_PASSWORD unset The shared bootstrap secret a poller with no token of its own presents, and the variable that decides whether the callout runs at all — unset, the responder is not started and NATS falls back to its static accounts. The remote-poller switch writes it; the bundled NATS server configuration consumes the same value (see compose-only variables).
YAGRA_NATS_CALLOUT_ACCOUNT $G NATS account that minted poller users are placed into. It must match the account the bus’s generated callout.conf names — and that file is written from this same value, so leave it alone unless the broker’s accounts were customized.
YAGRA_NATS_CALLOUT_SEED_FILE unset Legacy. Path to a mounted NATS account nkey seed file. Set, it takes precedence over the key core generates for itself; unset — the normal case — the stored key is used. Only relevant to a deployment that set this up by hand before v0.3.2.

The bus certificate is a separate thing from those credentials. It is generated by Yagra and kept in PostgreSQL, the same way the WebUI’s own certificate is, and a bus-cert-init one-shot service writes it to a volume the NATS server reads before the bus starts.

Normally you do not set either of these by hand. Settings ▸ Pollers ▸ Accept remote pollers sets them for you, as part of turning TLS and authentication on in one change.

Variable Default Purpose
YAGRA_BUS_TLS_SANS unset Extra subject alternative names for the bus certificate, comma-separated — the addresses your remote sites dial. nats, localhost and 127.0.0.1 are always included even when this is set, because dropping nats would cut the co-located core and poller off from their own bus the moment TLS came on.
YAGRA_BUS_TLS_DIR unset Where the bus-cert one-shot writes the certificate and the NATS server configuration. Set by the composition, not by an operator; the one-shot exits non-zero if it is missing.

Settings ▸ Upgrade (v0.2.2+) is served by core, but the work is done by a yagra-updater sidecar that holds the Docker socket. Core never does.

These two variables are the core half. The sidecar’s own settings are under compose-only variables below.

Variable Default Purpose
YAGRA_UPGRADE_DIR unset Directory core and the sidecar hand requests through — a shared volume, /data/upgrade in the deploy composition. Unset ⇒ no sidecar is deployed: the page still reports what is running and what it could move to, and reports the apply half unavailable. Nothing in this directory is ever executed; it carries a request file, a heartbeat and uploaded archives only.
YAGRA_UPGRADE_BUNDLE_MAX_BYTES 4294967296 (4 GiB) Ceiling on an uploaded image archive, enforced as the bytes land. Three release images saved together come to roughly a gigabyte, so this is not a working limit — it is what catches the wrong file being dragged into the browser before it fills the filesystem PostgreSQL is on.

Variables read by the yagra-poller binary. The poller is the stateless polling worker, and it also hosts the passive-event and traffic-flow edge listeners.

Variable Default Purpose
YAGRA_POLLER_ID local in the shipped composition; otherwise hostname Stable poller identity used in heartbeats, working-set assignment, and the Settings ▸ Pollers page. Since v0.3.2 docker-compose.deploy.yml passes local for the poller inside the central deployment, because a container hostname changes every time Compose recreates the container and left a dead row behind on every upgrade. Core is given the same value, so the two halves cannot name different pollers. Run standalone with nothing set and it is still the machine hostname; if that is unresolvable, a random poller- id. Sanitized to A–Z a–z 0–9 _ -.
YAGRA_POLLER_POOL default The pool this poller starts in — the value it reports the first time core sees it (see distributed polling). From v0.3.4 core owns the pool after that: a move made at Settings ▸ Pollers is sent on the next working-set snapshot and the running poller re-points its subscriptions in place, so editing this value and recreating the container no longer reverts a move. When unset, passive events and flows received by this poller are tagged with no pool rather than default.
YAGRA_POLLER_QUEUE pollers NATS queue-group name for the legacy per-job fan-out path.
YAGRA_BUS_CA_FILE unset CA / server-certificate file used to pin the NATS server certificate for tls:// bus URLs (remote pollers). Unset or empty ⇒ no pinning — the plaintext single-node path.
YAGRA_BUS_AUTH_CALLOUT unset ⇒ off Poller only. 1 or true makes the poller present its own YAGRA_POLLER_ID as the bus username, which is the name Auth Callout scopes its permissions on. Left off — the default, and what the remote-poller switch configures — it presents the username written in YAGRA_BUS_URL, the shared static account. Turn it on only where the callout is enabled: with the callout off, a poller announcing its own id matches no static account and the bus refuses it.
Variable Default Purpose
YAGRA_MAX_CONCURRENT_POLLS 256 Bound on total concurrent probes. Each device is additionally limited to one in-flight probe at a time. This bounds what is in flight, not a rate — and the same budget caps concurrent SNMP table walks, so lower it for a small site.
YAGRA_ADOPT_RATE_PER_SEC 200 Rate, in checks per second, used to size the jitter window when this poller adopts work from another — a restart, a failure, a rolling upgrade, a scale-in. The window is adopted ÷ rate, clamped to the check’s own interval, so fifty adopted checks start within a fraction of a second while a full cold start still spreads across the whole interval. 0 restores the previous behaviour (always jitter across the interval).

Syslog and SNMP-trap reception (see passive events). Each listener stays disabled until its bind address is set. The two YAGRA_LISTENER_* variables tune every edge listener, including the traffic-flow listeners in the next section.

Variable Default Purpose
YAGRA_SYSLOG_BIND unset UDP bind address for the syslog listener (e.g. 0.0.0.0:1514). Unset or empty ⇒ listener disabled. A failed bind is logged and the listener skipped — not fatal.
YAGRA_TRAP_BIND unset UDP bind address for the SNMP-trap listener (e.g. 0.0.0.0:1162) — v1/v2c traps and informs. Unset or empty ⇒ listener disabled.
YAGRA_TRAP_COMMUNITY unset Drop traps whose community string does not match. Unset or empty ⇒ no community filter — all traps accepted. The value is never logged.
YAGRA_EVENT_RATE_PER_SOURCE 200 Per-source-IP events-per-second cap for syslog + trap intake (one shared token bucket per source; minimum effective rate 0.1).
YAGRA_EVENT_RATE_GLOBAL 5000 Global events-per-second cap across all sources for syslog + trap intake.
YAGRA_LISTENER_WORKERS auto (1–4) Parallel reader sockets per edge listener. Defaults to the host’s available parallelism clamped to 1–4; platforms without SO_REUSEPORT always use a single socket.
YAGRA_LISTENER_RCVBUF_BYTES 4194304 Socket receive-buffer (SO_RCVBUF) size per listener socket — 4 MiB by default.

NetFlow, IPFIX, and sFlow reception. Flow datagrams have their own rate budget, separate from the one syslog and traps share.

Variable Default Purpose
YAGRA_FLOW_BIND unset UDP bind address for NetFlow v5/v9 and IPFIX (e.g. 0.0.0.0:2055). Unset or empty ⇒ listener disabled.
YAGRA_SFLOW_BIND unset UDP bind address for sFlow v5 (e.g. 0.0.0.0:6343). Shares the rate limiter, aggregator, and flusher with the NetFlow listener.
YAGRA_FLOW_RATE_PER_SOURCE 1000 Per-source cap in datagrams per second (not flow records).
YAGRA_FLOW_RATE_GLOBAL 20000 Global flow-datagram cap across all exporters.
YAGRA_FLOW_TOP_N 500 Top flows (by bytes) kept per bucket per exporter — the primary cardinality control for the flow store.
YAGRA_FLOW_BUCKET_SECS 60 Flow aggregation bucket width in seconds.

A remote poller buffers results through a network partition, in memory and then spilling to disk, and replays them when the link returns. See distributed polling.

Variable Default Purpose
YAGRA_STORE_FORWARD on Master switch for the result buffer. Set off, false, 0, or no (case-insensitive) to disable; any other value — including unset — means on. Off ⇒ pure pass-through: results publish live and are dropped on failure.
YAGRA_STORE_FORWARD_DIR /var/lib/yagra/buffer On-disk spill directory; the bundled compose files mount a named volume here. If the directory cannot be created or scanned, the poller degrades to memory-only buffering — it never crashes.
YAGRA_STORE_FORWARD_MEM_MAX 20000 In-memory ring size (in results) before the oldest results spill to disk.
YAGRA_STORE_FORWARD_DISK_MAX_MB 512 Maximum total on-disk spill in MB, enforced by dropping whole oldest segments.
YAGRA_STORE_FORWARD_MAX_AGE_SECS 86400 Buffered results older than this (default 24 h) are dropped at replay time.
YAGRA_STORE_FORWARD_DISK_FREE_FLOOR_MB 1024 Stop spilling when the filesystem’s free space drops below this many MB — a host-disk safety floor.
YAGRA_STORE_FORWARD_SEGMENT_MB 16 Spill-segment roll size in MB — the granularity of the disk cap. 0 or an unparseable value falls back to the built-in 16 MiB.
Variable Default Purpose
YAGRA_BUS_URL — NATS bus URL — nats://host:4222, or tls://user:pass@host:4222 for remote sites. Core requires it for live mode (see skeleton mode above); a poller without it logs a warning and idles. Both binaries retry the connection 30 times at 2 s intervals.
Variable Default Purpose
YAGRA_DISK_WATCH_PATHS /=root Comma-separated list of path or path=alias entries — the filesystems host self-metrics report capacity for. The alias becomes the metric’s mount label (derived from the last path segment when omitted). Unreadable paths are silently omitted from samples.
Variable Default Purpose
YAGRA_OTEL_ENDPOINT unset OTLP/HTTP endpoint for OpenTelemetry span export (e.g. http://jaeger:4318). Unset or empty ⇒ spans are not exported — structured logs only. A bad endpoint prints a warning and falls back to logs-only; it never aborts startup.
OTEL_EXPORTER_OTLP_ENDPOINT unset Standard OpenTelemetry fallback endpoint, consulted only when YAGRA_OTEL_ENDPOINT is unset.
OTEL_TRACES_SAMPLER parentbased_always_on Trace sampler. Recognized values: always_on, always_off, traceidratio, parentbased_always_off, parentbased_traceidratio; anything else falls back to the default (sample everything). At scale, prefer parentbased_traceidratio.
OTEL_TRACES_SAMPLER_ARG 1.0 Sampling ratio for the ratio-based samplers, clamped to 0.0–1.0.
YAGRA_LOG_DIR unset Directory for hourly-rotated JSON-lines log files, written in addition to stdout — never instead of it. It exists for deployments where nobody can reach docker logs, which is exactly where a panic or an OOM would otherwise leave nothing retrievable; the support bundle reads these files back over HTTP, so a bundle taken after a recovery still carries the run that died. Unset ⇒ stdout only. Writes are non-blocking and drop rather than stall the poll loop, and an unwritable directory degrades to stdout-only with a warning instead of failing startup.

On a poller this is also the switch that decides whether that poller can appear in a support bundle at all, and the bundled compose files set it two ways on purpose. A poller sharing a host with core gets /var/log/yagra/pollers, a subdirectory of core’s log volume that core reads back off disk — which reaches even a poller that has since died. A remote-site poller gets /var/log/yagra on a volume of its own and ships a window of it over the bus when core asks. Leave it unset and the poller does not advertise the log-ship capability, so the bundle records the site as unrepresented rather than waiting on it.
YAGRA_LOG_RETAIN_HOURS 48 How many hourly log files to keep in YAGRA_LOG_DIR, pruned automatically so an unattended deployment cannot fill its volume with its own logs.
RUST_LOG info Structured-log filter in standard tracing EnvFilter syntax — a plain level (debug) or per-module directives.

These variables are consumed by Docker Compose, or by the bundled NATS server configuration, when interpolating the compose files. The binaries never read them. Set them in the .env file next to the compose file you run.

The Used by column abbreviates:

  • deploy = docker-compose.deploy.yml (pull-only server composition)
  • poller = docker-compose.poller.yml (standalone remote-site poller)
  • single-node = docker-compose.yml
  • nats = docker/nats/nats-server.conf
Variable Default Used by Purpose
YAGRA_IMAGE_TAG latest deploy, poller Tag of the three published ghcr.io/horryworks/yagra-* images to pull. latest is the latest stable release; pin a v<version> tag for production.
YAGRA_IMAGE_REPO ghcr.io/horryworks deploy, poller Registry namespace the three images are pulled from. Change it only when serving them from a mirror of your own.
YAGRA_UPGRADE_REPO ghcr.io/horryworks deploy Where the yagra-updater sidecar looks for releases. Deliberately a separate variable from YAGRA_IMAGE_REPO: where releases live is not necessarily where this deployment’s current images came from, and a box pulling from a private mirror would otherwise point the release picker at a registry holding none. Fixed by the host either way, so no API request can name a registry.
YAGRA_UPGRADE_CHECK_SECS 86400 deploy How often the sidecar refreshes the release list — daily. The list only fills a picker, so checking more often buys nothing; switching the mechanism off in the WebUI stops the call entirely.
YAGRA_UPGRADE_ALLOW_BUNDLE 0 deploy Allow installing an uploaded docker save archive, for a site with no reachable registry. This widens the path from Yagra’s Admin role to host root — docker load installs whatever the archive contains, not only the three images the composition names — which is why it is a host setting and cannot be turned on from the WebUI. Everything after the load is unchanged: same backup, same composition swap, same provenance check, and the archive must contain the tag the operator claimed.
YAGRA_UPGRADE_MIN_FREE_BYTES 3221225472 (3 GiB) deploy Free space an upgrade demands before it writes anything. The pre-upgrade backup — a full PostgreSQL dump plus a VictoriaMetrics snapshot — runs before the release images are fetched, so without this check a host that is already full has several hundred MB written onto it and then fails to pull. The smaller of the Docker storage and the deployment directory is what is measured; a host where neither can be measured proceeds and records that nothing was checked. 0 switches the check off. A value that is not a plain number of bytes falls back to the default, so the check stays on.
YAGRA_UPGRADE_KEEP_RELEASES 1 deploy How many releases to keep behind the one being installed. It covers this project’s three images and the yagra-backup-* directories in the deployment directory; nothing else on the host is touched. The tidy-up runs only after the new version has been seen healthy, and a tidy-up that fails never turns a succeeded upgrade into a failed one. 1 is the default because the WebUI offers a single hop back to the release you came from, and that hop must not need a re-download. Raise it on a closed network where a re-pull is impossible. 0 keeps only the release now installed — but one backup is always kept, because the newest one is the one this upgrade just took.
YAGRA_DOCKER_GID 0 deploy Group the yagra-updater sidecar runs as. Only matters if you move its uid off 0; root reaches the Docker socket whatever the gid says.
POSTGRES_PASSWORD yagra deploy PostgreSQL password — interpolated into both the postgres container and core’s YAGRA_DATABASE_URL. Change it in production. 🚨 Must be URL-safe. It is placed into a connection URL and cannot be percent-encoded there, so a password holding /, @, :, ? or # ends the URL early and core refuses to start. openssl rand -hex 16 produces none of them; openssl rand -base64 produces / most of the time.
YAGRA_API_PORT 8080 deploy Host port mapped to core’s API port.
YAGRA_WEB_PORT 443 deploy Host port mapped to the WebUI container — HTTPS. The single-node build composition defaults it to 8443 instead, so an evaluation stack does not need a privileged port.
YAGRA_SYSLOG_PORT 514 deploy Host UDP port mapped to the poller’s syslog listener (container port 1514).
YAGRA_TRAP_PORT 162 deploy Host UDP port mapped to the SNMP-trap listener (container port 1162).
YAGRA_FLOW_PORT 2055 deploy Host UDP port mapped to the NetFlow/IPFIX listener.
YAGRA_SFLOW_PORT 6343 deploy Host UDP port mapped to the sFlow listener.
YAGRA_NATS_PORT 4222 deploy Host port to publish the NATS bus on. Only expose the bus with TLS + authentication enabled — which is what YAGRA_NATS_BIND below decides.
YAGRA_PULL_POLICY always deploy Whether Compose re-pulls the three images every time the stack starts. The default is unchanged, so an existing deployment does not move. Set it to missing on a host whose images did not come from a registry — a relocation loads the three images onto the new host directly, and that host must then be able to start itself without reaching for a registry that only ever answered on the machine it came from.
YAGRA_BACKUP_SKIP_METRICS 0 deploy 1 leaves the VictoriaMetrics snapshot out of a backup and records that as an omission in the manifest, exactly as an unreachable store would be. Set by a relocation whose operator unticked the metrics; the upgrade path never sets it.
YAGRA_NATS_BIND 127.0.0.1 deploy Address the bus port is published on. The default keeps the bus on the host’s loopback, reachable by the co-located core and poller and by nothing else. Settings ▸ Pollers ▸ Accept remote pollers sets it to 0.0.0.0, and does so together with TLS and authentication — the bus carries plaintext device credentials, so the two changes belong in one step.
YAGRA_NATS_ARGS -js deploy Arguments the NATS server is started with. Turning the bus TLS on appends -c /etc/nats/nats-server.conf, the configuration the bus-cert-init one-shot writes.
YAGRA_CORE_BUS_URL nats://nats:4222 deploy Bus URL core dials. Becomes tls://core:<password>@nats:4222 when the bus is switched to TLS: server-wide TLS leaves no plaintext port, so the co-located core has to move in the same change.
YAGRA_POLLER_BUS_URL nats://nats:4222 deploy Bus URL the co-located poller dials — the same reasoning as YAGRA_CORE_BUS_URL, with the poller account’s password. A remote poller gets its URL from the archive Settings ▸ Pollers issues it, not from this file.
YAGRA_CERT_DIR ./certs deploy, poller Host directory bind-mounted for the NATS server certificate (server side) and the poller’s CA certificate (remote side, pairs with YAGRA_BUS_CA_FILE).
YAGRA_NATS_CORE_PASSWORD — (required) deploy, nats Password for the core user in the NATS static-auth configuration. The NATS server exits at startup if it is referenced but unset — fail-closed, never a silent default.
YAGRA_CALLOUT_SEED_DIR ./callout deploy Legacy. Host directory holding account.seed, mounted read-only into core. Pairs with YAGRA_NATS_CALLOUT_SEED_FILE; nothing needs it since v0.3.2.
YAGRA_SESSION_KEY_DIR ./session deploy Host directory holding session.key, mounted read-only into the core container(s). Pairs with YAGRA_SESSION_KEY_FILE.
YAGRA_POLLER_LOG_DIR /var/log/yagra/pollers deploy What the composition passes to the co-located poller as its YAGRA_LOG_DIR — a subdirectory of the log volume core reads back, which is how that poller’s log reaches a support bundle. Set it empty to keep the poller on stdout only.
YAGRA_IPASN_URL https://iptoasn.com/data/ip2asn-combined.tsv.gz deploy, single-node Dataset URL the ipasn-updater sidecar fetches — the only container that needs egress for AS enrichment.
YAGRA_IPASN_REFRESH_SECS 604800 deploy, single-node Fetch cadence of the ipasn-updater sidecar — 7 days by default.
COMPOSE_PROFILES unset (self-upgrade in an issued bundle) poller Docker’s own variable, and at a monitored site the switch that decides whether that site can install a release. With self-upgrade named, Compose starts the yagra-poller-updater sidecar, the poller advertises self-upgrade, and Settings ▸ Upgrade can move it. Empty the value and no container at that site holds a Docker socket. The bundle (Settings ▸ Pollers ▸ “Issue token & download”) writes it by default; change it here rather than in the composition, because an upgrade reinstalls the composition and never touches .env.
Variable Default Purpose
VITE_API_BASE empty The API origin — scheme + host + port, never a path — that the WebUI’s API and SSE clients call. Baked in at build time by Vite; it cannot be changed on a built image. Empty ⇒ same-origin: the production image serves the WebUI behind its bundled nginx, which proxies /api to core. Set it only when building the WebUI yourself against a core on another host.