MikroDash: a live command center for MikroTik RouterOS v7
Real-Time Open-source command center for MikroTik RouterOS v7. Streams live CPU, traffic, wireless clients, DHCP, WireGuard, firewall and geo connection data straight from the router API to your browser over a WebSocket. Alerts, reports, config management and zero-touch provisioning. One static Go binary, self-hosted, Docker-ready
At a glance
- What is it?
- MikroDash is a self-hosted dashboard for MikroTik routers that keeps one connection per router open and pushes changes to the browser over a WebSocket instead of polling. It ships as a single static Go binary with the TypeScript frontend embedded, one Docker volume, no database server and no agents on the router.
- Who is it for?
- MikroDash suits a homelab or small site running MikroTik gear where the router API is already the source of truth and a refreshing dashboard is too slow to be useful, because the connection model pushes changes rather than polling, and the deployment is one image and one volume.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 1 day ago.
- What is it written in?
- Mainly Go, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 22, 2026, and from our analysis. They are not legal advice.
Editorial analysis
One connection per router, pushed not polled
The architectural claim is in the first bullet of the project notes and it is the thing that separates this from a typical monitoring page. MikroDash holds one connection per router and pushes changes to the browser over a WebSocket the moment they happen, rather than refreshing on a timer. The second bullet is about being careful with small routers, which is the audience that matters: each RouterOS menu is read once however many pages want it, collectors sleep when nobody is looking, and every router can be switched between streaming and polling.
That last part is the practical escape hatch. A home router on a slow link can be moved to polling so the dashboard stops holding a session open, and a busy site can leave streaming on. The data on offer comes straight from the RouterOS v7 binary API: live CPU, traffic, wireless clients, DHCP, WireGuard, firewall and geo connection data. The project also lists alerts and notifications for interface up and down, WireGuard peers, CPU, ping loss and NetWatch hosts, a multi-router fleet view with devices grouped by site, drag and drop dashboard cards whose layouts are saved to the account, and CSV import for adding devices in bulk.
One image, one volume, and a setup code in the log
The quick start is a Compose file and one command:
# docker-compose.yml
services:
mikrodash:
image: ghcr.io/secops-7/mikrodash:latest
restart: unless-stopped
ports:
- "3081:3081"
- "13231:13231/udp" # only for zero-touch provisioning; see below
volumes:
- mikrodash-data:/data
volumes:
mikrodash-data:docker compose up -dThe panel is served on port 3081, and the UDP port is only needed for the zero-touch provisioning feature, where remote routers dial in. On first run the application asks you to create an administrator account using a setup code that it prints to its log, and the notes tell you to read it with the compose logs command. No environment file is required for the standard path, because all router configuration and dashboard settings are managed through the web interface and persisted to the volume.
Images are published for linux/amd64, linux/arm64 and linux/arm/v7 on every release tag, so the latest tag always means the latest release rather than unreleased work, and a specific version can be pinned by tag. There is also a one-click deploy option through RepoCloud for people who would rather not write a Compose file at all.
Running it on the router itself
Because RouterOS v7 has container support of its own, the dashboard can run on the MikroTik it monitors, which removes a separate host from the picture. The container is added as an ordinary container with a remote image:
/container/add remote-image=ghcr.io/secops-7/mikrodash:latest \
interface=veth_mikrodash root-dir=usb1/mikrodash \
mountlists=mikrodash_data start-on-boot=yes comment="MikroDash"The documentation for that route is a file in the repository, and it spells out the three things that go wrong. The container mode has to be enabled, along with the veth interface and the bridge. The firewall needs an input chain rule, and the absence of that rule is named as the usual cause of a bare timeout when adding the router. And the data directory has to be mounted at /data, without which every repull of the image discards the database.
There is a second route with a caveat: the RouterOS Apps menu installs MikroDash from MikroTik's own copy of the catalogue, which MikroTik refreshes on their own schedule and which can lag behind the current release. Adding it as an ordinary container always pulls the latest release, so the choice is convenience against freshness.
The build dropped the Node stage
The Dockerfile carries a long explanation of a change that is worth reading, because it says something about how the project is run. The image was previously assembled with a Node stage running npm and an esbuild step, which is a strange thing to do in a Go project when esbuild is itself a Go program. The replacement is a command, cmd/webbuild, that does the same work from the Go stage through the esbuild Go API, and the comment states the output was verified byte for byte against the Node build before the stage was removed.
The stated benefit is not speed. It is that the image no longer pulls in a second language runtime, and that a contributor can produce a correct build with the Go toolchain alone. The type check still needs Node, but it lives in the frontend package manifest and it emits nothing, so it gates a change without being required to make one. The rest of the build compiles a static Go binary with CGO disabled and copies it into an Alpine runtime with /data as the only mount, and a multi-architecture build uses buildx with the three supported platforms:
docker buildx build --platform linux/amd64,linux/arm64,linux/arm/v7 -t mikrodash:local --load .The image also fetches a geo database at build time, and the comment explains that this replaced copying the addresses out of the old Node image, which shipped a fixed file whose contents drifted because nothing in that pipeline ever refreshed it.
A patched router client is the interesting dependency
The Go module file contains the most revealing line in the repository, and it is a comment rather than a version number. The routeros client at version 3.0.1 loses a reply that arrives before its tag is registered, so the project carries a patched copy of it in the third_party directory, with the reasons documented in a patches file, and the module file replaces the upstream dependency with the local path.
That is a significant thing to know if you are considering this software, because it means the dashboard does not use the stock client. It is also a well handled problem: the patch and its rationale are in the repository rather than hidden, which is what you want from a fork of a dependency. The rest of the dependency list fits the job. A WebSocket library for the browser connection, the geo database reader for mapping addresses, the WireGuard module for the provisioning tunnel, a PDF generator for reports, and a pure Go SQLite implementation, which is what lets a single static binary carry its own database with no database server to install.
Access control, single sign-on and the write audit
The security posture is described in four claims that are specific enough to check. Credentials are encrypted at rest. Every write is permission-checked and audited. Changes that could cut the dashboard off from the router are refused or warned about first. And there are per-user accounts with editable roles, expressed as a read and write matrix per page, granted over everything, over a site, or over a single router.
Single sign-on is supported against any OpenID Connect provider, with Entra ID, Okta, Keycloak and Authentik named, and the role decided by a claim the provider sends. The password form never goes away, which the project describes as the local administrator always being a way back in, and that is a deliberate trade rather than an oversight. The encryption key is either supplied through an environment variable or generated randomly on first start and written to a secret file on the data volume, and the environment example says to set it only if you need to manage your own key, for instance for a backup and restore across different volumes.
The comments in the compose file are warnings, not decoration
The project's own Compose file opens with a note that the project name and the volume name are load-bearing, and it explains why: together they produce the volume that holds every history sample, every alert row, every audit row the install has ever written, plus the encrypted settings and the user store. Renaming either of them silently starts a brand new empty volume, which looks exactly like total data loss. A second note in the same file records a rename that has already happened once, from a Go-suffixed name to a plain one, and says the compose project name was deliberately left alone so the data volume cannot be orphaned by the change.
The other long comment covers the zero-touch provisioning port, and it is a good example of a failure that gives no error at all. The container needs no network administration capability and no tunnel device because the implementation is in userspace, but the port MikroDash binds comes from the setting inside the interface while Docker publishes the port named in the compose file. If the two disagree, every handshake arrives at a port where nothing is listening, and the tunnel still logs that it is up. The environment file names the same trap for the write timeout, the trusted proxy for forwarded headers, the maximum simultaneous browser connections and the listen port.
Editorial conclusion
MikroDash suits a homelab or small site running MikroTik gear where the router API is already the source of truth and a refreshing dashboard is too slow to be useful, because the connection model pushes changes rather than polling, and the deployment is one image and one volume. It is the wrong choice if you cannot accept a dashboard holding router credentials, even encrypted, since a compromise of the dashboard is a compromise of the fleet, and it is the wrong choice if you need to run anything other than RouterOS v7. Before you deploy, read the comment at the top of the compose file about the project and volume names, because renaming either silently starts an empty volume and looks like total data loss, and make sure the zero-touch provisioning port in the compose file matches the listen port in the settings, since a mismatch fails silently with the tunnel still reporting itself up. The licence is MIT, the last push was on 2026-10-19 and the current release is v0.8.76.
Frequently asked questions
How do I deploy MikroDash?
With a Compose file that runs the image ghcr.io/secops-7/mikrodash:latest, publishes port 3081 and mounts a single named volume at /data, then docker compose up -d. On first run you create the administrator account with the setup code printed in the log, and no environment file is required.
Does MikroDash need a database server?
No. The project states there is no database server, no agents on the router and no CDN, and the Go module file shows a pure Go SQLite implementation, so a single static binary carries its own storage in the one Docker volume.
Can MikroDash run on the MikroTik router itself?
Yes, using the container support in RouterOS v7, by adding it as an ordinary container. The walkthrough in the repository covers enabling container mode, the veth interface and bridge, the firewall input chain rule whose absence causes a bare timeout, and the /data mount without which every repull discards the database.
How are router credentials stored?
They are encrypted at rest, and the key comes from the DATA_SECRET environment variable or is generated randomly on first start and saved to /data/.secret on the volume. Every write is permission-checked and audited, and changes that could cut the dashboard off from the router are refused or warned about first.
Which platforms are the container images published for?
linux/amd64, linux/arm64 and linux/arm/v7, on every release tag, so the latest tag always points at the latest release. A specific version can be pinned by tag, and the current release is v0.8.76, published on 2026-10-19.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/secops-7-mikrodash)Was this useful?