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.
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
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.
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
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
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
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 -dImages are multi-arch, so it runs on ARM too.
Two things it deliberately does not do: historical charts and usage analytics.
Built with FastAPI, React and shadcn/ui, on top of livekit-api.









