MikroTik Script: RouterOS Backup

For the past few months, I’ve been manually backing up my MikroTik (CCR1009-7G-1C-1S+). It was routine, after making any adjustments to my router, I would promptly create and move the backup to a network share hosted on my local Synology NAS unit.  Normally, being someone who prefers automating tasks, I was reluctant to start writing this script, since, at the time, I had never written my own script within RouterOS. Learning a new scripting language in an unfamiliar environment has its own learning curve and would, without a doubt, become a black hole;  a black void of despair that would suck away all the time that I had set aside for this evening for more interesting activities – like reviewing mathematical proofs, calculating probabilities of random events, studying string theory, and doing an inventory of my matchstick collection, which consists of rare matchsticks from all over the world.

Let’s be honest, I didn’t have anything better to do this evening. I flat out planned to get this script written and nailed down to meet my needs and hopefully yours as well. I wrote this script to be somewhat granular. I pulled apart the date and time values and assigned them to new variables to better aid in customization. Mix and match these variables to fit your desired date/time format. I also included boolean variables to turn on/off features you may or may not need. At the very least, it’s easier than commenting out multiple line items one at a time. In the end, I hope this script proves to be beneficial to you. I’m currently using this script in my production environment, but only after I thoroughly tested each feature. If you decide to use this script in your environment, I recommend that you do the same – I take no responsibility for how you use this script.

Marthur's RouterOS Backup Script v1.0

#---------------------------------------------------SCRIPT INFORMATION----------------------------------------------------
#
# Script:  Marthur's RouterOS Backup Script
# Version: 1.0
# Updated: 10/08/2017
# Created: 10/08/2017
# Author:  Marthur Jones
# Website: https://www.marthur.com
#
# The script will first create local backup file(s) (.backup and/or .rsc). The backup file(s) can then be uploaded via
# FTP to another location if needed. Furthermore, depending on the script settings ($keepRecentLocalBackup), the script 
# can leave the most recent backup(s) on the MikroTik OR remove the backup(s). Afterwards, the script can send script
# success/error alerts via e-mail as long as the MikroTik's Email settings have been properly configured (/Tools E-Mail). 
#
# I've written this script to allow for granular/custom filenames:
#
# Backup Filename Syntax:  CustomPrefix_Identity_RouterOS Version_YYYY.MM.DD_HHMMSS.backup
# Backup Filename Example: MikroTik_Triton_RouterOS v6.40.4_2017.10.08_104456.backup
#
#-----------------------------------------------TESTED USING THE FOLLOWING------------------------------------------------
#
# Hardware: CCR1009-7G-1C-1S+
# Firmware: v3.41
# RouterOS: v6.40.4
#
#----------------------------------------------MODIFY THIS SECTION AS NEEDED----------------------------------------------

# script settings
:local saveConfigBackup         true
:local saveSystemBackup         true
:local encryptSystemBackup      false
:local keepRecentLocalBackup    true

# ftp settings
:local ftpUpload                true
:local ftpAddress               "192.168.88.100"
:local ftpPort                  "990"
:local ftpUser                  "user"
:local ftpPassword              "password"
:local ftpDestination           "/Backups"

# email settings
:local emailAlertOnSuccess      true
:local emailAlertOnError        true
:local emailTo                  "tritonb7@gmail.com"
:local emailSubjectOnSuccess    ("MikroTik Backup Alert for ".[/system identity get name]." - SUCCESS")
:local emailSubjectOnError      ("MikroTik Backup Alert for ".[/system identity get name]." - ERROR")
:local emailBody                "MIKROTIK BACKUP SCRIPT SETTINGS\r\n\r\n\
                                saveConfigBackup: $saveConfigBackup\r\n\
                                saveSystemBackup: $saveSystemBackup\r\n\
                                encryptSystemBackup: $encryptSystemBackup\r\n\
                                keepRecentLocalBackup: $keepRecentLocalBackup\r\n\r\n\
                                ftpUpload: $ftpUpload\r\n\
                                ftpAddress: $ftpAddress\r\n\
                                ftpPort: $ftpPort\r\n\
                                ftpUser: $ftpUser\r\n\
                                ftpDestination: $ftpDestination"

# destination directory for local system backup file (.backup)
:local systemBackupDir "/disk1/backups"

# destination directory for local config backup file (.rsc)
:local configBackupDir "/disk1/backups"

# filename prefix
:local filePrefix "MikroTik"

#-------------------------------------------------------------------------------------------------------------------------

:log warning message="START: Backup Script"

# system identity
:local systemIdentity ([/system identity get name])

# router os version
:local routerOSVersion ("RouterOS v".[/system package get number=0 value-name=version])

# months array
:local months ("jan","feb","mar","apr","may","jun","jul","aug","sep","oct","nov","dec")

# get current time
:local currentTime [/system clock get time]
:set currentTime ([:pick $currentTime 0 2].[:pick $currentTime 3 5].[:pick $currentTime 6 8])

# get current Date
:local currentDate [/system clock get date]

# convert name of month to number
:local month [ :pick $currentDate 0 3 ]
:local monthNumber ([ :find $months $month -1 ] + 1)
:if ($monthNumber < 10) do={
    :set monthNumber ("0" . $monthNumber)
}

# set $currentDate to format YYYY-MM-DD
:set currentDate ([:pick $currentDate 7 11] .".". $monthNumber .".". [:pick $currentDate 4 6])

# filename for system backup
:local backupFilename ($filePrefix."_".$systemIdentity."_".$routerOSVersion."_".$currentDate."_".$currentTime.".backup")

# filename for config backup
:local configFilename ($filePrefix."_".$systemIdentity."_".$routerOSVersion."_".$currentDate."_".$currentTime.".rsc")

# filename for wildcard filename search
:local wildcardFilename ($filePrefix."_".$systemIdentity."_".$routerOSVersion."_")

# store various error messages
:local errorMessage

# do not modify - this variable is used for error handling
:local scriptError false

# do not modify - this variable is used for error handling
:local exitBackupScript false

# remove all previous local backups
    :foreach backupFile in=[/file find name~"$wildcardFilename"] do={
        :do {
            /file remove $backupFile
        }   on-error={
                :set errorMessage "Backup Script: Error removing/clearing backups"
                :log error message="$errorMessage"
                :set scriptError true
                :set exitBackupScript true
            }
}

# save new system backup
:if (($saveSystemBackup = true) && ($scriptError = false)) do={
    :if (($encryptSystemBackup = true) && ($scriptError = true)) do={
        :do {
            /system backup save name="$systemBackupDir/$backupFilename"
        }   on-error={
                :set errorMessage "Backup Script: Error saving system backup (.backup file)"
                :log error "$errorMessage"
                :set scriptError true
                :set exitBackupScript true
            }
    }
    :if (($encryptSystemBackup = false) && ($scriptError = false)) do={
        :do {
            /system backup save dont-encrypt=yes name="$systemBackupDir/$backupFilename"
        }   on-error={
                :set errorMessage "Backup Script: Error saving encrypted system backup (.backup file)"
                :log error "$errorMessage"
                :set scriptError true
                :set exitBackupScript true
            }
    }
    :log info message="Backup Script: Finished system backup $systemBackupDir/$backupFilename"
}

# save new config backup
:if (($saveConfigBackup = true) && ($scriptError = false)) do={
    :do {
        /export compact file="/$configBackupDir/$configFilename"
        :log info message="Backup Script: Finished config backup $configBackupDir/$configFilename"
    }   on-error={
            :set errorMessage "Backup Script: Error saving config backup (.rsc file)"
            :log error "$errorMessage"
            :set scriptError true
            :set exitBackupScript true
        }
}

# upload to ftp
:if ($ftpUpload = true) do={

    :delay 5

    :if (($saveSystemBackup = true) && ($scriptError = false)) do={
        :if ([:len [/file find name~"$backupFilename"]] > 0) do={
            :do {
                /tool fetch mode=ftp address="$ftpAddress" port="$ftpPort" user="$ftpUser" password="$ftpPassword"\
                src-path="$systemBackupDir/$backupFilename" dst-path="$ftpDestination/$backupFilename" upload=yes
                :log info message="Backup Script: Finished uploading system backup via FTP to $ftpAddress$ftpDestination/$backupFilename"
            }   on-error={
                    :set errorMessage "Backup Script: Error uploading system backup $systemBackupDir/$backupFilename via FTP to $ftpAddress$ftpDestination/$backupFilename"
                    :log error "$errorMessage"
                    :set scriptError true
                    :local exitBackupScript true
                }
        } 
    }

    :delay 5

    :if (($saveConfigBackup = true) && ($scriptError = false)) do={
        :if ([:len [/file find name~"$configFilename"]] > 0) do={
            :do {
                /tool fetch mode=ftp address="$ftpAddress" port="$ftpPort" user="$ftpUser" password="$ftpPassword"\
                src-path="$configBackupDir/$configFilename" dst-path="$ftpDestination/$configFilename" upload=yes
                :log info message="Backup Script: Finished uploading config backup via FTP to $ftpAddress$ftpDestination/$configFilename"
            }   on-error={
                    :set errorMessage "Backup Script: Error uploading config backup $configBackupDir/$configFilename via FTP to $ftpAddress$ftpDestination/$configFilename"
                    :log error "$errorMessage"
                    :set scriptError true
                    :set exitBackupScript true
                }
        }
    }
}

# remove local backups
:if ($keepRecentLocalBackup = false) do={
    :if (($saveSystemBackup = true) && ($scriptError = false)) do={
        :if ([:len [/file find name~"$backupFilename"]] > 0) do={
            :do {
                :delay 5
                /file remove [/file find name~"$backupFilename"]
                :log info message="Backup Script: Finished local system backup removal"
            }   on-error={
                    :set errorMessage "Backup Script: Error removing recent local system backup $systemBackupDir/$backupFilename"
                    :log error "$errorMessage"
                    :set scriptError true
                    :set exitBackupScript true
                }
        }
    }

    :if (($saveConfigBackup = true) && ($scriptError = false)) do={
        :if ([:len [/file find name~"$configFilename"]] > 0) do={
            :do {
                :delay 5
                /file remove [/file find name~"$configFilename"]
                :log info message="Backup Script: Finished local config backup removal"
            }   on-error={
                    :set errorMessage "Backup Script: Error removing recent local config backup $configBackupDir/$configFilename"
                    :log error "$errorMessage"
                    :set scriptError true
                    :set exitBackupScript true
                }
        } 
    }
}

# send email alert on success
:if (($emailAlertOnSuccess = true) && ($scriptError = false)) do={
    
    :delay 5

    :if (($saveSystemBackup = true) && ($saveConfigBackup = true) && ($scriptError = false)) do={
        :do {
            /tool e-mail send to="$emailTo" subject="$emailSubjectOnSuccess" body="$emailBody\r\n\r\nBackup File: $backupFilename\r\nConfig File: $configFilename"
        }   on-error={
            :set errorMessage "Backup Script: Error sending error alert via email to $emailTo"
            :log error "$errorMessage"
            :set scriptError true
            :set exitBackupScript true
            }
    }
    
    :if (($saveSystemBackup = true) && ($saveConfigBackup = false) && ($scriptError = false)) do={
        :do {
            /tool e-mail send to="$emailTo" subject="$emailSubjectOnSuccess" body="$emailBody\r\n\r\nBackup File: $backupFilename\r\nConfig File: none"
        }   on-error={
            :set errorMessage "Backup Script: Error sending error alert via email to $emailTo"
            :log error "$errorMessage"
            :set scriptError true
            :set exitBackupScript true
            }
    }
    
    :if (($saveSystemBackup = false) && ($saveConfigBackup = true) && ($scriptError = false)) do={
        :do {
            /tool e-mail send to="$emailTo" subject="$emailSubjectOnSuccess" body="$emailBody\r\n\r\nBackup File: none\r\nConfig File: $configFilename"
        }   on-error={
            :set errorMessage "Backup Script: Error sending error alert via email to $emailTo"
            :log error "$errorMessage"
            :set scriptError true
            :set exitBackupScript true
            }
    } 
    
    :if (($saveSystemBackup = false) && ($saveConfigBackup = false) && ($scriptError = false)) do={
        :do {
            /tool e-mail send to="$emailTo" subject="$emailSubjectOnSuccess" body="$emailBody\r\n\r\nBackup File: none\r\nConfig File: none"
        }   on-error={
            :set errorMessage "Backup Script: Error sending error alert via email to $emailTo"
            :log error "$errorMessage"
            :set scriptError true
            :set exitBackupScript true
            }
    }

    :log info message="Backup Script: Sent backup alert via email to $emailTo"
}

# send email alert on error
:if (($emailAlertOnError = true) && ($scriptError = true)) do={
    :do {
        /tool e-mail send to="$emailTo" subject="$emailSubjectOnError" body="$errorMessage"
        :log info message="Backup Script: Sent backup alert via email to $emailTo"
    }   on-error {
            :log error "Backup Script: Error sending error alert via email to $emailTo"
        }
}

:log warning message="END: Backup Script"

Example: Email Alert Output (On Success)

MIKROTIK BACKUP SCRIPT SETTINGS

saveConfigBackup: true
saveSystemBackup: true
encryptSystemBackup: false
keepRecentLocalBackup: true

ftpUpload: true
ftpAddress: 192.168.88.100
ftpPort: 990
ftpUser: user
ftpDestination: /Backups

Backup File: MikroTik_Triton_RouterOS v6.40.4_2017.10.08_104456.backup
Config File: MikroTik_Triton_RouterOS v6.40.4_2017.10.08_104456.rsc

Example: Email Alert Output (On Error)

Backup Script: Error uploading system backup /disk1/backups/MikroTik_Triton_RouterOS v6.40.4_2017.10.08_104456.backup via FTP to 192.168.88.100

Leave a Comment

Your email address will not be published. Required fields are marked *