RouterOS script
mikroscope plan --rsc writes the whole install as one RouterOS script. Run it on the router, from
a terminal or with /import: no ssh from your computer, and the script checks the router before it
writes anything. To fill in the options in a form instead, use the
Script generator; it writes the same script.
Generate
Section titled “Generate”mikroscope plan --rsc --remote-image jmrplens/mikroscope-agent:1.6.1 --out install.rscIt connects to nothing and prints
install.rsc: 39 lines; review it, then paste it into the router's terminal or /import it.
Without --out the script goes to standard output. It takes the same flags as install: --name,
--veth, --subnet, --iface-list, --addr-list, --rate, --disk and the rest
(CLI).
- Registry pull, with
--remote-image: the router pulls the image itself. - Image tar, without it: the script expects the tar on the router as
mikroscope.tar(<name>.tarwith--name), and its header says so (BEFORE RUNNING: put the agent image tar on the device as mikroscope.tar). Upload it first: Offline install.
With the default options the script is:
# mikroscope 1.6.1: install script for RouterOS 7.24 or later. Container name: mikroscope# Every object it creates carries the comment "mikroscope:mikroscope (managed by mikroscope)", which is how# `mikroscope status` and `uninstall` recognize them later. It lists them in# mikroscope/mikroscope.manifest.txt on the router, which `mikroscope uninstall` reads and deletes last.## The router pulls registry-1.docker.io/jmrplens/mikroscope-agent:1.6.1 itself.# The registry host is part of remote-image= (RouterOS 7.18 and later take it# there), so this script neither reads nor changes the device-wide registry-url.# A registry username set on the device for a registry other than registry-1.docker.io# can make the pull end in `auth error`; `mikroscope doctor` warns about it.## It runs as one block: a check that fails stops it before anything is written,# and a step that fails stops the steps after it.
{:if (!([/system/resource/get version] ~ "^(7[.](2[4-9]|[3-9][0-9]|[1-9][0-9][0-9])|([89]|[1-9][0-9]+)[.])")) do={ :error "mikroscope: needs RouterOS 7.24 or later" }:if ([:len [/system/package/find name="container" disabled=no]] = 0) do={ :error "mikroscope: the container package is not installed" }:local dm [:tostr [/system/device-mode/get container]]; :if ($dm != "yes" && $dm != "true") do={ :error "mikroscope: device-mode container is not enabled" }:if ([:len [/interface/veth/find name="veth-mikroscope"]] > 0 && [:len [/interface/veth/find name="veth-mikroscope" comment="mikroscope:mikroscope (managed by mikroscope)"]] = 0) do={ :error "mikroscope: veth veth-mikroscope exists and is not mikroscope's" }:if ([:len [/container/envs/find list="mikroscope-env"]] > 0 && [:len [/container/envs/find list="mikroscope-env" key="MIKROSCOPE_TAG" value="mikroscope:mikroscope (managed by mikroscope)"]] = 0) do={ :error "mikroscope: envlist mikroscope-env exists and is not mikroscope's" }:if ([:len [/interface/list/find name="LAN"]] = 0) do={ :error "mikroscope: interface list LAN does not exist" }:if ([:len [/file/find name="mikroscope/mikroscope.manifest.txt"]] > 0) do={ :if (!([:typeof [:find [/file/get [find name="mikroscope/mikroscope.manifest.txt"] contents] "\ntag=mikroscope:mikroscope (managed by mikroscope)\n"]] = "num")) do={ :error "mikroscope: mikroscope/mikroscope.manifest.txt exists and is not this install's manifest" } }# install manifest mikroscope/mikroscope.manifest.txt:local m "mikroscope-manifest=1\nname=mikroscope\ntag=mikroscope:mikroscope (managed by mikroscope)\ndisk=\nveth=veth-mikroscope\nsubnet=172.30.10.0/30\nport=9123\niface-list=LAN\naddr-list=LANs\nexpose=\ncontainer-name=\nremote-image=registry-1.docker.io/jmrplens/mikroscope-agent:1.6.1\ntoken=no\ndir=mikroscope\nfile=mikroscope/mikroscope.manifest.txt\nobject=/interface/veth name=veth-mikroscope\nobject=/ip/address interface=veth-mikroscope\nobject=/interface/list/member interface=veth-mikroscope list=LAN\nobject=/ip/firewall/address-list list=LANs address=172.30.10.0/30\nobject=/container/envs list=mikroscope-env\nobject=/container interface=veth-mikroscope\ndir=mikroscope/mikroscope\n"; :if ([:len [/file/find name="mikroscope/mikroscope.manifest.txt"]] > 0) do={ /file/set [find name="mikroscope/mikroscope.manifest.txt"] contents=$m } else={ /file/add name="mikroscope/mikroscope.manifest.txt" contents=$m }# veth interface veth-mikroscope/interface/veth/add name="veth-mikroscope" address=172.30.10.2/30 gateway=172.30.10.1 comment="mikroscope:mikroscope (managed by mikroscope)"# router address 172.30.10.1/ip/address/add address=172.30.10.1/30 interface="veth-mikroscope" comment="mikroscope:mikroscope (managed by mikroscope)"# interface-list membership LAN/interface/list/member/add list="LAN" interface="veth-mikroscope" comment="mikroscope:mikroscope (managed by mikroscope)"# address-list membership LANs/ip/firewall/address-list/add list="LANs" address=172.30.10.0/30 comment="mikroscope:mikroscope (managed by mikroscope)"# container mikroscope:if ([:len [/container/envs/find list="mikroscope-env" key="MIKROSCOPE_TAG" value="mikroscope:mikroscope (managed by mikroscope)"]] > 0) do={ /container/envs/remove [find list="mikroscope-env"] }; /container/envs/add list="mikroscope-env" key=MIKROSCOPE_TAG value="mikroscope:mikroscope (managed by mikroscope)"; /container/envs/add list="mikroscope-env" key=RATE_HZ value="10"; /container/envs/add list="mikroscope-env" key=BUFFER_S value="60"; /container/envs/add list="mikroscope-env" key=PORT value="9123"; /container/envs/add list="mikroscope-env" key=ADDR value="172.30.10.2"; /container/envs/add list="mikroscope-env" key=MEM_LIMIT_MB value="16"; /container/envs/add list="mikroscope-env" key=CAPTURE_MB value="4"; /container/add remote-image="registry-1.docker.io/jmrplens/mikroscope-agent:1.6.1" interface="veth-mikroscope" root-dir=mikroscope/mikroscope envlist="mikroscope-env" logging=yes start-on-boot=yes restart-policy=on-failure restart-max-count=5 restart-interval=10s memory-max=64M privileged=yes ignore-remote-image-change=yes comment="mikroscope:mikroscope (managed by mikroscope)"; /container/start [find comment="mikroscope:mikroscope (managed by mikroscope)"]:local k 0; :while ([:len [/container/find comment="mikroscope:mikroscope (managed by mikroscope)" running]] = 0 && $k < 120) do={ :delay 1s; :set k ($k + 1) }:if ([:len [/container/find comment="mikroscope:mikroscope (managed by mikroscope)" running]] > 0) do={ :put "mikroscope: agent running, http://172.30.10.2:9123/healthz" } else={ :put "mikroscope: not running yet; see /log/print where topics~\"container\"" }}# When it is done: /container/print where comment="mikroscope:mikroscope (managed by mikroscope)"# The agent answers on http://172.30.10.2:9123/healthz from the router's LAN.It runs as one { … } block, in this order:
- Guards. It stops with
:error "mikroscope: …", before anything is written, when the RouterOS release is before 7.24, thecontainerpackage is missing, device mode is off, a veth, an envlist or a--container-namecontainer of that name belongs to something else, the interface list does not exist, the--diskis missing, the tar is not uploaded, or a file at the manifest’s path is not this install’s manifest. - The install manifest, then each object, with the same tag
installwrites. A step that fails stops the steps after it. - A wait of up to 120 s for the container to run, then one line:
mikroscope: agent running, http://172.30.10.2:9123/orhealthz mikroscope: not running yet; see /log/print where topics~"container".
Run on the router
Section titled “Run on the router”- Open a terminal on the router: WebFig › Terminal, Winbox › New Terminal, or ssh.
- Wait for the
] >prompt. - Paste the whole file.
-
Upload
install.rscin Files (WebFig or Winbox), or withscp. -
Run:
/import file-name=install.rsc -
Delete the file:
/file/remove install.rsc.
A successful /import prints:
mikroscope: agent running, http://172.30.10.2:9123/healthzScript file loaded and executed successfullyA guard that fails names the problem and writes nothing, for instance with the tar route and no tar uploaded:
Script Error: mikroscope: upload mikroscope.tar first (:error; line 20) (:import; line 1)Verify
Section titled “Verify”On the router:
/container/print where comment="mikroscope:mikroscope (managed by mikroscope)":put ([/tool/fetch url="http://172.30.10.2:9123/healthz" output=user as-value]->"data")The first shows the container with the R (running) flag; the second prints the agent’s
/healthz answer, {"ok":true,…}. From a computer with the CLI, mikroscope status --router …
recognises the install and probes the agent.
Install manifest
Section titled “Install manifest”The script writes the install manifest first, mikroscope/ on the install’s
disk. Read it on the router:
:put [/file/get [find name="mikroscope/mikroscope.manifest.txt"] contents]mikroscope-manifest=1name=mikroscopetag=mikroscope:mikroscope (managed by mikroscope)disk=veth=veth-mikroscopesubnet=172.30.10.0/30port=9123iface-list=LANaddr-list=LANsexpose=container-name=remote-image=registry-1.docker.io/jmrplens/mikroscope-agent:1.6.1token=nodir=mikroscopefile=mikroscope/mikroscope.manifest.txtobject=/interface/veth name=veth-mikroscopeobject=/ip/address interface=veth-mikroscopeobject=/interface/list/member interface=veth-mikroscope list=LANobject=/ip/firewall/address-list list=LANs address=172.30.10.0/30object=/container/envs list=mikroscope-envobject=/container interface=veth-mikroscopedir=mikroscope/mikroscopeThe first lines are the options the install was made with, under the CLI’s flag names; token=
says only yes or no, never the value. Each object=, file= and dir= line is something the
install created. mikroscope uninstall reads the manifest, removes everything it lists and the
manifest last. The tar route adds file=mikroscope.tar.
Limitations
Section titled “Limitations”- It cannot upload anything. Pair it with
--remote-image, or upload the tar before you run it. - With a token, the file is a credential. The envlist line carries the token in clear, because
the router needs it in clear. The CLI writes the file
0600; delete it from the router after/import. - It runs no
doctor. The guards cover the release, the package, device mode, name collisions, the interface list, the disk, the tar and the manifest path. Free memory and storage, a route that overlaps the /30 and a firewall rule that drops the agent’s replies are not checked: runmikroscope doctorfrom a computer that can reach the router, or check the Requirements by hand.
What has been run, and what has not, is on Tested on.
Remove
Section titled “Remove”From a computer with the CLI:
mikroscope uninstall --router admin@192.168.88.1 --yesIt reads the manifest, so it needs no other flag. Without the CLI, run the removal commands on Manual install: terminal. Upgrade and uninstall has what removal never touches.