One router you configure by hand. Twenty routers across twenty sites you configure by hand once, and then spend your life logging into them one at a time to change a DNS server. This is how to drive a fleet of RouterOS boxes from one place — the REST API, Ansible, and a scripted push that stays idempotent. The Cisco Ansible post, in RouterOS.
Manual configuration doesn't scale, and it doesn't stay consistent — the whole reason a fleet drifts into twenty subtly-different snowflakes is that every change was typed by hand into whichever boxes someone remembered. Automation fixes both: one source of truth, pushed everywhere, verifiable. RouterOS 7 gives you three levels of it. The REST API is the low-level primitive — HTTP verbs against /rest/… paths, scriptable from anything. Ansible (the community.routeros collection) is the declarative layer — describe the desired state, let it converge. And on-box scripting + scheduler (from the scripting post) handles what's best done locally.
The engineering goal throughout is idempotency: running the same push twice changes nothing the second time. Get that and automation is safe to run on a schedule; miss it and you're duplicating rules across the estate. This mirrors Cisco IOS: Managing a Fleet with Ansible — same discipline, RouterOS transports.
api-ssl/REST to the automation host only01
RouterOS 7 exposes the entire menu tree over REST. Every path you know from the CLI is a URL; GET reads, PUT adds, PATCH edits, DELETE removes. Anything that speaks HTTP can now configure the router.
> /ip service set www-ssl address=10.10.99.0/24 certificate=rest-cert disabled=no # Use a real cert and restrict to the mgmt subnet — this is full control.
# Read: GET the address table as JSON. $ curl -sk -u auto:secret https://10.10.0.1/rest/ip/address | jq . # Change: PATCH the DNS server across the whole tree in one call. $ curl -sk -u auto:secret -X POST https://10.10.0.1/rest/ip/dns/set \ -H 'Content-Type: application/json' -d '{"servers":"1.1.1.1,9.9.9.9"}' # Wrap in a for-loop over a host list and you've changed 20 boxes.
02
A loop over curl works but isn't idempotent and has no state model. Ansible's community.routeros collection gives you inventory, desired-state modules, and a dry-run — the grown-up version of the same idea.
- hosts: mikrotiks gather_facts: no connection: ansible.netcommon.network_cli vars: ansible_network_os: community.routeros.routeros tasks: - name: Ensure NTP client config community.routeros.command: commands: - /system ntp client set enabled=yes servers=time.google.com - name: Read version (for a report) community.routeros.command: commands: [ /system resource print ] register: ver $ ansible-playbook -i inventory playbook.yml --check # dry run first
routeros_api vs routeros_command
The collection has two transports: community.routeros.command (over SSH, runs CLI lines) and community.routeros.api (over the binary API, structured). For pushing config, prefer the API modules where they exist — they understand RouterOS's .id-keyed items and can genuinely converge to a desired state, rather than blindly re-running CLI that may duplicate entries. Use command for reads and for menus the API modules don't cover yet.
03
The failure mode of naive automation is duplication: a push that adds a firewall rule adds it again every run. The fix is find-then-set, so the second run is a no-op.
# Instead of a bare add (which duplicates), check first: > :if ([:len [/ip firewall address-list find list=MGMT address=10.10.99.0/24]] = 0) do={ \ /ip firewall address-list add list=MGMT address=10.10.99.0/24 } # For settings, 'set' is naturally idempotent — prefer it over add/remove: > /ip dns set servers=1.1.1.1,9.9.9.9 # same result every run
A wrong command typed into one router is one broken router; the same command pushed to a fleet is an outage across every site at once — including the management path you were using to reach them. Always dry-run (--check), stage to one canary box, and never push a firewall input-chain change to the whole estate without a scheduled auto-revert or a second access path. The Safe Mode habit doesn't protect API pushes — that safety is yours to build in.
Takeaways
/rest/…, scriptable from anything.community.routeros adds inventory, desired state, and dry-run — the declarative layer over the same operations.set (naturally idempotent) over add. A second run should change nothing.NOCTIS builds automation for MikroTik and Cisco fleets across Crete — one source of truth, safe staged pushes, and configuration that stays consistent across every site instead of drifting apart.
Book a Discovery Call →