Ports & firewall
Yagra needs very few holes in a firewall. The core host exposes two TCP ports, the poller opens UDP listeners only for the passive-intake features you turn on, and everything else — all five stores and the bus — stays on the internal Docker network. Outbound connections are strictly per-feature: a fresh install with no notification channels, no forwarding destinations, and no AI provider configured makes no egress at all (except image pulls).
Inbound — core host
Section titled “Inbound — core host”| Port | Protocol | Service | Notes |
|---|---|---|---|
8080 |
TCP (HTTP) | Core API | One port serves the REST API (/api/v1), the Prometheus endpoint (/metrics), the health probes (/healthz, /readyz), and — when YAGRA_ENABLE_MCP is on — the MCP tool surface at /mcp (off by default; the route 404s). Host port via YAGRA_API_PORT (compose) or YAGRA_API_ADDR (native). |
443 |
TCP (HTTPS) | WebUI | nginx (rootless, container port 8080) serving the frontend over TLS; it proxies /api and /mcp to core, so browsers only ever need this port. Host port via YAGRA_WEB_PORT — 443 on the deploy composition, 8443 on the single-node build composition. There is no plain-HTTP listener unless you set YAGRA_WEB_TLS=off. |
8081 |
TCP (HTTP) | Second core (HA overlay only) | The two-core high-availability overlay maps the standby core’s API to a distinct host port. /readyz answers 200 only on the leader (a standby returns 503), so a load balancer can route on it. |
The UI and API carry the login password, bearer tokens, and (pre-encryption) device
credentials. The WebUI port is HTTPS by default and needs nothing in front of it. Core’s API
port is still plaintext — do not publish 8080 beyond a trusted LAN, and once your machine
clients have moved to the TLS edge, close it entirely with YAGRA_API_BIND=127.0.0.1.
Inbound — poller
Section titled “Inbound — poller”All poller listeners are opt-in: each exists only when its *_BIND variable is set
(the compose files set the first three by default; set the variable empty in .env to
disable one). The container binds unprivileged ports; compose maps the standard low ports
on the host.
| Container port | Host default | Protocol | Service | Enable / disable |
|---|---|---|---|---|
1514 |
514 (YAGRA_SYSLOG_PORT) |
UDP | syslog intake | YAGRA_SYSLOG_BIND |
1162 |
162 (YAGRA_TRAP_PORT) |
UDP | SNMP trap intake (v1/v2c + inform) | YAGRA_TRAP_BIND |
2055 |
2055 (YAGRA_FLOW_PORT) |
UDP | NetFlow v5/v9 / IPFIX intake | YAGRA_FLOW_BIND |
6343 |
6343 (YAGRA_SFLOW_PORT) |
UDP | sFlow v5 intake | YAGRA_SFLOW_BIND — off by default; the host mapping exists but nothing listens until you set the bind |
9100 |
— | TCP (HTTP) | Poller Prometheus /metrics (fixed 0.0.0.0:9100) |
Not published by the compose port mappings; reachable when the poller runs with host networking (the remote-site composition) or natively |
Only open the corresponding host ports to the network segments your devices send from. Event→node correlation keys on the datagram source IP, so anything that rewrites it (NAT between device and poller) breaks attribution — place pollers close to their devices.
Internal only
Section titled “Internal only”These services must stay on the internal Docker network. None of the compose files publish them, and nothing outside the stack ever needs to reach them — keep it that way.
| Port | Service | Role |
|---|---|---|
5432 |
PostgreSQL | Metadata store (nodes, config, users, alert history) |
6379 |
Redis | Ephemeral poller liveness/assignment mirror (rebuildable) |
4222 |
NATS | The core⇄poller bus. Job messages carry plaintext device credentials, so this port may be published only with the TLS + authentication configuration in place — and only when you run remote-site pollers. |
8428 |
VictoriaMetrics | Metrics time-series store |
9428 |
VictoriaLogs | Passive-event log store (optional) |
8123 |
ClickHouse | Traffic-flow store (optional) |
Outbound (egress) by feature
Section titled “Outbound (egress) by feature”Every outbound connection Yagra can make, and which process makes it. Nothing on this list happens until you configure the feature.
| Feature | Destination | Protocol | From |
|---|---|---|---|
| Webhook notifications | The webhook URL(s) you configure | HTTP/HTTPS | core |
| Email notifications | YAGRA_SMTP_HOST (default port 465, implicit TLS) |
SMTP | core |
| PagerDuty notifications | events.pagerduty.com (EU accounts: events.eu.pagerduty.com, via the channel’s API URL) |
HTTPS | core |
| Jira Service Management notifications | api.atlassian.com |
HTTPS | core |
| Forwarding — relay destinations | The collector host:port you configure |
UDP, TCP, or TLS | core (the active/leader core — not the pollers) |
| Forwarding — BigQuery destination | bigquery.googleapis.com and oauth2.googleapis.com; plus the GCE metadata server 169.254.169.254 when using Workload Identity instead of a stored key |
HTTPS | core |
| AI root-cause analysis | Only the one configured provider: api.anthropic.com (Claude), generativelanguage.googleapis.com (Gemini), or {location}-aiplatform.googleapis.com (Vertex AI, stays in your GCP project). Default off — no provider configured means zero egress. |
HTTPS | core |
| Single sign-on (OIDC) | Your identity provider’s issuer URL | HTTPS | core |
| Cisco Meraki monitoring | api.meraki.com (or the regional api.meraki.cn / api.gov-meraki.com) |
HTTPS | the poller pool that runs Meraki jobs |
| Distributed tracing | Your OTLP collector (YAGRA_OTEL_ENDPOINT, e.g. :4318) |
OTLP/HTTP | core and pollers |
| IP→ASN enrichment dataset | iptoasn.com (weekly fetch) |
HTTPS | the ipasn-updater sidecar — the only container that needs egress for this feature |
Two points worth repeating for a locked-down core host:
- Forwarding egress originates from core, not pollers. Pollers carry received bytes to core over the bus; core does all relaying and BigQuery streaming. Only the core host needs firewall exceptions for forwarding destinations.
- A TLS relay destination verifies the collector’s certificate against the system trust store (plus an optional operator-supplied CA certificate). There is no flag to disable verification, so a TLS destination behind an interception proxy will not connect.
Remote sites & firewalls
Section titled “Remote sites & firewalls”A remote-site poller is designed to need one outbound rule and no inbound rules at HQ:
- The poller dials out to the central NATS bus (
tls://…:4222). The central firewall publishes exactly one port — the TLS + authenticated bus (YAGRA_NATS_PORT, default4222) — and nothing else. No hole is opened toward the poller; all job assignment, results, events, and flow batches travel over that single outbound connection, which also crosses NAT without port forwarding at the site. - The remote poller composition uses host networking, so passive listeners bind the host’s ports directly and the device’s real source IP survives for event correlation (a Docker bridge would rewrite it).
- The poller runs non-root (file-capability
NET_RAWonly), so it cannot bind ports below 1024. Use the default high ports (1514,1162) and either point devices at them directly or redirect the standard ports in the site firewall:
# Redirect the standard syslog/trap ports to the poller's unprivileged listenersiptables -t nat -A PREROUTING -p udp --dport 514 -j REDIRECT --to-ports 1514iptables -t nat -A PREROUTING -p udp --dport 162 -j REDIRECT --to-ports 1162WAN bandwidth for the site link
Section titled “WAN bandwidth for the site link”So that forwarding can relay exactly what a device sent, pollers always carry the original bytes to core: passive events cost roughly 1.5–1.6× their raw syslog/trap volume on the bus, and every received flow datagram is relayed verbatim alongside the aggregated stream. Budget 0.4–0.8 Mbit/s per 1,000 flows/s of relayed flow — up to ~1 Mbit/s with densely packed exporters (≈4–8 Mbit/s at 10,000). If the WAN drops, the poller’s store-and-forward buffer keeps polling locally and replays metrics on reconnect, so a flapping link costs history nothing.
See also
Section titled “See also”- Configuration reference — every environment variable, including the bind and port-mapping variables named above.
- Installation — the compose files these mappings come from, and the remote-site poller setup.