# The API user

The dedicated RouterOS user the collector logs in as, the policy it needs for each command, and what that policy lets it read.

Source: https://jmrplens.github.io/mikroscope/security/api-user/

The agent needs no RouterOS account. Three things on your host do: the collector's API tier, the
relay transport, and the router-log markers. This page answers which of them needs which policy,
how to create a user that has that and nothing more, and what such a user can still read.

## Which commands need it

| Used by                                                                          | Runs over the binary API                                                                                                                                                                                                                                             | Policy          |
| -------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------- |
| `forward`'s API tier                                                             | `/interface/monitor-traffic`, `/interface/print` (`name`, `default-name`, `type`, `comment`, `actual-mtu`), `/interface/list/member/print` (`list`, `interface`), `/interface/bridge/port/print` (`interface`, `bridge`), `/interface/print stats-detail`, `/interface/ethernet/print stats`, `/system/resource/print`, `/system/resource/cpu/print`, `/system/health/print`, `/ip/firewall/connection/print count-only` | `read,api`      |
| `record --log-markers`, `mark --log-markers`                                     | `/log/print` (`time`, `topics`, `message`)                                                                                                                                                                                                                           | `read,api`      |
| the relay transport (`--transport relay`, or `auto` when direct does not answer) | `/tool/fetch output=user` against the agent's address                                                                                                                                                                                                                | `read,api,test` |

`/tool fetch` and `/tool profile` both require the `test` policy (verified
on RB5009UG+S+, RouterOS 7.24.2, 2026-09-11). mikroscope uses `/tool fetch` for the relay and does not use `/tool profile`.

`read,api` is enough for the API tier and for `--log-markers`. `test` is needed only when the relay
is used — `--transport relay`, or `auto` when the direct transport does not answer — whatever
`--api-mode` is. With `--api-mode off` the tier needs no user at all.

Not every call in the first row runs every time. `/system/health/print` is skipped in `slow` and
with `--no-health`; the conntrack `count-only` runs only when `--conntrack-every` is above 0, and
its default is 0 even in `full`; `monitor-traffic` runs only when `--interfaces` is set, while the three
configuration reads behind the interface inventory run whenever the tier is on, once before the
first kernel pull and again every `--labels-every`; the two stats reads follow `--counters-every`,
10 s by default. Which calls
run at which cadence is on [the RouterOS API tier](/mikroscope/sinks/api-tier/).

Without an address and a user, each command says so differently:

- `forward` runs the kernel tier alone and logs `api tier disabled: …`.
- `mark --log-markers` and `--transport relay` fail with
  `the RouterOS API needs --api, --api-user and MIKROSCOPE_API_PASSWORD`.
- `record --log-markers` keeps the recording, prints `log markers: the RouterOS API needs …` on
  stderr and exits 0.
- `--transport auto`, when the direct transport does not answer, fails with
  ``direct transport did not answer and the relay is not configured: the RouterOS API needs … (or `install --expose`)``.

That check looks only at `--api` and `--api-user`. An empty `MIKROSCOPE_API_PASSWORD` is not caught
there; it shows up as a failed login, `api <address>: …`.

## The group and the user

A group that grants `read`, `api` and `test` and denies every other policy by name, and a user in
it restricted to the collector's address:

```text
/user/group/add name=mikroscope policy=read,api,test,!write,!ftp,!local,!telnet,!ssh,!reboot,!policy,!winbox,!password,!web,!sniff,!sensitive,!romon,!rest-api
/user/add name=mikroscope group=mikroscope password=<generate> address=<collector host>/32
```

Drop `test` from the group if you will never use the relay.

Restrict `address=` to the collector host, and restrict `/ip/service` for `api` to your LAN. Both
are RouterOS-side limits on where the password is accepted from, and neither depends on mikroscope.

Make this user for mikroscope rather than reusing one made for another tool. A least-privilege API
user built for something else typically belongs to a group that denies `test`, so it cannot run the
relay, and widening that group widens it for the other tool as well.

## What `read` still reads

`read` is not narrow. **Over the binary API, `/container/print` returned every property of every
container, `cmd` and `envlist` included, to a user with only `read,api`** (the user
`mikroscope`, RB5009UG+S+, RouterOS 7.24.2, 2026-09-11; only the property names were printed). Reading the envlist
entries' values in `/container/envs` was not checked separately; the design assumes this user can,
and so treats the agent's `TOKEN` entry, when one is set, as readable by it.

The collector narrows what it asks for where it reads configuration. The three interface-inventory reads
name their properties — `name`, `default-name`, `type`, `comment` and `actual-mtu`; `list` and
`interface`; `interface` and `bridge` — and no other field, so none of them brings back a field that
could carry a secret; `/system/resource`, `/system/resource/cpu`, `/system/health` and `/log/print` carry
a `.proplist` as well. The counter reads — `monitor-traffic`, `stats`, `stats-detail` — and the
conntrack `count-only` do not. None of this limits what the user is allowed to request: it can
still ask for every container's properties.

## How the CLI passes it

| Setting  | Flag         | Environment variable      |
| -------- | ------------ | ------------------------- |
| address  | `--api`      | `MIKROSCOPE_API_ADDR`     |
| user     | `--api-user` | `MIKROSCOPE_API_USER`     |
| password | none         | `MIKROSCOPE_API_PASSWORD` |

The password has no flag on purpose: a flag is visible in `ps` and in a shell history.
`.env.example` gives the address as `192.168.88.1:8728`.

> **The API connection is not encrypted**
>
> `record`, `mark` and `forward` connect to the plain binary API. The vendored client can dial TLS,
> but no flag uses it, so the login and every reply cross the network between the collector and the
> router unencrypted. `address=` limits where the login is accepted from; it does not change that.

## See also

- [What runs where](/mikroscope/security/): every piece, what it reaches and which credential it
  holds.
- [The RouterOS API tier](/mikroscope/sinks/api-tier/): what the collector reads over this user,
  and the `off`, `slow` and `full` presets.
- [Reaching the agent](/mikroscope/install/reaching-the-agent/): the direct and relay transports,
  and when the relay needs `test`.
