unmask

docs

JA4 acquisition, LB / CDN setup, supported distros, FAQ.

Prometheus metrics

The admin daemon exposes a Prometheus-format metrics endpoint at GET /unmask/metrics. A scraper polls it (typically every ~30 s) and you visualize the result in Grafana — challenge volume, the behavioral-score distribution, DB latency. It is emitted in the plain Prometheus text format directly from the Go standard library, so it adds no runtime dependency.

Keep it private. The endpoint carries bot-pressure stats (e.g. “100k challenges/day on your site”), so it is gated at the application layer. The default allowlist is loopback only (127.0.0.1 + ::1) — a same-host scraper works with no configuration. To scrape from a remote Prometheus, add only that scraper's IP / CIDR to metrics_allow_from under settings → Network. A request from any other address gets a 403. If you don't run Prometheus, ignore this — the endpoint exists but nothing will reach it.

Exposed metrics

Metric Type What it is
unmask_event_total
{phase, verdict}
counter Events in the trailing 24 h, broken down by challenge phase and JA4 verdict. The main “what is being challenged” signal.
unmask_event_unique_ip gauge Distinct source IPs seen across any phase in the trailing 24 h.
unmask_verify_score
_bucket{le} / _sum / _count
histogram Behavioral-score distribution from /api/verify (buckets 0.1 … 1.0). Counted in-process since the daemon started. Watch where humans vs. bots land relative to the 0.5 threshold.
unmask_db_query_seconds
_sum / _count {op}
counter DB query latency (sum & count) for the daemon's internal aggregation operations — a coarse database-health signal.

The DB-sourced metrics (event_total / unique_ip) are cached for 30 s, so a fast scrape interval will not add database load.

Scrape configuration

Via the site (recommended)

nginx proxies all of /unmask/ to the admin daemon, so this works regardless of how the daemon binds (TCP or unix socket). Point Prometheus at your host and add its IP to metrics_allow_from:

# prometheus.yml
scrape_configs:
  - job_name: unmask
    scheme: https
    metrics_path: /unmask/metrics
    static_configs:
      - targets: ['your-host']
Same host (default, zero allowlist change)

If Prometheus runs on the unmask host itself and the daemon binds TCP (default bind: 127.0.0.1), scrape loopback directly — the default allowlist already permits it:

metrics_path: /unmask/metrics
static_configs:
  - targets: ['127.0.0.1:<admin-port>']   # the daemon's configured bind port

Health check

For a plain liveness probe (uptime monitors, load-balancer health checks, container orchestrators) use the unauthenticated health endpoint — it returns 200 with the body ok and exposes no stats:

curl -sf https://your-host/unmask/healthz   # -> ok

healthz is open by design (no allowlist) precisely because it reveals nothing; the stats live behind /unmask/metrics and its allowlist.