Files
2GT-RichandClaude Opus 5 98a72e1f7a docs: versioned documentation site, and the four pages that were missing (v0.23.28-beta)
Closes #112.

Source stays `docs/*.md`, rendered by MkDocs-Material and published to GitHub
Pages by Actions. Same repository on purpose: documentation drifts, and
co-location is the only thing that reliably prevents it — the pull request that
changes behaviour changes the description, and review sees both. A separate repo
would double the ceremony and guarantee divergence.

The markdown remains readable when browsing the repository, so the site renders
those files rather than replacing them.

**Versioned from the start**, using mike. Images are published to GHCR and this
project ships betas most days, so readers are routinely running something other
than the newest build; a single "latest" would confidently describe a release
they do not have. Versions follow the product rather than the docs, so the site
and the running image carry the same number.

**Content came first, and it had to.** The docs were eleven days and sixteen
releases stale — SSH keys, bulk commands, the data-cap SMS, poller health and the
timezone setting appeared in exactly zero files between them. Publishing that
would have given documentation missing five of the most consequential features a
polished, authoritative home, and a well-presented wrong answer is worse than an
obviously rough one. Four pages now cover them:

  - cellular.md — signal grading, carrier aggregation, the uplink anchor,
    observed bands, and the data-cap SMS including why it fires early and how to
    calibrate the margin
  - ssh-keys.md — leading with what installing a key costs, because RouterOS
    disables password SSH for that user and the database becomes load-bearing
  - commands.md — why waves exist, and why reading output matters when RouterOS
    reports failure in text rather than an exit code
  - scaling.md — headroom, why it is insufficient on its own, and every tunable

Pull requests build the site with `--strict`, which turns warnings into errors.
That is the point of running it there at all, and it earned itself immediately:
the first build failed on two links to the project README, which sits outside the
docs tree. They are absolute now, so they resolve both in the rendered site and
when reading the markdown on GitHub.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-02 18:42:40 -07:00

2.6 KiB

Bulk commands

← Documentation index

Run one RouterOS console command across many devices, in waves, stopping at the first failure.

Commands run over SSH, because console syntax — :put, :foreach, /interface print — is not reachable through the binary API, which has its own command tree.

Why waves exist

A shell loop already runs a command on many hosts, costs nothing, and prints errors as they happen. What it cannot do is stop.

Devices run together within a wave; waves run strictly in sequence. With halt-on-failure enabled, a mistake reaches one wave rather than the whole fleet. That is the entire reason to do this here rather than in a terminal — without it, this would be a worse shell loop.

Start with a wave of one. Widen it once the command has proved itself.

Detecting failure

RouterOS reports most errors in the output text rather than through an exit code, so a rejected command and a successful one are indistinguishable unless the output is read.

Output is scanned for unambiguous markers — syntax error, bad command name, no such item, failure: and similar. The matching is deliberately conservative: mistaking ordinary output for failure would halt a run that was working, which is worse than the error it guards against.

Change Guard

Each device is wrapped by Change Guard by default, so one that stops answering after the command restores itself.

It is one click to turn off. You may know exactly why you are running something that will drop a device, and a tool that refuses to cut is not a sharp tool.

The one combination that asks for explicit acknowledgement is a command that can sever management with the guard disabled — the only case where nothing catches a mistake.

Preview

Before running, the preview shows:

  • which devices are selected and which wave each falls into
  • whether the command matches patterns that can cut management access, and why
  • devices with no SSH credential, which would otherwise produce a wave of identical authentication failures

It warns; it never blocks.

Output

Captured per device and kept with the run. Some commands exist purely for their output — :put [:resolve google.com] across a fleet is a legitimate use — and "it failed" without the device's own words is not actionable.

Stopping a run

Cancelling prevents the next wave. Devices already executing finish, because that is the only point at which stopping is safe.

Requirements

Every targeted device needs an SSH credential: either a password, or a verified SSH key. On a fleet of any size, keys are the practical answer.