Kapkandocs
GitHub

Dashboard

Kapkan ships with a self-contained web UI embedded directly in the binary via go:embed. There is no build step, no bundler, and no external assets to fetch — the same static kapkan binary serves the dashboard alongside the JSON API and Prometheus metrics. It is plain JavaScript that polls the REST API, not a React application, so it runs entirely from live data with no database required.

iOne binary, one listener

The dashboard, the JSON API and /metrics are all served by the same process on the same address. There is no separate web service to deploy or keep in sync.

Where it lives

The dashboard is served at / on the same address as the REST API — the api.listen value from your config. With the default of 127.0.0.1:8080, you open it at http://localhost:8080.

To serve only the JSON API and metrics without the UI, disable it:

api:
  listen: "127.0.0.1:8080"
  dashboard: false   # serve the JSON API and /metrics only

With api.dashboard: false, the /api/v1 endpoints and /metrics keep working — only the embedded UI shell stops being served.

What it shows

The dashboard polls the JSON API and renders everything Kapkan tracks in memory:

  • Live mode — whether the instance is running in dry-run or live, so you can see at a glance whether a detected attack would actually be announced.
  • Active and recent attacks — currently firing attacks plus the recently ended ones, each with its classification (amplification vectors such as NTP / DNS / CLDAP / memcached / SSDP / chargen, and SYN / UDP / TCP / ICMP / fragment floods) and the dominant sources, ports and protocols captured from the flow samples.
  • Top talkers — the tracked-host snapshot with per-direction rates and learned baselines, so you can see who is loudest and how it compares to normal.
  • Hostgroups — your named prefix groups and their state.
  • Ban table — every ban, active and historical.

It also exposes the same control endpoints the API offers: manual ban / unban of an address and config reload (the equivalent of SIGHUP). The whole view works on live data alone — no ClickHouse or other database is needed for any of it.

No database required

The dashboard is built entirely from the engine's in-memory state. Historical flow storage is a separate, optional feature — it is not needed to see live attacks, top talkers or bans.

Authentication

By default the API and dashboard are unauthenticated, which is safe only because the default api.listen binds to 127.0.0.1. When you set an API token, the dashboard adapts: the static UI shell still loads, but the data behind it does not until you supply the token.

When auth is enabled, the dashboard prompts for the token and keeps it in the browser's sessionStorage, attaching it as a bearer header on every API request it makes. Each /api/v1 request is authorized with Authorization: Bearer <token>; /metrics and the static shell stay open, but the live data and the ban / reload controls do not.

!Set a token before exposing the listener

Before binding api.listen to anything beyond 127.0.0.1, configure an API token. See Authentication for how to set api.token_env and how requests are verified.

  • REST API — the endpoints the dashboard polls and the control actions it calls.
  • Authentication — how to protect the API and dashboard with a token.