Environment variables
Two programs read environment variables, and they read different ones. The
CLI on your machine reads MIKROSCOPE_* variables as flag defaults, plus a
handful of credentials that have no flag, plus GRAFANA_URL and
GRAFANA_TOKEN. The agent on the router reads unprefixed variables
(RATE_HZ, TOKEN …) from its container envlist, which install writes. This
page lists both, from cmd/mikroscope/*.go and internal/agent/config.go.
How the CLI reads them
Section titled “How the CLI reads them”-
A variable sets a flag’s default; the flag on the command line wins.
-
A variable set to the empty string is treated as unset.
-
The CLI never reads a
.envfile. Export it into the shell first:Terminal window set -a; . ./.env; set +a -
Quote a URL that holds
&when it lives in a file yousource: unquoted,&is a shell operator..env.examplequotesMIKROSCOPE_INFLUX_URLfor that reason.
Most deployment flags have no variable. --rate, --buffer, --port,
--memory-max, --mem-limit-mb, --capture-mb, --triggers, --floor-hz,
--privileged, --ephemeral and --expose are set on the command line or not
at all. Commands and flags has every flag.
Router and deployment
Section titled “Router and deployment”| Variable | Flag | Read by | Default in the code | Value in .env.example |
|---|---|---|---|---|
MIKROSCOPE_ROUTER |
--router |
doctor, install, upgrade, uninstall, status |
none (required) | empty |
MIKROSCOPE_SSH_PORT |
--ssh-port |
the same | ssh config | 22 |
MIKROSCOPE_SSH_KEY |
--ssh-key |
the same | ssh agent or config | empty |
MIKROSCOPE_ARCH |
--arch |
the deployment verbs | arm64 |
arm64 |
MIKROSCOPE_AGENT_TAR |
--agent-tar |
plan, install, upgrade, image |
empty (build the agent here) | not in the file |
MIKROSCOPE_REMOTE_IMAGE |
--remote-image |
plan, install, upgrade |
empty (upload a tar) | not in the file |
MIKROSCOPE_NAME |
--name |
the deployment verbs | mikroscope |
commented out |
MIKROSCOPE_VETH |
--veth |
the deployment verbs | veth-mikroscope |
veth-mikroscope |
MIKROSCOPE_SUBNET |
--subnet |
the deployment verbs, record, forward |
172.30.10.0/30 |
172.30.10.0/30 |
MIKROSCOPE_IFACE_LIST |
--iface-list |
the deployment verbs | LAN |
LAN |
MIKROSCOPE_ADDR_LIST |
--addr-list |
the deployment verbs | LANs |
LANs |
MIKROSCOPE_DISK |
--disk |
the deployment verbs | empty (internal flash) | commented out, tmpfs |
MIKROSCOPE_LAN_ADDRESS |
--lan-address |
the deployment verbs | empty | commented out |
MIKROSCOPE_TOKEN |
--token |
the deployment verbs, record, forward |
empty | commented out |
Scroll sideways to see every column
MIKROSCOPE_TOKEN is two things at once. For install it is the token
written into the agent’s envlist, which the agent then requires. For record
and forward it is the token the direct transport sends. The envlist is not
a secret store: any RouterOS user with the read policy can list every
container’s envlist over the API (verified on RB5009UG+S+, RouterOS 7.24.2, ), which is why the token
is the only credential that goes there.
Reaching the agent and the RouterOS API
Section titled “Reaching the agent and the RouterOS API”| Variable | Flag | Read by | Meaning |
|---|---|---|---|
MIKROSCOPE_API_ADDR |
--api |
record, mark, forward |
RouterOS binary API host:port; .env.example has 192.168.88.1:8728 |
MIKROSCOPE_API_USER |
--api-user |
record, mark, forward |
the dedicated API user |
MIKROSCOPE_API_PASSWORD |
none | record, mark, forward |
that user’s password; there is deliberately no flag |
MIKROSCOPE_INTERFACES |
--interfaces |
forward |
comma-separated interfaces for monitor-traffic; .env.example has bridge,ether1 commented out |
Scroll sideways to see every column
The relay, --log-markers and the API tier fail, or in forward’s case are
disabled with a warning, unless --api, --api-user and
MIKROSCOPE_API_PASSWORD are all set. The API
user has the policy that user needs.
| Variable | Flag | Default in the code | Meaning |
|---|---|---|---|
MIKROSCOPE_INFLUX_URL |
--influx |
empty | InfluxDB 3 write URL |
MIKROSCOPE_LOKI_URL |
--loki |
empty | Loki push URL |
MIKROSCOPE_LOKI_TENANT |
--loki-tenant |
empty | X-Scope-OrgID |
MIKROSCOPE_OTLP_URL |
--otlp |
empty | OTLP/HTTP metrics endpoint |
MIKROSCOPE_GRAPHITE_ADDR |
--graphite |
empty | carbon plaintext host:port |
MIKROSCOPE_ELASTIC_URL |
--elastic |
empty | Elasticsearch or OpenSearch base URL |
MIKROSCOPE_TELEGRAF_URL |
--telegraf |
empty | Telegraf listener URL (http://, tcp:// or udp://) |
MIKROSCOPE_HOST_TAG |
--host-tag |
router |
host tag on every point in every sink; .env.example has rb5009 commented out |
Scroll sideways to see every column
Setting a sink’s URL variable is enough to turn that sink on: forward builds
every sink whose flag ends up non-empty, from the command line or from the
variable. Every one of these names carries the MIKROSCOPE_ prefix: a bare
LOKI_URL is read by nothing, and .env.example says so beside
MIKROSCOPE_LOKI_URL.
Credentials that have no flag
Section titled “Credentials that have no flag”A flag is visible in ps and in a shell history, so every secret the CLI uses
is read from the environment only.
| Variable | Used for |
|---|---|
MIKROSCOPE_API_PASSWORD |
the RouterOS API user |
MIKROSCOPE_INFLUX_TOKEN |
InfluxDB, sent as Authorization: Bearer <token> |
MIKROSCOPE_LOKI_TOKEN |
Loki |
MIKROSCOPE_OTLP_TOKEN |
the OTLP endpoint |
MIKROSCOPE_ELASTIC_AUTH |
Elasticsearch or OpenSearch |
MIKROSCOPE_ |
the Telegraf HTTP listener |
GRAFANA_TOKEN |
dashboards import and dashboards check |
Scroll sideways to see every column
Grafana
Section titled “Grafana”dashboards import and dashboards check read GRAFANA_URL (the default of
--grafana) and GRAFANA_TOKEN. Neither has the MIKROSCOPE_ prefix.
.env.example sets GRAFANA_URL twice, once empty in its LAN-services block
and once commented out in the Grafana block, and says the token never goes in
the file.
The agent’s envlist
Section titled “The agent’s envlist”The agent reads these from its container’s environment when it starts. An
invalid value makes it print one line starting
mikroscope-agent: bad configuration:, which RouterOS puts in its log under
the container topic, and exit with status 2.
| Variable | Agent default | Accepted | Meaning |
|---|---|---|---|
RATE_HZ |
10 |
1–100 | sampler rate |
BUFFER_S |
300 |
10–3600 | ring length in seconds |
PORT |
9123 |
1–65535 | HTTP port |
ADDR |
empty | an address | bind address. Empty binds :PORT, every address in the container’s network namespace; install always sets it to the agent’s veth address |
TOKEN |
empty | when set, every path but /healthz requires Authorization: Bearer <token> |
|
IRQ_TOP_K |
8 |
0–64 | interrupt lines kept per sample, busiest first; 0 ships no interrupt lines and no irq_total |
MEM_LIMIT_MB |
14 |
8–1024 | Go soft memory limit in MiB |
FLOOR_HZ |
0 |
0–1000 | 0 keeps the per-source floors; N puts every level source on N Hz and turns off emit-on-change |
SOURCES |
empty (every source detected) | comma-separated names | restrict the optional sources to this list; /proc/stat is always read |
TRIGGERS |
softnet-drop,oom,kmsg<=3,reset,irq-err,flash-bad |
conditions, comma-separated | capture trigger conditions |
CAPTURE_MB |
4 |
0–256 | pinned-bytes budget for captures; 0 turns them off |
CAPTURE_PRE_S |
5 |
1–60 | seconds kept before the sample a trigger fires on |
CAPTURE_POST_S |
5 |
1–60 | seconds kept after it |
CAPTURE_POLICY |
first |
first or last |
on a full budget: first refuses the new capture, last evicts the oldest |
TRIGGER_REFRACTORY_S |
10 |
0–3600 | quiet time per condition after it fires |
PROC_ROOT |
/proc |
a path | where /proc is read from; the kernel log is /dev/kmsg only when this is /proc, otherwise dev/kmsg beside the given directory |
SYS_ROOT |
/sys |
a path | where /sys is read from |
Scroll sideways to see every column
The names SOURCES accepts are the optional sources /capabilities reports:
meminfo, loadavg, softnet, softirqs, interrupts, vmstat, psi,
schedstat, self, buddyinfo, yaffs, diskstats, slabinfo, kmsg,
thermal, cpufreq, mtd and perf. The trigger conditions and what each
compares are on triggered capture.
Before it listens, the agent checks the ring against the container’s own
memory.max: RATE_HZ × BUFFER_S × 2 560 B plus CAPTURE_MB must fit, or it
refuses to start and names the three variables and --memory-max. If that
figure is more than half of MEM_LIMIT_MB, it starts and logs a warning with
the limit to raise to. 2 560 B is not itself a measurement: it is the mean
line measured on the RB5009 with every source of that date (2 439 B, 4 cores,
IRQ_TOP_K 8, RouterOS 7.24.2, 2026-09-12) rounded up. A board with more cores
or more interrupt lines writes longer lines, so the check errs open. When the
agent cannot read its memory.max, the refusal check does not run.
What install writes into it
Section titled “What install writes into it”install and upgrade write the envlist <name>-env with these entries, in
this order, and nothing else:
| Key | Written | From | Holds |
|---|---|---|---|
MIKROSCOPE_TAG | always | --name | the ownership marker mikroscope:<name> (managed by mikroscope), written first and removed last; the agent ignores it |
RATE_HZ | always | --rate, default 10, 1–100 | the sampler rate, in Hz |
BUFFER_S | always | --buffer, default 300, 10–3600 | the ring's length, in seconds |
PORT | always | --port, default 9123, 1–65535 | the agent's HTTP port |
ADDR | always | --subnet | the agent's address, the .2 of the /30; the agent binds only there |
MEM_LIMIT_MB | always | --mem-limit-mb, default 40, 8–1024 | the agent's Go soft memory limit, in MiB |
FLOOR_HZ | only when above 0 | --floor-hz, default 0, 0–1000 | one cadence for every level source, in Hz |
CAPTURE_MB | always | --capture-mb, default 4, 0–256 | the triggered-capture budget, in MiB; 0 turns captures off |
TRIGGERS | only when set | --triggers | the trigger conditions; unset, the agent uses its default set |
TOKEN | only when set | --token | the bearer token the agent requires, from --token or MIKROSCOPE_TOKEN, with or without --expose |
Scroll sideways to see every column
In .env.example but not read by the code
Section titled “In .env.example but not read by the code”.env.example is also the development template for the project’s own devices,
so it carries names that no binary reads. Setting them changes nothing:
MIKROSCOPE_ROUTEROS, the RouterOS version of the reference device.OPERATOR_HOST_IP, the operator host for push-sink and probe tests.- The
HEXS_*block (HEXS_ROUTER,HEXS_SSH_PORT,HEXS_SSH_KEY,HEXS_ARCH,HEXS_API_ADDR,HEXS_API_USER,HEXS_API_PASSWORD), kept for a hEX S that has not arrived.