Dashboard
Open http://localhost:8080 in a browser running on the Kapkan host. When you are under attack, look first at the Live mode banner (is Kapkan actually announcing, or only watching?) and the Active attacks list (what is being hit, and how hard).
The web UI is built into the kapkan binary itself, so there is nothing extra to install or
deploy — the same process serves the dashboard, the JSON API and Prometheus metrics.
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.
Because the default binds 127.0.0.1, the dashboard is reachable only from the Kapkan host
itself — opening localhost:8080 on your own laptop will show nothing. To view it from your
workstation, forward the port over SSH rather than rebinding api.listen to a public address:
ssh -L 8080:127.0.0.1:8080 user@kapkan-host
Then open http://localhost:8080 on your workstation. (Rebinding the listener to a public address needs an API token first — see the Authentication caveat below.)
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 of the attack type (for example, NTP/DNS amplification or a SYN flood — see the Detection page for what each type means) 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.
- Scrubbing nodes — shown only when you run managed scrubbing nodes: each node's liveness (it is alive because it keeps polling for rules), how many bans divert to it, and its own reported load, drops, version and dry-run flag — the reported columns are labelled as such, because a node's self-report is advisory, never the source of its liveness.
- Ban table — every ban, active and historical (with the scrubbing node column when nodes are configured).
- Traffic / Reports — live ingress/egress charts built from the in-memory rate buffers, plus a Historical reports section that reads the persisted ClickHouse tables when storage is enabled.
- Controls — the same actions the API offers: manual ban / unban of an address and
config reload (the equivalent of sending
SIGHUP).
The Historical reports section on the Traffic / Reports view is the one part that needs storage: it is populated only when ClickHouse storage is enabled, and otherwise renders a labeled placeholder explaining how to turn it on.
✓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.
Attack detail
Click an attack in the Active and recent attacks list to open its detail drawer. Alongside the classification, the "why it fired" breakdown, the escalation ladder and the mitigation route, two sections attribute the traffic:
- Captured sample — the dominant Top sources (relabeled Top destinations for an
outgoing attack), Protocols and Top source / dest ports distilled from the flow sample,
plus the total packets sampled. With GeoIP enabled it also shows a Top ASNs row (Top dest
ASNs for outgoing attacks): the busiest autonomous systems by sampling-corrected packets,
listed as
AS<number> <organization>. - Raw flows — a table of individual captured flows (source, protocol, destination, flags,
fragmentation, packets). With a country database loaded, each source carries a small
country-code badge such as
USorDE; hover it to see the source's network organization.
The Top ASNs row and the per-flow country badges appear only when GeoIP attribution is enabled.
Point geoip.asn_database at a MaxMind GeoLite2/GeoIP2 ASN database for the ASNs and organization
names, and geoip.country_database at a country database for the country badges — see the geoip
block in Configuration. Without them the drawer still renders, just without
the ASN row and country tags.
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.
Related
- REST API — the endpoints the dashboard polls and the control actions it calls.
- Authentication — how to protect the API and dashboard with a token.