neuron-explorer
Steering-first neuron explorer for Qwen3.5-4B: push every MLP neuron, keep every rollout, browse the results
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 brows
Developer toolsGo · TypeScriptGitHub @SecOps-7Self-installOwner unconfirmed
Paste into Claude or ChatGPT for installation instructions suited to your environment.
Have you tried it? One tap is enough. No sign-in needed.
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
Taken from the repository README
Loading the full README.
Read the full README ↗# 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 -d
Open http://localhost:3081. On first run MikroDash asks you to create an administrator account, using the setup code it prints to its log (docker compose logs mikrodash), then walks you through adding your first router and testing the connection. No .env file is needed.
[!TIP] Images are published for
linux/amd64,linux/arm64andlinux/arm/v7on every release tag, solatestalways means the latest release, never unreleased work. Pin a version withghcr.io/secops-7/mikrodash:<version>.
MikroDash can run on the MikroTik it monitors, using RouterOS's own container support:
/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"
Follow docs/routeros-container-install.md for the full walkthrough: enabling container mode, the veth and bridge, the input chain firewall rule (its absence is the usual cause of a bare "timed out" when adding the router) and the /data mount, without which every repull discards your database.
The RouterOS Apps menu installs MikroDash from MikroTik's own copy of the catalogue, which they refresh on their own schedule and which can lag behind the current release. Adding it as an ordinary container, as above, always pulls the latest release.
Only Docker is needed on the host:
git clone https://github.com/SecOps-7/MikroDash.git
cd MikroDash
docker build -t mikrodash:local .
docker run -d --name mikrodash --restart unless-stopped \
-p 3081:3081 -v mikrodash-data:/data mikrodash:local
The multi-stage build bundles the frontend with esbuild through its Go API (cmd/webbuild, so no Node runtime is involved), compiles a static Go binary with CGO_ENABLED=0, and copies both into an Alpine runtime with /data as its only mount. For a multi-arch build:
docker buildx build --platform linux/amd64,linux/arm64,linux/arm/v7 -t mikrodash:local --load .
A worked deployment on a separate Docker host is in docs/deploy-r5s.md.
| 📊 Dashboard | A drag-and-drop grid of cards (traffic, system health, network flow, network topology, connections, top talkers, WireGuard, and optional cards such as a world connections map, BGP peers, NetWatch, logs, a Security Score, and API diagnostics that show every router command by who asked for it). Layouts are saved to your account, so every browser shows the same arrangement. |
| 🛰️ Multi-router fleet | Manage many routers from one install. Switch from the header, where devices are grouped by site, with no reload. The Devices page shows the whole fleet as cards, a sortable list or a world map, filterable by site: each device's 24-hour connectivity, last backup, open alerts and available updates at a glance. Click one for its own overview - connectivity history and outages, live usage, ports, clients, its public IP and recent alerts - without leaving the device you are on. Routers are placed on the map by their public IP until you pick a town, and a whole list of devices can be added at once from a CSV (Settings -> Devices -> Import). |
| 🔐 Users and access control | Per-user accounts with editable roles (a read and write matrix per page), granted to users or groups over everything, a site, or a single router. Or sign in with an existing account: single sign-on against any OpenID Connect provider (Entra ID, Okta, Keycloak, Authentik), with the role decided by a claim your provider sends. The password form never goes away, so the local administrator is always a way back in. |
| 🔔 Alerts and notifications | Interface up/down, WireGuard peers, CPU, ping loss, NetWatch hosts, router online/offline, RouterOS updates, configuration drift and backup failures, delivered through notification channels you create: SMTP, or a webhook URL for Telegram, Pushbullet, ntfy, Discord, Slack, Gotify, Pushover, a generic JSON endpoint, or an Apprise server for everything else. Each channel picks its own alert types, devices, thresholds and cooldown, and scheduled reports go out through one. |
| 📈 History and reports | Traffic, ping, bandwidth, alerts and connectivity recorded to SQLite, viewable by date range, exported to CSV or PDF, and emailed on a daily, weekly or monthly schedule. Click any interface for its own traffic: live for the last minute, or up to thirty days back for the interfaces you choose to record. |
| 🪄 Zero-touch provisioning | Add a router before it exists: a wizard makes a short script for it, and when the router runs it, it calls home, joins the fleet and receives its Config Management template on its own. Remote routers dial in over a WireGuard tunnel built into MikroDash, from behind NAT anywhere; a generic script brings in a whole rollout, each router waiting for your approval. |
MikroDash has more than fifty pages. Here they are by area (the sidebar can group them too, or you can hide the ones you do not use). Most read live data; with write access, the configuration pages edit the router directly.
| Area | Pages |
|---|---|
| Overview | Dashboard, Devices, Config Management, Network Topology, WAN |
| Wireless | Wifi Networks, Wifi Clients, Wifi Map (draw your site and see clients around each access point), CAPsMAN (both the wifi and legacy stacks) |
| Network | Interfaces, IP Addresses, VLANs, Bridges, DHCP, DHCP Servers, DHCP Clients, DNS, IP Pools, Interface Lists, ARP |
| Routing | Routing (routes and BGP), Routing Tables, Routing Rules, OSPF, VRRP |
| Tunnels | VPN (an overview of every tunnel technology, with a card per live connection), WireGuard (interfaces and peers, with a client configuration and a scannable QR code), PPP, IPsec, OpenVPN, PPPoE Clients |
| Traffic | Connections (a world map, or a list of every connection), Bandwidth, Queues, Logs |
| Security | Firewall (Filter, NAT, Mangle and Raw, with reorder, undo and redo), Address Lists, Certificates, Security Scan |
| System | Users (RouterOS accounts and groups), Services, Packages, Scripts, Scheduler, NTP Client, Clock, Logging, SNMP, Files, Containers, NetWatch |
| MikroDash | Tools, Terminal, AI Agent, Reports, Backups, Audit Trail, Settings |
Every table sorts by its headers, except the ones where order is meaning (firewall rules, queues, routing rules, IPsec policies): those always show the router's order, with move arrows.
*.auto.*) or to install at the next reboot (.npk). A file's contents are read only when you ask, capped, with credential values hidden.Off by default. Nothing is sent anywhere until you switch it on and configure an endpoint.
docs/mikromcp-parity.md maps what the assistant can reach.
Off by default. Switch it on under Settings, Provisioning, and give the public name or address routers will dial.
/import, or paste it into a terminal. It sets up the tunnel and an API user limited to MikroDash's address, then calls home every minute until MikroDash answers, and removes itself.| Key | Opens |
|---|---|
1 | Dashboard |
2 | WAN |
3 | Wifi Networks |
4 | Wifi Clients |
5 | CAPsMAN |
6 | Interfaces |
7 | DHCP |
8 | DNS |
9 | VLANs |
/ | Logs, with the search box focused |
Create a dedicated, read-only API user. Every page, chart and alert works with it, and a compromised dashboard cannot change your router:
/ip service set api port=8728 disabled=no
/user group add name=mikrodash policy=read,api,test,!local,!telnet,!ssh,!ftp,!reboot,!write,!policy,!winbox,!web,!sniff,!sensitive,!romon,!rest-api
/user add name=mikrodash group=mikrodash password=<a-strong-password>
Pages that change the router need more than read:
| Page | Needs |
|---|---|
| Configuration pages (Firewall, Routing, DNS, DHCP, VLANs, Bridges, Interfaces, VPN, Queues, Packages and the rest) | write |
| Users (RouterOS accounts and groups), and credential profiles | write and policy |
| Backups | write and ftp |
| Terminal | whatever the line you type needs - see below |
ftp governs reading and writing files on the router, which /export file= and /system/backup/save need; it does not enable the FTP service. policy governs user management, so an account holding it can create router users. Grant it deliberately, not by default.
/user group set [find name=mikrodash] policy=read,write,policy,api,test,!local,!telnet,!ssh,!ftp,!reboot,!winbox,!web,!sniff,!sensitive,!romon,!rest-api
Without these nothing breaks: a page that is refused drops to read-only and shows the command it needs. MikroDash never lets you edit the account it signs in with, or that account's group.
Credential profiles need the same two policies, for the same reason: a profile (Config Management -> Credentials) creates a RouterOS account on every device you link it to, which is user management. Each profile creates its own group with the policies you choose, so it never shares a group with MikroDash's own account, and that account can never be taken by a profile - the same guard refuses it per device. See SECURITY.md on what a fleet-wide password is worth.
The MikroDash login is the one exception, and it is deliberate. The pinned "MikroDash login" row on the same tab keeps the password of the mikrodash account MikroDash itself signs in with, in one place. Linking a device creates that account in a mikrodash group, or adopts the one you made by hand, and MikroDash then signs in through the profile. Changing the password changes it on every linked device or on none: each device must be online, each is confirmed with a fresh sign-in, and any failure puts the old password back everywhere.
The Terminal page is the exception to that whole table, because it does not know what your line will do. It sends what you type to the router's own console and shows the reply, so the policies above are not a list it consults - they are the limit the router enforces on it. On the read-only account at the top of this section it can read and nothing else, because RouterOS refuses the rest.
Who may use it is a permission, per device: grant a role write access to the Terminal page in Settings -> Authentication -> Access Management. Administrators have it already; nobody else does until you say so, and a grant on one device does not carry to another. Every line is recorded in the Audit Trail whether it worked or not. There is no guard, no read-back and no undo on this page, which is the point of it and the reason the permission is worth granting deliberately.
[!NOTE] If a queue seems to do nothing, check FastTrack. FastTracked connections bypass simple queues, and the Queues page tells you when that is happening.
A self-signed certificate is enough:
/certificate add name=local-ca common-name=local-ca days-valid=3650 key-size=2048 key-usage=key-cert-sign,crl-sign
/certificate sign local-ca
/certificate add name=api-ssl-cert common-name=mikrodash days-valid=3650 key-size=2048 key-usage=digital-signature,key-encipherment,tls-server
/certificate sign api-ssl-cert ca=local-ca
/ip/service set api-ssl certificate=api-ssl-cert disabled=no port=8729
Then edit the router in MikroDash, enable TLS and Allow self-signed cert, and set the port to 8729.
Or let MikroDash do all of the above: Auto Switch to API-SSL in the device's edit dialog creates the certificates, enables the service, and moves the connection across once the device answers on 8729. The plain API is left on.
The Dashboard's Top Talkers card reads per-device rates from RouterOS Kid Control. RouterOS only tracks devices there once at least one Kid Control profile exists, so on a router without one the card says "No devices".
Create one profile that allows everything:
/ip kid-control add name=monitor mon=0s-1d tue=0s-1d wed=0s-1d thu=0s-1d fri=0s-1d sat=0s-1d sun=0s-1d
Within a few seconds RouterOS starts listing the devices it sees on your LAN. Kid Control only restricts devices assigned to a profile, and none are, so this blocks nothing. The all-day schedule is there in case a device is ever assigned to it: without it, RouterOS defaults to 7h-21h.
Devices found this way have no name. To name them from your DHCP leases (the lease comment if it has one, otherwise the client's hostname), wait about ten seconds and paste:
:foreach l in=[/ip dhcp-server lease find] do={
:local mac [/ip dhcp-server lease get $l mac-address]
:local nm [/ip dhcp-server lease get $l comment]
:if ($nm = "") do={ :set nm [/ip dhcp-server lease get $l host-name] }
:local d [/ip kid-control device find where mac-address=$mac]
:if ($nm != "" && [:len $d] > 0) do={
:if ([/ip kid-control device get $d name] = "") do={
:do { /ip kid-control device set $d name=$nm } on-error={
/ip kid-control device set $d name=($nm . " (" . [:pick $mac 9 17] . ")")
}
}
}
}
Living Room TV (E2:57:BE).kc-names, then /system scheduler add name=kc-names interval=1h on-event=kc-names.Almost everything is configured in the web UI (Settings) and stored on the /data volume: routers, users and roles, notification channels, poll intervals, retention and appearance. /data is the only mount, and it holds encrypted settings, the user store, the SQLite history database and configuration backups.
All optional.
| Variable | Purpose |
|---|---|
MIKRODASH_ORIGINS | Hostnames the browser uses to reach MikroDash, comma separated (wildcards like *.example.com work). Required behind a reverse proxy; see below. |
MIKRODASH_TRUSTED_PROXIES | IPs or CIDR ranges of your reverse proxies. Their X-Forwarded-For is believed, so the login limit and audit trail see real visitors. Empty trusts none. |
FORCE_HTTPS | true marks the session cookie Secure, for use behind a TLS-terminating proxy. Plain http:// sign-in stops working while it is set. |
DATA_SECRET | The key for credentials at rest. Overrides the key generated on first run and saved to /data/.secret. |
LOG_HISTORY_SIZE | How many router log lines to keep in memory for the Logs page. |
MIKRODASH_ROUTER_CONCURRENCY | The cap on API commands in flight per router. |
TZ | The timezone of the container's log lines. Schedules follow the display timezone set in Settings instead. |
The image passes these as its CMD; give the container its own command: to override them.
| Flag | Image default | Purpose |
|---|---|---|
-listen | :3081 | Address to serve on |
-data | /data | Data directory |
-history | on | Record traffic, ping and connectivity history for Reports |
-backup-scheduler | on | Take scheduled configuration backups |
-retention | on | Run the daily sweep that ages old data out of the database |
-alert-dispatch | on | Send alert notifications and scheduled report emails |
-no-pool | off | Do not hold background connections to routers nobody is watching |
-origins | empty | Same as MIKRODASH_ORIGINS |
-trusted-proxies | empty | Same as MIKRODASH_TRUSTED_PROXIES |
-geo | /app/geo | Directory with the bundled geo-IP database and city list |
The four feature switches are off in the bare binary and on in the image, because each is unsafe to run twice against the same routers: two instances would take every backup twice and send every alert twice. If you run a second instance against the same fleet, turn them off there.
GET /healthz reports startup and router connection state, and is what the container health check uses.
MikroDash is built for your local network. It serves plain HTTP; terminate TLS at a reverse proxy if you need it.
/data volume, and /data/.secret in particular, private./data.To report a vulnerability, see SECURITY.md.
MikroDash refuses a WebSocket whose Origin does not match the Host it sees, which is what stops a hostile page opening an authenticated socket to a MikroDash you are signed in to. Behind a proxy the two differ, so the UI loads and then stays empty, with this in the log:
[ws] accept: failed to accept WebSocket connection: request Origin "dash.example.com" is not authorized for Host "..."
Name the host the browser uses, including the port when it is not the default:
environment:
- MIKRODASH_ORIGINS=dash.example.com
- MIKRODASH_TRUSTED_PROXIES=172.18.0.0/16 # your proxy's address or network
Alternatively, have the proxy preserve the original Host header (proxy_set_header Host $host; in Nginx). X-Forwarded-Host is deliberately not trusted, since any client can send one.
MikroDash does not ship cloudflared, but it runs well beside Cloudflare's own container. This puts the login page on the internet, so first make sure sign-in is required, put Cloudflare Access in front of the hostname, and use strong passwords.
dash.example.com, pointing at http://mikrodash:3081..env as TUNNEL_TOKEN=...:services:
mikrodash:
# ... your existing service ...
environment:
- MIKRODASH_ORIGINS=dash.example.com
- MIKRODASH_TRUSTED_PROXIES=172.18.0.0/16 # the network the two containers share
- FORCE_HTTPS=true
cloudflared:
image: cloudflare/cloudflared:latest
command: tunnel --no-autoupdate run
environment:
- TUNNEL_TOKEN=${TUNNEL_TOKEN}
restart: unless-stopped
depends_on:
- mikrodash
docker network inspect <project>_default --format '{{(index .IPAM.Config 0).Subnet}}'. MikroDash refuses to start if MIKRODASH_TRUSTED_PROXIES does not parse.FORCE_HTTPS=true means plain http:// sign-in on the LAN stops working; use the tunnel hostname everywhere, or leave it off. The official cloudflared image covers linux/amd64 and linux/arm64 only.
RouterOS binary API (TCP / TLS)
│
internal/routeros adapter over go-routeros (a patched copy in third_party/)
internal/roscache one read per menu, shared by every page that wants it
internal/collect collectors, one per RouterOS subsystem
internal/session one session per router, owning its shared connection
internal/alert alert rules internal/guard write guards
internal/store /data: encrypted settings, users, routers
internal/db SQLite history and audit (pure Go, so the binary is static)
internal/server HTTP routes and the WebSocket protocol
│
web/src the TypeScript frontend
Concurrent API channels, not data volume, are what strain a small router, so the collector layer is built to ask for less: live data streams, configuration is polled, and a collector runs only while a page, card, alert or report needs it. Collector-Architecture.md describes it in full.
Geo-IP data comes from DB-IP - City Lite for country and city, ASN Lite for the organisation that owns an address - both bundled into the image at build time under CC BY 4.0. Lookups happen locally; nothing leaves the machine.
Go runs in a container, so Docker is the only hard requirement. Node is needed only to type-check and test the frontend.
(cd web && npm ci) # once: TypeScript and esbuild for the frontend checks
sh tools/verify.sh # everything: gofmt, vet, go test, generated code, tsc, web tests
sh tools/verify.sh --no-docker # frontend half only
tools/verify.sh discovers what to check rather than working from a list, so a new Go test or *.test.ts file runs without being registered anywhere. You do not need a MikroTik to contribute: MikroDash starts without one and shows the setup wizard.
Read CONTRIBUTING.md for the local setup and the project's conventions, and Collector-Architecture.md before changing how data is read from a router.
Issues and pull requests are welcome, from typo fixes to new pages. Check the open issues first, and open one before a large change so the approach can be agreed. See CONTRIBUTING.md.
MIT, see LICENSE. Third-party attributions are in THIRD_PARTY_NOTICES.md.
MikroDash is an independent community project and is not affiliated with, endorsed by, or associated with MikroTik SIA. MikroTik and RouterOS are trademarks of MikroTik SIA.
| 🧩 Config Management | A library of 21 ready-made configuration templates (firewalls, a threat IP blocklist, VLANs, a guest network, WireGuard, DNS, queues, monitoring) plus your own, captured from a router or written in the editor. Every setting has a working default. Deploy to one router or the fleet: a syntax check first, a restore point, a canary router before the rest, an automatic revert if a change cuts MikroDash off, and History and Drift afterwards. |
| 💾 Backups | Scheduled configuration backups kept only when something changed, with a unified diff of what moved, retention rules, and a guarded restore. Optionally a migration export as well, per device: the full configuration with its passwords and keys included, encrypted at rest, for rebuilding on a different device. |
| 🛠️ Tools | Ping, traceroute with an animated world map of the hops, torch, bandwidth test and a packet sniffer with a pcap export, run from the router with live output and a Stop button. |
| ⌨️ Terminal | A RouterOS console in the browser, for the device you have selected. The line you type goes to the router's own parser, so where, :put [...] and everything else the CLI understands works, and what comes back is the router's own text. Granted per device through the Terminal page permission, and bounded by what the RouterOS account MikroDash signs in with may do. Every line is in the audit trail. |
| 🛡️ Security Scan | Audits the router's configuration (management access, firewall, exposed services, accounts, system, wireless and certificates), scores it, and links each finding to the page where it is fixed. The score is also a Dashboard card, and the AI Agent can run the scan when you ask how secure a router is. |
| 🤖 AI Agent | An optional assistant that answers questions from live router data and makes changes through the same checks, audit trail and undo as the forms: one row, or several as a plan you approve once. It can reboot, upgrade, sign a certificate, set the clock, run a script, read a file or an export, and undo its own change, always with your confirmation. Works with any OpenAI-compatible endpoint, including local models. |
| 📦 Containers | RouterOS containers with their env lists, mounts and interfaces, plus an Apps tab that browses RouterOS's app store and installs an app in one click. |
| 🧾 Audit trail | Every write, allowed or refused, with who, where, what changed and the outcome. Filterable and exportable to CSV. Credential values are never stored. |
| 🧪 Optional features | Extras that stay off until you switch them on in Settings -> Features: DNS bulk edit and export, a DNS fleet sync to a reference router, domain list subscriptions kept as FWD entries, a DNS cache browser and domain route trace, a Domain Routing card and alert, a device watch list that alerts when a device goes missing, Wi-Fi client history, Wi-Fi map weak spots and CAP version checks. Switched off, a feature reads nothing from your routers. |
| 🎨 Make it yours | 26 colour palettes, 26 self-hosted fonts, contrast and brightness controls, visible-page presets, a grouped sidebar, and custom branding (name and icon). |