Using Flashfig to bulk upgrade Routerboard devices

Here at Bright WiFi, we go through a LOT of Routerboards, and are proud of our ability to help resellers rapidly deploy new device configurations. When I say a lot.. as of right now we have 1000 hAP units on backorder, with 250~ units waiting to be installed and another 300~ awaiting configuration today. While these are numbers for our own use here in Australia; the system we’ve created was with the intent that anyone should be able to use our platform to achieve similar results.

Because of this, we’ve gone through a number of different revisions to our configuration and deployment process in order to improve the time it takes to get devices ready for installation, as well as ensuring all devices are labeled and we have a record of when they were configured and by whom.

Today I was reading a post on the MikroTik subreddit and saw someone post about configuring multiple devices. One of the hardest parts I’ve struggled with when configuring MikroTik devices in the past has been getting all the units up to the right version before configs can be applied. If this is not done then features or configuration components that aren’t available in the older versions won’t be applied or may prevent the config from loading entirely.

Enter The Deployment Tool

In order to facilitate configuring devices, Bright WiFi has a custom-built deployment tool that is made available to our resellers – while this isn’t much use to anyone as a standalone tool it does allow automation of  “upgrade, configure and test” part of setting up each router. However in using it day to day I would still come across the same underlying delay when configuring a lot of devices at the same time – it has to wait to upgrade each new unit before the configuration can continue.

So what does this mean for upgrades? The deployment tool is great, but it works best in the following scenarios:

  • I have a few devices to upgrade and configure (3-4 min per unit)
  • I have lots of devices to configure that are already upgraded (30 seconds per unit)

The Flashfig Paradox

Flashfig is a useful and at the same time, very frustrating feature of Routerboards.

  • Loads configuration onto a router
  • Works on all new Routerboard devices
  • Only requires a single ethernet connection to the device
  • Can be used to push out a configuration to many devices at once
  • Router shuts down after config is uploaded
  • Config is not deployed until the device is rebooted (power cycle required)
  • No other files can be copied to the device
  • No RouterOS upgrade functionality
  • New config does not persist through a reset (unlike netinstall)

So with that in mind – I came up with the following solution

#Created by Andrew Cox -
#Script provided as is with no responsibility or liability taken for any bugs/issues/misuse

#Requirements: A deployment router with DHCP server, ip address (
#and copies of the RouterOS versions you want to upgrade to - IE 6.34.6
#all devices to be upgraded will be connected back to this main device

#last updated 20160706
/ip dhcp-client add interface=ether1 disabled=no
/ip address add interface=ether2 address=
/system routerboard settings set boot-device=nand-if-fail-then-ethernet

/system scheduler
add interval=5s name=upgraderos on-event=":global scriptname \"u\
\n:if ([:len [/system script job find script=\$\"scriptname\"]] > 0) do={\r\
\n:log info \"\$scriptname Already Running - dont run this\"\r\
\n} else={\r\
\n/system script run upgraderos\r\
\n}" policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive \
add interval=10s name=resetleds on-event=":delay 1s\r\
\n:if ([:len [/system scheduler find name=upgraderos]] >0) do={} else={\r\
\n/system leds\r\
\nset 0 disabled=no leds=led1 type=off\r\
\nset 1 disabled=no leds=led2 type=off\r\
\nset 2 disabled=no leds=led3 type=off\r\
\nset 3 disabled=no leds=led4 type=off\r\
\nset 4 disabled=no leds=led5 type=off\r\
\nset 0 disabled=no leds=led1 type=interface-activity\r\
\nset 1 disabled=no leds=led2 type=interface-activity\r\
\nset 2 disabled=no leds=led3 type=interface-activity\r\
\nset 3 disabled=no leds=led4 type=interface-activity\r\
\nset 4 disabled=no leds=led5 type=interface-activity\r\
\n:delay 1\r\
\n:log info \"newly upgraded device - reset LEDS\"\r\
\n/system scheduler remove resetleds\r\
\n}" policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive start-time=startup

/system script
add name=upgraderos policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive \
source="#Script Variables\r\
\n:global deploymentrouter \"\"\r\
\n:global druser \"routeradmin\"\r\
\n:global drpass \"routerpassword\"\r\
\n:global flash \"0\"\r\
\n:global remotedir \"\"\r\
\n:global upgradeversion \"6.34.6\"\r\
\n#Don't touch anything past here\r\
\n:global localversion [/system resource get version]\r\
\n:set localversion [:pick \$localversion 0 [:find \$localversion \" \"]]\r\
\n:if (\$upgradeversion = \$localversion) do={\r\
\n\t:log info \"Device already upgraded\"\r\
\n\t:execute {\r\
\n\t:while (1=1) do={\r\
\n\t/system leds\r\
\n\tset [find leds=led3] type=on\r\
\n\tset [find leds=led4] type=on\r\
\n\tset [find leds=led5] type=on\r\
\n\t:delay 500ms\r\
\n\tset [find leds=led3] type=off\r\
\n\tset [find leds=led4] type=off\r\
\n\tset [find leds=led5] type=off\r\
\n\t:delay 500ms\r\
\n\t/system scheduler remove [find where name=upgraderos]\r\
\n\t/system script remove [find where name=upgraderos]\r\
\n\t:delay 1s\r\
\n:execute {\r\
\n:while (1=1) do={\r\
\n\t/system leds\r\
\n\tset [find leds=led3] type=on\r\
\n\t:delay 500ms\r\
\n\tset [find leds=led3] type=off\r\
\n\t:delay 500ms\r\
\n:global arch [/system resource get architecture]\r\
\n:global filelocation {\"software/routeros-\" . \$arch . \"-\" . \$upgradeversion . \".npk\"}\r\
\n:global filename {\"routeros-\" . \$arch . \"-\" . \$upgradeversion . \".npk\"}\r\
\n:global status true;\r\
\n:global duration;\r\
\n:if (\$flash = 1) do={:set remotedir \"flash/\"} else={:set remotedir \"\"}\r\
\n:for a from=1 to=(60) do={\r\
\n\t:if ([:len [/ip route find where dst-address=] ] > 0) do={\r\
\n\t\t:log info \"Starting Software Version Upgrade\"\r\
\n\t\t:do {\r\
\n\t\t\t:set duration [:time { /tool fetch mode=ftp address=\$deploymentrouter src-path=\$filelocati\
on user=\$druser password=\$drpass } ]\r\
\n\t\t} on-error={\r\
\n\t\t\t:set status false;\r\
\n\t\t:if (\$status) do={\r\
\n\t\t\t:log warning (\"Status: transfer finished | Duration: \" . \$duration)\r\
\n\t\t\t:log error \"File download complete - force reboot\"\r\
\n\t\t\t:delay 1s\r\
\n\t\t\t/system reboot\r\
\n\t\t} else={\r\
\n\t\t\t:log error (\"Status: transfer failed\");\r\
\n\t\t\t:execute {\r\
\n\t\t\t\t:while (1=1) do={\r\
\n\t\t\t\t/system leds\r\
\n\t\t\t\tset [find leds=led4] type=on\r\
\n\t\t\t\t:delay 500ms\r\
\n\t\t\t\tset [find leds=led4] type=off\r\
\n\t\t\t\t:delay 500ms\r\
\n\t} else={\r\
\n\t\t:delay 1s\r\
\n\t\t:log info \"...Waiting for DHCP lease ...\"\r\

This, when used as the config to be loaded by flashfig, achieves the following:

1. Adds basic config (DHCP on ether1, on ether2)

2. On startup, if the version doesn’t match the target version wait for a DHCP lease on ether1 then continue

3. Fetch a file matching the architecture + RouterOS version detailed in the script (6.34.6) from

4. Start flashing LED3 on the target router to indicate a download is occurring

5. Reboot when download is finished OR start flashing LED4 to indicate the download failed

6. Upon startup if the version does match the target version, flash LEDs 3-5 to indicate upgrade is complete

7. Remove upgrade scripts

8. Upon next boot – reset LEDs to default and remove final script.

To make this work, you must also have a second MikroTik designated as the deployment router (as noted above) from which all the devices being upgraded can retrieve their files from. I would recommend an RB750/450/hAP and it needs the following basic configuration:

/ip dhcp-client add disabled=no interface=ether1
/ip address add interface=ether2 address=
/interface ethernet
set ether3 master=ether2
set ether4 master=ether2
set ether5 master=ether5
/ip pool add name=local ranges=
/ip dhcp-server
add address-pool=local disabled=no interface=ether2 lease-time=10m name=local
/ip dhcp-server network
add address= gateway= netmask=24
/ip firewall filter
add chain=srcnat out-interface=ether1 action=masquerade

Final notes: make sure to adjust the version, ip address and directory in the script depending on your setup.

Feel free to discuss, ask any questions or make suggestions on the reddit thread for this article here:

Did you like this article? Bright WiFi provides a software-as-a-service offering designed to help service operators improve takeup, simplify deployment and make day to day service management easy. Click on one of the links below to find out more.