For years, changing our network meant the same ritual. Open a terminal, SSH into one MikroTik router, paste in a firewall rule, jump to the next device, paste again, and quietly hope I hadn't fat-fingered a semicolon somewhere along the way. On a good day it took two hours. This is the story of how MikroTik, Terraform, network as code, and the goal of zero SSH typos turned that ritual into a twenty-minute pull request.

The SSH-and-pray era

Picture forty routers configured entirely by hand. You copy-paste a rule from one box to the next, tweak an IP here, a comment there, and tell yourself the semicolons are fine. There is no version control. No rollback. No audit trail. Just a terminal window and whatever you can remember.

The failure mode was always the same. Something breaks at 11 PM, and now you are trying to recall which rule you touched three hours ago, on which router, and whether the fix you applied to device twelve ever made it to device thirteen. If a change took down the network, "roll back" meant retyping the old config from memory. That is not engineering. That is gambling.

And the knowledge lived nowhere. When the one person who understood the NAT layout went on vacation, the network went with them.

Why network gear gets left behind

Servers got Infrastructure as Code years ago. We version app configs, we template Kubernetes, we review Terraform for cloud resources in pull requests. But network devices somehow stayed stuck in the SSH-and-pray world, treated as special hand-fed pets that only the senior engineer was allowed to touch.

The thing is, RouterOS has an API. If a device has an API, it can be automated. There was never a good reason to keep the routers out of Git. There was only habit.

The setup: Terraform talks to RouterOS

So I replaced the whole ritual with a Terraform provider that talks directly to the MikroTik RouterOS API. Firewall rules, NAT, DHCP, VLANs, all of it defined in HCL and living in a repository like any other piece of infrastructure.

A few Python scripts handle the parts Terraform is awkward at: bulk operations across dozens of routers, and a validation layer that runs before anything is applied. That validation is the quiet hero. It catches the malformed rule, the overlapping subnet, the typo, before any of them ever reach a live device.

And every change goes through a pull request. Someone reads the diff. Someone approves it. The network only feels a change after a human has looked at it, not during a 2 AM copy-paste marathon.

What actually changed

The before-and-after was not subtle.

  • Time per change: from 2-3 hours down to 15-20 minutes.
  • Rollback: from "retype it from memory" to a single git revert.
  • Errors: validation catches them before apply, instead of production catching them for you.
  • Audit trail: full history for every change, on every router, every time. git blame works on network configs too.
  • Onboarding: a new engineer can read the HCL on day one and understand the entire topology, instead of spelunking through SSH history and asking "who changed the NAT rules last Thursday?"

That last one matters more than the time savings. The network stopped being tribal knowledge and became something you could actually read.

Boring is the goal

Here is the part that surprised me. Network operations went from stressful to boring. No more late-night adrenaline, no more praying over semicolons, no more archaeology to figure out what changed. Just a diff, a review, an apply.

And in networking, boring is exactly what you want. Boring means predictable. Predictable means the thing your entire company runs on does not surprise you at midnight.

If it isn't in Git, it doesn't exist

MikroTik, Cisco, Juniper, the vendor barely matters. The principle is identical: define it in code, version it, review it, apply it safely. Config that lives in one person's head dies the moment that person goes on vacation. Config that lives in Git is boring, versioned, and recoverable in minutes.

So the only real question is the one I keep asking other engineers: is your network config in Git, or in someone's head?