Skip to content

Metrics and Status

Vexillum provides two different ways to expose runtime information:

  • The public API, intended for users, communities, and dashboards built against it.
  • The metrics listener, intended for operators and monitoring systems.

These serve different purposes and should usually have different exposure rules. The public API can be safely shown to users when configured appropriately - it’s a JSON+SSE API, not a bundled status page; see Public Interface and the Public API Reference. The metrics listener should normally remain private.

The metrics listener is intended for monitoring and observability.

Metrics are useful for operators who want to track runtime behavior, service health, traffic patterns, and mode activity over time.

A typical metrics listener default is:

[metrics]
listen = "127.0.0.1:9090"

Binding metrics to localhost keeps them private by default. That is usually the right choice unless you have a dedicated monitoring network, reverse proxy, VPN, or firewall rules protecting access.

The public API and metrics listener should not be treated as the same thing.

Surface Audience Typical exposure Purpose
Public API Users, communities, dashboards Public or semi-public Read-only reflector status (JSON/SSE)
Metrics listener Operators and monitoring systems Private Machine-readable monitoring data
Admin interface Operators Private Management and configuration

The public API answers questions like:

  • Which modes and instances are available?
  • Is the reflector online?
  • What services does this deployment provide?
  • Where should users connect?
  • Who’s currently active?

The metrics listener answers questions like:

  • Is the process healthy?
  • Are mode instances running?
  • How much activity is happening?
  • Are errors increasing?
  • Did traffic suddenly drop?
  • Is something behaving strangely?

A safe deployment usually exposes services like this:

Service Recommended exposure
Protocol listeners Public if the reflector is intended for public use
Public API Public or community-facing
Admin interface Private, VPN, SSH tunnel, or reverse proxy protected
Metrics listener Private or monitoring-only

Avoid exposing the metrics listener directly to the public internet. Metrics can reveal operational details that are useful to operators and occasionally useful to people whose hobbies need better parental supervision.

For a local-only metrics listener:

[metrics]
listen = "127.0.0.1:9090"

This allows monitoring tools on the same host to scrape metrics without exposing the listener externally.

Example private network metrics configuration

Section titled “Example private network metrics configuration”

For a private monitoring network:

[metrics]
listen = "10.10.0.25:9090"

Use a specific private interface address when metrics should only be reachable from a monitoring VLAN, VPN, or private management network.

The public API may be exposed through a reverse proxy such as Caddy, nginx, or Traefik. It’s a JSON+SSE API, not a rendered page - see Public Interface for the deployment model and CORS/rate-limit configuration.

A typical deployment might expose it on HTTPS:

https://vexillum.example.net/api/public/v1/overview

while keeping the admin and metrics listeners private:

127.0.0.1:8080
127.0.0.1:9090

This gives users (or a dashboard built against the API) useful status data without handing them the control panel like civilization has learned nothing.

When using a reverse proxy:

  • Terminate TLS at the proxy.
  • Expose the public API publicly.
  • Restrict the admin interface by VPN, IP allowlist, authentication, or private network.
  • Keep the metrics listener private unless your monitoring system needs proxy access.
  • Avoid publishing raw metrics unless you have a specific reason.
  • Use clear hostnames for public and admin access.

Example hostname layout:

Hostname Purpose
vexillum.example.net Public API
admin.vexillum.example.net Admin interface, restricted
metrics.vexillum.example.net Metrics, restricted or internal only

Do not put all three surfaces behind the same access policy unless you enjoy solving self-inflicted security puzzles.

Operators should configure service health checks where possible.

Health checks can be used by:

  • systemd watchdogs
  • reverse proxies
  • load balancers
  • monitoring systems
  • external uptime checks
  • deployment automation

A health check should answer one basic question:

Is the Vexillum process alive and able to serve requests?

A health check does not necessarily prove that every reflector mode is healthy, reachable, or correctly configured. It only proves that the checked service is responding. Useful, but not magic. Humans keep trying to outsource judgment to endpoints named /health.

Useful things to monitor include:

  • Process uptime
  • Admin or public API availability
  • Metrics scrape success
  • Enabled mode instance state
  • Listener availability
  • Packet or session activity
  • Authentication failures
  • Error counts
  • Unexpected restarts
  • Disk usage for storage and logs
  • Memory and CPU usage
  • Network traffic on protocol ports

For a public reflector, also consider monitoring from outside your network so you know whether users can actually reach the exposed services.

Use ss to confirm which ports Vexillum is listening on:

ss -ltnup | grep vexillum

If the process name does not appear, search by port:

ss -ltnup | grep -E '8080|9090|17000|42000|43000'

This can help confirm whether the configured services actually started and which addresses they are bound to.

Use curl to test HTTP listeners:

curl -v http://127.0.0.1:8080/

For the public API, expect JSON back, not a rendered page:

curl -v http://127.0.0.1:8081/api/public/v1/overview

For metrics:

curl -v http://127.0.0.1:9090/

If a service is bound to 127.0.0.1, it will only be reachable from the same machine unless you use a tunnel or reverse proxy.

Check:

  • Is Vexillum running?
  • Is the public API listener enabled ([public_api] enabled = true)?
  • Is the listener bound to the expected address?
  • Is the reverse proxy pointing to the correct port?
  • Is the firewall allowing inbound traffic?
  • Is DNS pointing to the correct host?
  • Is TLS configured correctly?

Check:

  • Is the metrics listener enabled?
  • Is it bound to 127.0.0.1 or a private address?
  • Are you testing from the same host?
  • Is a firewall blocking access?
  • Is your monitoring system scraping the correct URL?
  • Are you accidentally trying to access private metrics from a public network?

This usually means the admin listener is bound to localhost:

[admin]
listen = "127.0.0.1:8080"

That is expected. Use an SSH tunnel, VPN, reverse proxy, or private listener address if remote administration is required.

A mode port is open but clients cannot connect

Section titled “A mode port is open but clients cannot connect”

Check:

  • The mode instance is enabled.
  • The listener is bound to the expected address.
  • The firewall allows the protocol and port.
  • NAT forwards the correct protocol, UDP or TCP.
  • The client is using the correct reflector address.
  • The mode-specific configuration matches what the client expects.
  • Logs show whether packets or sessions are arriving.

For UDP modes, remember that a port can appear open from the server side while clients still fail due to NAT, firewall, or routing problems. UDP remains the internet’s way of saying “maybe.”

A practical deployment might use:

Tool Purpose
systemd Process supervision
journalctl Runtime logs
Prometheus-compatible scraper Metrics collection
Grafana Dashboards
Uptime monitor Public API availability
Reverse proxy health checks Web listener health
External UDP checks Protocol reachability, where practical

The exact tooling matters less than having enough visibility to know whether Vexillum is healthy before users start reporting “it doesn’t work” with the diagnostic precision of a foghorn.

Before publishing a Vexillum deployment:

  • Confirm the public API responds (and any dashboard built against it loads).
  • Confirm admin access is restricted.
  • Confirm metrics are private.
  • Confirm enabled protocol ports are listening.
  • Confirm firewall and NAT rules match enabled modes.
  • Confirm monitoring can reach the metrics listener.
  • Confirm logs are available after restart.
  • Confirm storage is persistent.
  • Confirm backup coverage includes configuration and storage.
  • Confirm public documentation shows the correct connection details.

Metrics and status behavior may continue to evolve while Vexillum is under active development. Operators should review the current example configuration and release notes when upgrading.