MikroMan is a lightweight management, traffic accounting, and monitoring companion for MikroTik RouterOS gateways. It provides byte-accurate per-device accounting, automatic MAC-rotation tracking, parent-child bandwidth shaping, automated configuration backups with visual config drift, live connection observability, and safe firmware update orchestration.
-
📊 High-Precision Traffic Accounting:
- Measured via dedicated RouterOS firewall mangle
action=passthroughcounters, bypassing unreliable queue byte counters. - Accumulates traffic deltas against persisted baselines, surviving network outages and distinguishing hardware reboots.
- Configurable monthly ISP billing cycle anchors with optional time-of-day boundary slicing.
- Built-in tools to reconcile historical LAN-to-LAN overcounts.
- Measured via dedicated RouterOS firewall mangle
-
🚦 Lockout Prevention & Write Guards:
- Pure validation layer (
guards.py) intercepting all mutations before network packets are constructed. - Immune target protection: loopbacks, wildcards, management subnets, and container endpoints can never be throttled, blocked, or dropped.
- Foreign resource isolation: configuration rules not created by MikroMan (
mikroman:) are strictly protected from mutation or deletion. - Relational queue validation preventing invalid rate parameters and circular parentage.
- Pure validation layer (
-
🛡️ Multi-Router Management & Isolated Environments:
- Complete operational isolation: users, devices, queues, rollups, quotas, and timezone offsets exist strictly per-router.
- Instant context switching in UI and WebSocket telemetry.
- Seamless hardware swap workflow (
Change Router) with data retention choices (keepvsreset_hardware). - Soft archive vs permanent purge router lifecycles.
- Automated TLS/SSL certificate generation directly on RouterOS without modifying custom service ports.
-
🗂️ Config-Drift Backups & Visual Diff Viewer:
- Automated dual-pair exports: compact
.rscplain-text scripts and encrypted.backuprecovery archives. - Zero-false-drift SHA-256 fingerprinting via volatile timestamp header stripping.
- Interactive unified diff viewer with structured hunks, comparing historical revisions or live router state.
- Flash write safety invariants: polling for stable file sizes and guaranteed temporary file cleanup sweeps.
- Automated dual-pair exports: compact
-
⚡ Firmware & Update Intelligence:
- Multi-channel update tracking across
stable,long-term,testing, anddevelopmentchannels. - RouterBOOT bootloader status tracking and one-click staging.
- Bounded upstream changelog streaming client with in-memory caching and negative TTL.
- Pre-upgrade safety invariant: mandatory automated pinned backup and strict router name confirmation gate before upgrade dispatch.
- Autonomous 4-stage reboot reconnection state machine.
- Multi-channel update tracking across
-
🌐 Real-Time Observability & Centralized Logs:
- Real-time
/ip/firewall/connectiontracker with device attribution and safe socket termination. - In-memory offline GeoIP engine resolving destination countries without external API dependencies.
- Centralized terminal log viewer with regex event classification (auth, interface, DHCP, wireless, firewall, system).
- 1-click RouterOS
/system/loggingtopic management.
- Real-time
-
📈 Peak-Preserving Hardware & Bandwidth Graphs:
- Router Health tab charts interface RX/TX, CPU load, RAM and board temperature/voltage over 1 h / 6 h / 24 h / 7 d / 30 d ranges.
- Every display bucket carries its mean and its worst case, so a burst shorter than the bucket is still on the chart: solid line = average, shaded band = peak (min–max on the voltage view).
- Downsampling runs inside SQLite (
strftimebucket grid, two-level grouping), so a 30-day window returns ~180 rows instead of pulling a million raw samples through the ORM. - Rates are summed per sample before the peak is taken, so a multi-interface selection cannot invent a combined spike out of two unrelated moments.
- Outages are drawn as blanks, not ramps:
/api/v1/metrics/{system,interfaces}reportbucket_seconds, and any gap wider than 2.5 buckets ends the line's current run, so hours nobody sampled stay visibly empty. - The range selector shows the timestamp of the newest reading, because a collector that stopped with its host still prints a plausible "current" rate.
- Axes scale to the peak rather than to the tallest average, and points are placed by timestamp rather than by array index.
- A stalled router leaves one WARNING on state change and one INFO on recovery, instead of a debug line nobody reads or a warning every 25 seconds.
-
📦 Self-Hosting on the Router (RouterOS Containers):
- MikroMan can run as a container on the RouterOS device it manages:
POST /api/v1/routers/{id}/containers/setup/planshows every change it would make (containerlayer-dir/tmpdiron external storage, bridge, veth, gateway address, masquerade, mount, the container itself) and writes nothing;.../setup/applyexecutes that same plan. - Idempotent and defensive: each step checks what the router already has, refuses to modify objects it did not create (
mikroman:comments), blocks before creating anything when the storage is missing or the chosen subnet is already in use, and stops at the first refused command while reporting which steps landed. - The web port forward is only ever created bound to one interface; an unbounded
dstnatwould expose the administrative UI on WAN. POST .../containers/migrate-datacarries the existing installation over: a consistent snapshot of the live database via SQLite's backup API plus the.secret_keythat decrypts it. It refuses to run while the target container is up, so a live database is never replaced underneath its application.- No credentials are written into
/container/envs: router logins and the bot token already travel inside the encrypted database, and copying them to env would put them in plaintext in the running config and every exported.rsc. - Manual path for a bare router:
scripts/setup_ros_container.rsc.
- MikroMan can run as a container on the RouterOS device it manages:
-
🤖 Dual-Mode Telegram Bot:
- Operates in both Long Polling (zero-config NAT) and Authenticated Webhook modes.
- Proactive alerts for new device arrivals, CPU spikes, thermal thresholds, and WAN IP changes.
- Interactive inline commands for gateway status, user limits, and pausing access.
For detailed architectural specifications, algorithms, and configuration guides, refer to the MikroMan Project Wiki:
- System Architecture & Design
- Traffic Accounting Engine Mechanics
- Lockout Prevention & Write Guards
- Multi-Router Management & Lifecycle
- Backups, Config Drift & Visual Diff
- Firmware & Update Intelligence
- Live Connections & Router Log Stream
- Deployment, Storage & Container Mode
Pre-built multi-architecture container images (linux/amd64, linux/arm64, linux/arm/v7) are automatically built and published to GitHub Container Registry upon every release.
How the multi-architecture image is built
The Dockerfile uses three stages so that a single build serves 64-bit servers
and 32-bit ARM routers (RB4011, RB3011, hAP ac²) alike:
| Stage | Runs on | Purpose |
|---|---|---|
frontend |
Build host ($BUILDPLATFORM) |
Compiles the static JS/CSS bundle natively at full speed, never under emulation. |
wheelbuilder |
Target architecture | Carries build-essential + libffi-dev and resolves every dependency into a local wheelhouse. |
runtime |
Target architecture | Installs from that wheelhouse with --no-index; ships without a compiler. |
The wheelbuilder stage exists because four hard dependencies publish no
linux/arm/v7 wheels on PyPI and ship source distributions only: cffi (via
cryptography), greenlet (via SQLAlchemy's asyncio support), MarkupSafe
(via Mako/alembic) and PyYAML. Since python:3.12-slim contains no compiler,
they are compiled once in the throwaway builder stage and the finished wheels
are bind-mounted into the runtime stage, which keeps the shipped image slim.
Two optional C accelerators - uvloop and httptools - are excluded on ARMv7
by environment marker instead. Neither is required for correctness: uvicorn
falls back to the standard asyncio event loop and the h11 parser.
git clone https://github.com/masseselsev/mikroman.git
cd mikroman
docker compose up -dCompose pulls the published multi-architecture image and brings up the named
data volume with it — nothing is compiled on the device, which matters on the
32-bit ARM boards this runs on. Upgrading is docker compose pull && docker compose up -d.
Building from source instead. Contributors, and anyone running a change that has not been released yet, add the build overlay:
docker compose -f docker-compose.yml -f docker-compose.build.yml up -d --buildThe overlay tags the result mikroman:local, so a local build can never be
mistaken for — or silently shadow — a published release in the same image store.
Note that building on the target device is only realistic on amd64/arm64; an
armv7 board does not have the memory to compile the frontend bundle.
docker run -d \
--name mikroman \
--restart unless-stopped \
-p 1928:1928 \
-v mikroman_data:/data \
ghcr.io/masseselsev/mikroman:latestOpen http://localhost:1928 in your browser. The first-run setup wizard will guide you through:
- Connecting to your MikroTik RouterOS gateway (REST API credentials).
- Configuring optional Telegram notifications.
- Selecting language (English / Russian) and theme (Dark / Light).
python3 -m venv .venv
source .venv/bin/activate
pip install -r backend/requirements.txt
uvicorn backend.app.main:app --host 0.0.0.0 --port 1928 --reloadcd frontend
npm install
npm run devRun the automated backend test suite:
.venv/bin/pytest -vRun code formatting and linter checks:
.venv/bin/ruff check .Run frontend unit tests and production build:
cd frontend
npm test
npm run buildMikroMan targets RouterOS 7.x (version 7.4 or higher recommended for REST API and container support).
| Architecture | Supported Devices | Notes |
|---|---|---|
| ARM64 | RB5009, CCR2004, CCR2116, CCR2216, hAP ax², hAP ax³, cAP ax | Native container support |
| ARM | RB4011, RB3011, RB1100AHx4, hAP ac², hAP ac³ | Native container support |
| MMIPS | hEX (RB750Gr3), hEX S, wAP R | Remote management mode |
| x86 / CHR | Cloud Hosted Router, Custom PC x86_64 | Full capability |
| TILE | CCR1009, CCR1016, CCR1036, CCR1072 | Full capability |
This project is licensed under the MIT License.