MediumLiveKit Console: A Dashboard for Your Self-Hosted LiveKit Server | by Bhagyajit Jagdev | Stackademic
Sitemap
Stackademic

Stackademic is a learning hub for programmers, devs, coders, and engineers. Our goal is to democratize free coding education for the world.

LiveKit Console: A Dashboard for Your Self-Hosted LiveKit Server

--

Stop Debugging Phone Calls With a Terminal and a JSON Blob

Self-hosting LiveKit is a genuinely good experience. You run `livekit-server`, point a SIP trunk at it, and calls start flowing.

Then you need to actually look at something. A customer says their call dropped. A new number is not routing. You want to know if anyone is on a call right now.

And you realise the dashboard was part of what you were paying LiveKit Cloud for. Everything still works trunks, dispatch rules, rooms, recordings. But the only way to see any of it is a terminal.

So I built LiveKit Console, an open-source dashboard for a self-hosted LiveKit server.

Press enter or click to view image in full size

Why Not Just Use the CLI

For a one-off check, `lk` is exactly right. It falls apart the moment you have more than one thing to check.

A dispatch rule references its trunks by ID:

{
"sipDispatchRuleId": "SDR_xxxxxxxxxxxx",
"trunkIds": ["ST_yyyyyyyyyyyy"],
"rule": { "dispatchRuleIndividual": { "roomPrefix": "support-" } }
}

To learn what `ST_yyyyyyyyyyyy` is, you run a second command and match the ID by eye. Six trunks and four rules later, you are doing a join in your head.

Worse, you cannot watch anything. A call is happening now is the agent in the room? Is it recording? The CLI snapshots and exits, so you end up in a `watch` loop re-reading JSON, hoping to spot what changed.

That is the part that pushed me to build this.

Live Calls

Press enter or click to view image in full size

Active calls with the remote number pulled out of the SIP attributes, so you see `+1 555 0143` instead of `support-15550143`. Durations tick up live.

Expand one and you get the participants caller, agent, their tracks, who is muted, the SIP call status.

Press enter or click to view image in full size

When someone says “nobody answered”, you can see whether an agent ever actually joined. That single view replaced most of my `watch` loops.

Get Bhagyajit Jagdev’s stories in your inbox

Join Medium for free to get updates from this writer.

Trunks and Dispatch Rules

Press enter or click to view image in full size

Full CRUD for inbound and outbound trunks, and all three dispatch rule types.

Rules show their destination room the way it will really be named `support-<caller>`, not `dispatchRuleIndividual`. Trunk IDs are resolved to trunk names, which is the mental join from earlier, gone.

Recordings

Press enter or click to view image in full size

What is recording now, what recently finished, and the storage path each file landed at — `s3://your-bucket/…` so you can go straight to it. Failures show their error. Live ones can be stopped.

A JSON Tab on Every Form

Press enter or click to view image in full size

Every create and edit form flips to the exact payload being sent to LiveKit. Edit it there, switch back, the form updates.

The form is faster for normal work. The JSON tab means you never lose the precision of the API.

Try It

For real use, there is a compose bundle with Caddy for TLS:

mkdir livekit-console && cd livekit-console
curl -fsSLO "https://raw.githubusercontent.com/bhagyajitjagdev/livekit-console/main/deploy/{compose.yml,Caddyfile,.env.example}"
cp .env.example .env && $EDITOR .env
docker compose up -d

Images are multi-arch, so it runs on ARM too.

Two things it deliberately does not do: historical charts and usage analytics.

github.com/bhagyajitjagdev/livekit-console

Built with FastAPI, React and shadcn/ui, on top of livekit-api.

--

--

Bhagyajit Jagdev
Bhagyajit Jagdev

Written by Bhagyajit Jagdev

3+ yrs in Full-stack & AWS DevOps: JS to Python expert; proficient in React, Angular & FastAPI.

Stackademic
Stackademic

Published in Stackademic

Stackademic is a learning hub for programmers, devs, coders, and engineers. Our goal is to democratize free coding education for the world.