MikroTik hardware has a reputation for doing a great deal for very little money, and that is precisely why it spreads. A network that started with one RB4011 at the edge quietly grows into forty hAP units at branch offices, a pair of CCR routers handling BGP, and a few CHR instances in the cloud. Each device carries years of accumulated firewall rules, queues, and routing filters, yet in many environments the only backup is a binary file someone saved to a laptop in 2023.
Oxidized offers a better pattern. It connects to every RouterOS device over SSH, runs a text export, cleans out the lines that change on every run, and commits the result to Git. Consequently, you gain a searchable history of every configuration change across the entire MikroTik fleet, without installing agents or buying licenses. This guide explains the full implementation: how RouterOS exports differ from binary backups, how to build a least-privilege SSH account, how to deploy Oxidized in Docker, how to tune the routeros model for clean diffs, how to trigger backups from syslog, and how to restore a device when something goes wrong.
What Is Oxidized for MikroTik RouterOS?
Oxidized for MikroTik is an automated backup workflow in which the Oxidized application connects to RouterOS devices over SSH, runs the configuration export defined in its routeros model, removes volatile header lines, and commits each changed configuration to a Git repository. It provides scheduled text backups, version history, diffs, and a REST API for any MikroTik router, switch, or CHR instance that accepts SSH logins.
Key Takeaways
- Oxidized includes a native routeros model, so MikroTik support works out of the box.
- A text export (.rsc) is ideal for version control and diffs, while a binary backup (.backup) is better for full-device disaster recovery. Mature teams keep both.
- A dedicated user in a read-only group, restricted by source address, keeps the backup account low-risk.
- RouterOS 6 and RouterOS 7 export differently, so confirm behavior on both if your fleet is mixed.
- Model tuning, mainly header removal and secret handling, determines whether your Git history is useful or noisy.
- Syslog triggers let you capture a change within seconds of it being made.
Why MikroTik Backups Need More Than a Saved File
RouterOS gives administrators several backup mechanisms, and each answers a different question. Understanding the differences prevents the most common mistake: believing a single binary backup file covers every recovery scenario.
Export Versus Binary Backup
The /export command produces a human-readable script of CLI commands, normally saved with an .rsc extension. In contrast, /system backup save produces a binary snapshot that includes items such as users, certificates, and other data that a plain export may omit or hide.
| Characteristic | Text Export (.rsc) | Binary Backup (.backup) |
|---|---|---|
| Format | Readable CLI script | Proprietary binary |
| Diff-friendly | Yes | No |
| Restore target | Same or different hardware, with edits | Best on the same device or identical model |
| Contains secrets | Hidden by default on RouterOS 7 unless requested | Included, optionally encrypted |
| Version portability | Generally good across versions | Tied closely to the RouterOS version |
| Best use | Change tracking, review, partial restore | Full disaster recovery |
Because Oxidized relies on text export, it excels at change tracking, auditing, and partial restores. Nevertheless, it does not replace binary backups, and a later section shows how to run both side by side.
Where Manual and Scripted Backups Fall Short
RouterOS can run scheduled scripts that save a backup and upload it with /tool fetch. That approach works, yet it requires the script to be deployed and maintained on every device, the uploaded files pile up without a diff view, and failures are silent. Moreover, a file named by date tells you that something exists, but it does not tell you what changed between Tuesday and Wednesday.
| Approach | Strengths | Limitations |
|---|---|---|
| Manual WinBox or CLI export | Simple, no setup | Depends on human memory, no history |
| On-device scheduler and fetch script | Automated per device | Script sprawl, no diffing, silent failures |
| The Dude or other monitoring tool backup | Central visibility | Limited versioning and review workflow |
| Ansible with community.routeros | Flexible, scriptable | You build scheduling, storage, and diffs |
| Oxidized with Git | Central, versioned, multi-vendor, API-driven | Requires a server and operational ownership |
How Oxidized Works with RouterOS
Oxidized is a Ruby application organized around sources, inputs, models, and outputs. For MikroTik, each layer has a clear role.
Architecture Components
| Layer | Component | Function in a MikroTik Deployment |
|---|---|---|
| Source | CSV, SQL, HTTP, or NetBox | Lists devices, addresses, and model names |
| Input | SSH | Opens the RouterOS CLI session |
| Model | routeros | Runs the export and cleans the output |
| Output | Git or gitcrypt | Stores each changed export as a commit |
| Hooks | githubrepo, exec, slackdiff | Reacts to stored changes |
| Interface | REST API and Oxidized Web | Shows node status and allows manual triggers |
The Backup Lifecycle
Every polling cycle follows the same eight steps, which makes diagnosing a failure much easier once you know where to look.
- Oxidized loads the node list from the configured source.
- A worker thread opens an SSH session to the RouterOS device.
- The routeros model handles the console quirks and logs in.
- The model runs the export and a few informational commands.
- Header lines carrying timestamps are stripped, and secrets are optionally removed.
- Oxidized compares the cleaned text with the previously stored version.
- When the content differs, the output driver writes a Git commit and any hook fires.
- The node is rescheduled for the next interval.
What the routeros Model Does
RouterOS presents an interactive console with color codes and terminal width detection, which can corrupt captured output. The model accounts for this behavior so that the text arriving in Git is clean. It also removes the first comment line of the export, which includes the date and RouterOS version, because that line changes on every run and would otherwise force a commit every hour. Because model behavior is maintained by the community, keeping the Oxidized image current matters, especially after major RouterOS releases.
Prerequisites and Planning
A brief planning pass saves time later. The table below lists what to prepare.
| Requirement | Recommendation | Why It Matters |
|---|---|---|
| Backup server | Linux VM, 2 vCPU, 2 GB RAM for small and medium fleets | Oxidized is light, Git history grows steadily |
| Container runtime | Docker Engine with Compose | Simple upgrades and rollbacks |
| RouterOS access | SSH reachable on the management address | The model uses the CLI over SSH |
| Service account | Dedicated user in a read-only group | Limits damage if the credential leaks |
| Source restriction | Address filter on the user and the SSH service | Makes a stolen credential far less useful |
| Time sync | NTP on the server and all routers | Correct commit and log timestamps |
| Remote Git | Private repository on GitLab, GitHub, or Gitea | Protects history if the server is lost |
Choose a Management Path
MikroTik devices often sit behind NAT, on customer premises, or at the end of a VPN. Decide early how Oxidized will reach them: directly over a management VLAN, through a WireGuard or IPsec tunnel, or via a jump network. In practice, a dedicated management tunnel with predictable addressing is the most reliable approach for distributed branch estates, because the node IP in the inventory never changes even when the WAN address does.
RouterOS Versions in Your Fleet
Inventory your versions before you begin. RouterOS 7 changed export defaults, the SSH implementation, and several menu paths compared with RouterOS 6. As a result, one Oxidized configuration can behave slightly differently across a mixed fleet. Start with a small pilot group containing both major versions, review the first diffs, and only then roll out widely.
Preparing RouterOS for Oxidized Backups
The goal is an account that can log in over SSH, run an export, and nothing more. Building this properly takes only a few commands per device, and it is easy to automate with a script or configuration management tool.
Create a Read-Only Group and User
Begin by defining a group with the minimum policies required. SSH access and read access are the starting point. Because policy requirements can vary by RouterOS version and by what you want exported, start narrow and widen only if the export is incomplete.
/user group add name=oxidized-ro policy=ssh,read comment="Oxidized read-only backup" /user add name=oxidized group=oxidized-ro address=10.10.50.25/32 \ password="ChangeThisLongRandomPassword" comment="Oxidized service account" The address parameter on the user restricts logins to the Oxidized server, so a leaked password is useless from anywhere else. If you later decide to export secrets, you will need to add the sensitive policy to the group, which is a deliberate decision that deserves review rather than a default.
Verify the Account Manually
Before touching Oxidized, log in from the backup server exactly as the tool will.
ssh oxidized@10.10.1.1 "/export" If the output is a readable script, the account works. On the other hand, if you see a permissions error or a truncated export, adjust the group policies and retry before moving on.
Use SSH Key Authentication
Passwords are acceptable for a pilot, but keys are the better long-term choice. Generate a dedicated key pair on the Oxidized server, copy the public key to the router, and import it for the service user.
ssh-keygen -t rsa -b 4096 -f /srv/oxidized/ssh/id_rsa -C "oxidized@backup01" -N "" scp /srv/oxidized/ssh/id_rsa.pub admin@10.10.1.1:oxidized.pub /user ssh-keys import public-key-file=oxidized.pub user=oxidized RSA keys are accepted on both RouterOS 6 and 7, which makes them the safest choice for mixed fleets. Newer releases also accept Ed25519 keys, so you can adopt them once every device in the pool supports them. Afterward, you may disable password logins for the SSH service on devices where key authentication is confirmed.
Harden the SSH Service
While you are on the device, tighten the SSH service itself. These settings reduce exposure without affecting Oxidized.
/ip ssh set strong-crypto=yes forwarding-enabled=no /ip service set ssh address=10.10.50.0/24 /ip service disable telnet,ftp,www,api,api-ssl Strong crypto restricts the ciphers and key exchange algorithms RouterOS will accept. It is a good practice, though it can break very old SSH clients. Because Oxidized relies on a Ruby SSH library, an outdated image combined with strong crypto is a classic cause of key exchange errors, so keep the container image up to date.
Allow SSH Through the Input Chain
Most MikroTik firewalls drop unsolicited input traffic. Add an accept rule scoped to the Oxidized server before the drop rule.
/ip firewall filter add chain=input protocol=tcp dst-port=22 \ src-address=10.10.50.25 action=accept comment="Oxidized SSH" place-before=0 Placement matters here. If your input chain ends with a drop rule, an accept rule added after it never matches. Therefore, verify the rule order with /ip firewall filter print after adding it.
Installing Oxidized with Docker
Docker keeps the Ruby dependencies, native libraries, and upgrades out of your way. One persistent directory holds everything that matters.
Directory Layout
sudo mkdir -p /srv/oxidized/ssh sudo chown -R 30000:30000 /srv/oxidized The official image runs as an unprivileged user, so ownership mismatches are a frequent cause of a container that exits immediately. Check the image documentation for the UID used by your version, and ensure the private key file is readable only by that user.
The Core Configuration File
Save this as /srv/oxidized/config. It sets polling behavior, SSH input with key authentication, Git output, a CSV source, and a REST interface bound to localhost.
username: oxidized password: ChangeThisLongRandomPassword model: routeros interval: 3600 use_syslog: false debug: false threads: 20 timeout: 30 retries: 3 rest: 127.0.0.1:8888 vars: ssh_keys: /home/oxidized/.config/oxidized/ssh/id_rsa input: default: ssh ssh: secure: false output: default: git git: user: Oxidized email: oxidized@example.com repo: /home/oxidized/.config/oxidized/mikrotik.git source: default: csv csv: file: /home/oxidized/.config/oxidized/router.db delimiter: !ruby/regexp /:/ map: name: 0 ip: 1 model: 2 group: 3 A few choices deserve explanation. First, an hourly interval is a sensible baseline for most estates. Second, secure: false disables SSH host key verification, which is acceptable in a lab but should be switched on in production once the known hosts file is populated. Third, binding the REST service to localhost avoids exposing an unauthenticated API to the network.
The Device Inventory
Create /srv/oxidized/router.db with one device per line, following the field map above.
rtr-edge-01:10.10.1.1:routeros:core rtr-branch-12:10.20.12.1:routeros:branch sw-crs-03:10.10.2.3:routeros:switching The model name is routeros for RouterOS routers and switches alike, including CRS devices running RouterOS and CHR virtual routers. Keep node names consistent with the device identity set under /system identity, since that consistency pays off when you add syslog triggers.
Start the Container
docker run -d --name oxidized \ --restart unless-stopped \ -p 127.0.0.1:8888:8888 \ -v /srv/oxidized:/home/oxidized/.config/oxidized \ oxidized/oxidized:latest oxidized Follow the first run with docker logs -f oxidized. After a short delay you should see each node queued and then stored.
Confirm the First Backups
curl -s http://127.0.0.1:8888/nodes.json git -C /srv/oxidized/mikrotik.git log --oneline The first command lists node status, and the second shows the commit history. If a node fails, the troubleshooting section later in this guide tabulates the usual causes and fixes.
Git Versioning for RouterOS Configurations
Git transforms a pile of exports into a change history. Every time a device’s configuration differs from the last stored copy, Oxidized writes a commit.
Why Git Suits RouterOS Exports
A RouterOS export is a sequence of CLI commands grouped by menu path, such as /ip firewall filter and /routing ospf interface-template. That structure is naturally line-oriented, so a single added firewall rule becomes a single added line in the diff. Furthermore, Git gives you integrity guarantees, compact storage, branching for experiments, and a toolset that auditors and engineers already recognize.
Output Options
| Output | Use Case | Consideration |
|---|---|---|
| git | Standard versioned backups | Repository is plain text on the server |
| gitcrypt | Encrypted repository | Requires git-crypt setup and key handling |
| file | Flat files only | No history, so poor for change tracking |
| http | Forward to another system | Needs a receiving service |
Choose git at minimum. Consider gitcrypt when the repository will be mirrored to a shared platform or when exports include sensitive values.
Reading the History
Because the repository is bare, clone it for comfortable browsing.
git clone /srv/oxidized/mikrotik.git ~/mikrotik-configs cd ~/mikrotik-configs # Last five changes to one router git log -5 --stat -- rtr-edge-01 # Exactly what changed in the latest commit git show HEAD -- rtr-edge-01 # Compare two points in time git diff HEAD~20 HEAD -- rtr-edge-01 When devices are organized into groups, files live under the group directory, so adjust the paths. In addition, commit messages record the node and group, which makes git log --grep a fast way to find every change to one device.
Push to a Remote Repository
A repository that lives only on the backup server is a single point of failure. Add a hook that pushes after each stored change.
hooks: push_to_remote: type: githubrepo events: [post_store] remote_repo: git@git.example.com:netops/mikrotik-configs.git publickey: /home/oxidized/.config/oxidized/ssh/deploy.pub privatekey: /home/oxidized/.config/oxidized/ssh/deploy Despite its name, the hook works with any SSH-accessible Git server, including GitLab and Gitea. Use a deploy key limited to this one repository, and protect the main branch so history cannot be rewritten.
Tuning the routeros Model for Clean Diffs
A Git history is only as useful as its signal-to-noise ratio. If every hourly run produces a commit, reviewers stop looking, and the one change that matters gets buried. Fortunately, most RouterOS noise comes from a short list of sources.
Common Sources of Noise
| Noise Source | What Happens | Remedy |
|---|---|---|
| Export header comment | Date, time, and version change on every export | Handled by the model, so keep Oxidized current |
| Secrets and keys | Values may be hidden, shown, or re-generated depending on version and policy | Decide on a single policy and apply it fleet-wide |
| Scheduler and script timestamps | Run-related values shift between exports | Review the first diffs and filter or accept |
| Version differences in a mixed fleet | RouterOS 6 and 7 print the same setting differently | Group devices by major version |
| Auto-generated items | Dynamic entries appear after upgrades | Compare consecutive diffs before and after a maintenance window |
Because the exact behavior depends on your RouterOS versions, treat the first week as a calibration period. Review every unexpected commit, trace it to a cause, and then decide whether to filter it, group around it, or accept it as legitimate.
Export Modes Across RouterOS Versions
RouterOS exports differ in what they include. Since RouterOS 6.43, /export is compact by default, meaning it prints only settings that differ from the defaults. A verbose export prints everything, which produces larger files and more churn after upgrades. On RouterOS 7, sensitive values are hidden unless the export explicitly requests them and the account holds the sensitive policy.
| Mode | What You Get | Typical Use |
|---|---|---|
| Compact | Only non-default settings | Best for diffs and everyday change tracking |
| Verbose | All settings including defaults | Forensics and deep comparison, with more noise |
| Hide sensitive | Secrets omitted | Repositories that will be shared or mirrored |
| Show sensitive | Secrets included | Complete restores, with strict repository protection |
For most teams, compact with sensitive values hidden is the right default. It yields small, readable diffs and a repository that carries less risk if it is ever exposed.
The Secrets Decision
This choice has operational consequences. An export without secrets cannot restore Wi-Fi passphrases, PPP secrets, IPsec pre-shared keys, or user passwords, so those must be re-entered after a restore. Conversely, an export with secrets is a complete record that needs the same protection as a password vault. Many teams resolve the tension by exporting without secrets into Git and keeping encrypted binary backups for full recovery, which the next sections describe.
Model-Level Overrides
When part of your fleet needs different settings, Oxidized lets you override values per model or per group in the configuration file.
models: routeros: username: oxidized vars: remove_secret: true groups: branch: username: oxidized-br password: BranchLongRandomPassword core: username: oxidized password: CoreLongRandomPassword Variable names evolve between Oxidized releases, so confirm each one against the routeros model documentation for your installed version before relying on it. Afterward, trigger a manual run twice in a row. If the second run creates a commit, noise remains and the cause is worth investigating.
Validate the Tuning
- Force a fresh backup of one pilot device through the API.
- Wait for the commit to appear in Git.
- Force a second backup immediately.
- Confirm that no new commit was created.
- Make a harmless change on the router, such as editing a comment, and confirm that exactly one commit appears.
curl -s http://127.0.0.1:8888/node/next/rtr-edge-01 sleep 30 curl -s http://127.0.0.1:8888/node/next/rtr-edge-01 git -C /srv/oxidized/mikrotik.git log --oneline -3 This sequence proves both halves of the requirement: stable output when nothing changes, and a visible commit when something does.
Real-Time Backups with Syslog Triggers
Hourly polling leaves a gap between a change and its capture. If your change process demands tighter evidence, let the router announce its own edits.
How It Works
RouterOS writes a system log entry whenever a configuration item is added, changed, moved, or removed, and it records the administrator or tool responsible. Forwarding those entries to a syslog receiver lets a small script call the Oxidized API for that router immediately.
- An administrator edits the configuration through WinBox, WebFig, SSH, or an API client.
- RouterOS logs the change under the system and info topics.
- The log entry is sent to the Oxidized server over syslog.
- rsyslog passes the source address and message to a trigger script.
- The script recognizes a configuration change and calls the Oxidized API.
- Oxidized fetches the export and commits the diff.
Configure Remote Logging on RouterOS
/system logging action add name=oxidized-syslog target=remote \ remote=10.10.50.25 remote-port=514 /system logging add topics=system,info action=oxidized-syslog These two commands create a remote logging action and bind the relevant topic to it. Make sure the router’s source address for syslog matches the management address you used in the Oxidized inventory, because the trigger identifies devices by IP.
Configure rsyslog and the Trigger Script
Oxidized accepts either a node name or an IP address on its next-node endpoint, so the script can use the sender address directly. That approach avoids parsing hostnames out of log lines.
template(name="ipmsg" type="string" string="%fromhost-ip% %msg%\n") module(load="imudp") input(type="imudp" port="514" ruleset="mt") ruleset(name="mt") { action(type="omprog" binary="/usr/local/bin/oxidized-trigger.sh" template="ipmsg") } The script reads each line, splits off the IP, and checks whether the message describes a configuration change.
#!/bin/bash while read -r ip msg; do case "$msg" in *"added by"*|*"changed by"*|*"removed by"*|*"moved by"*) curl -s "http://127.0.0.1:8888/node/next/${ip}" > /dev/null ;; esac done Because the exact log wording can vary slightly between versions, capture a few real messages from your own devices and adjust the patterns accordingly. In addition, limit UDP 514 to router addresses with a host firewall rule. A busy administrative session can also emit many lines in seconds, so a small debounce, for example processing each IP at most once every thirty seconds, keeps the queue tidy.
Using the Oxidized REST API and Web Interface
The built-in HTTP service supports dashboards, scripts, and manual operations.
| Endpoint | Purpose |
|---|---|
| /nodes | Lists nodes with status and last run time |
| /nodes.json | Same data in JSON for automation |
| /node/fetch/NAME | Returns the latest stored configuration |
| /node/next/NAME | Queues an immediate backup for a node |
| /node/version?node_full=GROUP/NAME | Lists stored versions of a node |
| /reload | Reloads the inventory from the source |
In practice, the JSON node list is an excellent monitoring feed. A script or Prometheus exporter can raise an alert whenever a node stays in a failed state for more than two intervals, which catches an expired credential, a changed address filter, or a device that has quietly gone offline.
Securing the Backup Pipeline
A repository of router configurations reveals your topology, firewall logic, VPN peers, and possibly secrets, so protect it accordingly.
| Control | Recommendation |
|---|---|
| Service account | Read-only group, address restriction, strong credential or key |
| SSH service | Strong crypto enabled, forwarding disabled, address-limited |
| Unused services | Disable Telnet, FTP, plain API, and WebFig where possible |
| Host key checking | Enable in Oxidized once known hosts are populated |
| API exposure | Localhost binding, with an authenticated TLS reverse proxy if remote access is needed |
| Secrets in Git | Hide them in exports or encrypt the repository |
| Remote repository | Private, per-repository deploy key, protected main branch |
| Server hardening | Patch regularly, restrict SSH, use disk encryption |
| Monitoring | Alert on failed nodes and unexpected commits |
MikroTik’s own hardening guidance emphasizes restricting management services by source address, and this pipeline follows the same principle. Moreover, frameworks such as the CIS Controls and NIST SP 800-53 expect network devices to have controlled, reviewable configurations, which versioned backups directly support.
Combining Oxidized with Binary Backups
Because text exports omit or hide certain data, the strongest strategy pairs Oxidized with a periodic encrypted binary backup. The binary file handles full-device recovery, while Git handles history and review.
Create a Scheduled Binary Backup
This script saves an encrypted backup and uploads it to a file server over SFTP. Adapt the server address, credentials, and path to your environment, and confirm the encryption option your RouterOS version supports.
/system script add name=nightly-binary-backup policy=ftp,read,write,policy,test source={ :local id [/system identity get name] /system backup save name=nightly encryption=aes-sha256 password="BackupFilePassphrase" /tool fetch url=("sftp://10.10.50.25/backups/" . $id . ".backup") \ src-path=nightly.backup user=backupuser password="SftpPassword" upload=yes } /system scheduler add name=nightly-binary-backup start-time=02:15:00 interval=1d \ on-event=nightly-binary-backup After the first run, confirm that the file arrives and that you can decrypt it on a test device. Importantly, store the backup passphrase separately from the files, ideally in your password manager, because a backup you cannot decrypt is worthless.
Restoring a MikroTik Device from an Oxidized Backup
Restoration is where preparation pays off. Rehearse it on a spare device before you need it.
Restore Workflow
- Identify the target commit with
git logand compare it with the current state usinggit diff. - Extract the file with
git show COMMIT:PATHand save it with an .rsc extension. - Review the script for hardware-specific items, such as interface names, and for secrets that were hidden in the export.
- Upload the file to the router with SCP or SFTP.
- For a full rebuild, reset the device and run the script. For a partial rollback, import only the relevant section.
- Verify connectivity, routing, firewall behavior, and management access.
git show 3f9a2c1:core/rtr-edge-01 > rtr-edge-01.rsc scp rtr-edge-01.rsc admin@192.168.88.1: On the router, a complete rebuild uses a reset that runs the script afterward, whereas a targeted rollback uses a plain import.
# Full rebuild from the exported script /system reset-configuration no-defaults=yes skip-backup=yes run-after-reset=rtr-edge-01.rsc # Partial rollback without a reset /import file-name=rtr-edge-01.rsc verbose=yes Be careful with the import approach, because replaying a full export over a running configuration can create duplicates. For that reason, many engineers extract only the affected menu section, such as the firewall filter block, and apply it during a maintenance window.
Restore Pitfalls
Several problems recur. First, hidden secrets must be re-entered by hand. Second, moving a configuration to different hardware can break references to interface names, bridge ports, or wireless packages. Third, a configuration from a much older RouterOS version may not import cleanly into a newer one. Consequently, record the RouterOS version and hardware model next to each backup, and keep a small restore runbook in the repository.
Change Auditing and Compliance Evidence
Git history, together with RouterOS logs that identify the user behind a change, builds a reliable audit trail.
| Framework | Relevant Area | How Oxidized Helps |
|---|---|---|
| NIST SP 800-53 | CM-2, CM-3, CM-6 | Baselines, tracked changes, documented settings |
| CIS Controls | Secure configuration of network devices | Versioned, reviewable configurations |
| ISO 27001:2022 | Configuration management | Retrievable configuration history |
| PCI DSS 4.0 | Network security control reviews | Diffs that simplify periodic review |
| SOC 2 | Change management criteria | Timestamped change records |
To put this to work, schedule a daily digest of commits to the network team and require that each change map to a ticket. As a result, undocumented edits surface within a day instead of at the next audit.
Scaling Oxidized Across a Large MikroTik Fleet
Fleet growth changes the operational questions from how to back up a router to how to keep two hundred of them consistent.
Groups for Roles and Credentials
Use groups to separate cores, branches, and customer sites, and to apply different credentials or variables. For MSPs, this prevents one customer’s credential from touching another’s equipment. Git also stores each group in its own directory, which keeps repositories tidy.
A Source of Truth for the Inventory
A CSV file is fine for a pilot, yet it drifts from reality as devices are added and retired. Switching to NetBox or an HTTP source means the inventory follows your documentation, and decommissioned routers disappear from the rotation automatically.
Threads and Timeouts
Begin with 20 threads and a 30-second timeout. Distributed MikroTik estates often include slow LTE or satellite links, so raise the timeout before raising the retry count. Meanwhile, increase threads gradually while watching CPU and queue length rather than assuming more is faster.
Troubleshooting MikroTik Backups in Oxidized
Start with the container log, then reproduce the failing connection manually from the same host with the same account.
| Symptom | Likely Cause | Fix |
|---|---|---|
| Node shows no_connection | Input chain drop, address filter, or routing issue | Test with ssh from the Oxidized host, then adjust firewall and service address |
| Authentication failed | Wrong password, key not imported, or user address restriction | Verify the login manually and review the user address setting |
| Key exchange or cipher error | Strong crypto on the router with an outdated SSH library | Update the Oxidized image |
| Garbled output with escape codes | Console color or terminal detection | Update Oxidized and confirm the model is routeros |
| Truncated or empty export | Missing policy on the group | Add the needed policy deliberately and retest |
| Commit on every run | Volatile lines in the export | Update Oxidized and review the diff |
| Timeout on a remote site | Slow or lossy link | Increase timeout and reduce threads |
| Host key mismatch | Device reinstalled or replaced | Remove the old entry from known hosts after verifying the change |
Debugging One Device
When a single router misbehaves, isolate it. Enable debug logging temporarily, restart the container, and watch the session. Alternatively, run the export manually with the same account and compare. If the manual command works and Oxidized fails, suspect a prompt or console handling issue, which often traces back to an unusual identity string or an old model version.
After a RouterOS Upgrade
Major upgrades occasionally alter login banners, SSH algorithms, or export formatting. When backups begin to fail after an upgrade, update the Oxidized image first. If the issue persists, report it to the project with the RouterOS version and a sanitized debug log, since the model is community-maintained and fixes are usually quick.
Common Mistakes to Avoid
- Using the admin account for backups instead of a read-only user.
- Skipping the address restriction on the service user and on the SSH service.
- Placing the input chain accept rule after a drop rule.
- Treating a text export as a full replacement for binary backups.
- Mixing RouterOS 6 and 7 devices in one group without reviewing diffs.
- Exporting secrets into a repository that is mirrored to a shared platform.
- Forgetting to record RouterOS version and hardware model next to backups.
- Never rehearsing a restore.
- Leaving host key verification disabled after the pilot.
- Ignoring failed nodes until a device actually fails.
Oxidized Compared with Other MikroTik Backup Methods
| Method | Cost | Version Control | Multi-Vendor | Best Fit |
|---|---|---|---|---|
| Oxidized | Free | Native Git | Yes | Teams wanting history, diffs, and API access |
| On-device scripts | Free | No | No | Very small deployments |
| The Dude | Free | Limited | Mostly MikroTik | Visibility within a MikroTik-only network |
| Ansible with community.routeros | Free | You build it | Yes | Teams already invested in Ansible |
| Commercial NCM suites | Licensed | Yes | Yes | Organizations that want vendor support |
In most mixed environments, Oxidized wins on simplicity, because one tool covers MikroTik, Cisco, Juniper, Fortinet, and more with the same Git workflow. Ansible provides richer automation, but you assume ownership of scheduling, storage, and diffing.
Real-World Scenarios
Scenario One: Tracing an Unexplained Outage
A branch loses internet access after hours. The on-call engineer opens the Git history for that router and finds a commit forty minutes earlier that reordered two firewall filter rules. The diff shows the exact lines, the syslog entry names the administrator, and the fix is a two-line revert instead of an evening of guessing.
Scenario Two: Replacing a Dead Router at a Remote Site
A branch hAP fails and a replacement is shipped. The engineer extracts the latest export from Git, reviews it for interface names, re-enters the Wi-Fi passphrase and VPN secret, and runs the reset-and-import procedure. The site returns to service the same day, using a process the team had already rehearsed.
Scenario Three: Standardizing a Hardening Baseline
After a security review, the team wants to know which routers still allow Telnet or expose WebFig to the internet. A search across the repository for the relevant service lines answers the question in seconds, and a follow-up commit history proves when each device was corrected.
Optimization Recommendations
| Area | Recommendation | Benefit |
|---|---|---|
| Image management | Pin a tested version and upgrade deliberately | Predictable behavior |
| Polling | Hourly interval plus syslog triggers | Fresh data, low load |
| Export policy | Compact export with sensitive values hidden | Small diffs, safer repository |
| Binary backups | Nightly encrypted file per device | Complete recovery path |
| Repository care | Periodic garbage collection and off-site mirror | Smaller storage and resilience |
| Alerting | Notify on failed nodes and on changes to critical routers | Faster response |
| Documentation | README with restore steps and version notes | Faster recovery under pressure |
Frequently Asked Questions
Does Oxidized support MikroTik RouterOS?
Yes. Oxidized includes a routeros model that connects over SSH, runs a configuration export, and stores the result in Git or another output.
Is a text export enough to restore a MikroTik router?
It is enough to rebuild most configuration, but it may omit or hide secrets, certificates, and some device-specific data. For complete recovery, keep an encrypted binary backup as well.
What permissions does the Oxidized user need on RouterOS?
Start with SSH and read policies in a dedicated group, restricted to the Oxidized server address. Add policies only if the export proves incomplete.
Does Oxidized work with both RouterOS 6 and RouterOS 7?
Yes, although export defaults and SSH behavior differ. Pilot both versions together and review the first diffs before rolling out widely.
How often should I back up MikroTik configurations?
An hourly poll suits most networks. Adding syslog triggers captures changes within seconds when tighter evidence is required.
Can I use SSH keys instead of passwords?
Yes. Import the public key for the service user with the ssh-keys import command and reference the private key in the Oxidized configuration. RSA keys work across both major versions.
Why does Oxidized commit every time it runs?
A volatile line, usually a timestamp or generated value, is changing between exports. Update Oxidized, compare consecutive diffs, and tune until two consecutive runs produce no commit.
How do I push MikroTik backups to GitLab or GitHub?
Add a githubrepo hook bound to the post_store event with a deploy key and a private remote repository.
Can Oxidized restore a configuration to the router?
No. Oxidized collects and versions configurations. Restoration uses RouterOS tools such as import and reset-configuration with a run-after-reset script.
Does Oxidized back up CRS switches and CHR instances?
Yes, as long as the device runs RouterOS and accepts SSH logins. Use the routeros model for both.
Conclusion
Backing up MikroTik routers with Oxidized replaces scattered files with a living, searchable history. A read-only SSH account with address restrictions keeps risk low, the routeros model handles console quirks, and Git turns every change into an auditable record. Furthermore, syslog triggers and the REST API make the system responsive, while encrypted binary backups close the remaining recovery gaps.
The next step is small and practical: create the service account on one pilot router, run the container, and prove that two consecutive backups create a single commit. After that, add the remote push, tune the export policy, enable syslog triggers, and rehearse a restore on spare hardware. Once the pattern works for MikroTik, the same pipeline extends to every other vendor in your network.

