MikroTik Backup Automation през SSH с Bash скрипт
Автоматичен backup на MikroTik рутери през SSH: binary backup + .rsc export, сваляне към Linux сървър, верификация, ретенция и ntfy известия. Готов за cron.
Зависимости
bashopenssh-clientflock (util-linux)findcurl (по избор, за ntfy) Употреба
./mikrotik-backup.sh Какво прави
Скрипт за автоматично архивиране на MikroTik рутери. За всеки рутер от списъка създава binary backup (пълно състояние на RouterOS) и текстов .rsc export (портабил конфигурация), сваля двата файла през SFTP на локалния сървър, верифицира, че не са празни, изтрива временните файлове от рутера и прилага ретенция — старите директории отпадат автоматично. При проблем праща известие към ntfy.sh (по избор) и връща ненулев exit code, който мониторингът може да прихване.
Пълното ръководство със стъпка по стъпка настройка, импорт на SSH ключ в RouterOS и инструкция за възстановяване: Автоматичен backup на MikroTik рутер.
Кой къде каква роля има
Преди всичко друго — разпределянето на ролите, което спестява най-много главобълскане:
| Устройство | Роля | Какво се инсталира там |
|---|---|---|
| MikroTik рутер | Пази конфигурацията; по заявка създава backup и export | Нищо — само му импортираш SSH ключ |
| Linux сървър (LXC на Proxmox) | Изпълнява скрипта, свързва се с рутера, пази архивите, праща известия | Скриптът + cron задача |
| Твоят компютър (WSL2) | Участва само веднъж — пишеш файла и го качваш на сървъра | Нищо трайно |
Скриптът не се записва нито на рутера, нито на Windows. Живее на Linux машина, включена 24/7. Cron-ът на сървъра го пуска всяка нощ — рутерът просто приема връзката, създава файловете и ги дава за сваляне.
Два терминала — кой каква команда разбира
Това е грешката №1 при първа настройка: командите се пишат в грешния прозорец. Имаш два терминала и те не се смесват:
| Linux терминал (WSL или сървъра) | WinBox → New Terminal | |
|---|---|---|
| Промпт | fedia@host ~ $ | [fedia@Fedia-MikroTik] > |
| Кой говори | Линуксът | Самият рутер |
| Команди там | ssh, ssh-keygen, scp, nano, chmod, git | /ip service …, /user ssh-keys import …, /system backup … |
Ориентирът е прост: команди с наклонена черта отпред (/ip …, /user …) — за рутера. Команди като ssh, scp, nano — за Linux машината. Ако рутерът ти отговори bad command name — си пиши в грешния прозорец; нищо не е счупено, просто смени прозореца.
Характеристики
- Архивира няколко рутера в един пуск — отказът на един не спира останалите
- Създава и двата формата:
.backupза бързо възстановяване и.rscза миграция/одит - SSH ключова автентикация (
BatchMode=yes) — без пароли в скриптове - Поддържа нестандартен SSH порт на всеки рутер — задава се в конфигурацията (виж по-долу)
- Верификация след сваляне — празен файл се брои за грешка, не за успех
- Ретенция: директории по-стари от
KEEP_DAYSдни се изтриват автоматично flockзащита срещу паралелни изпълнения (cron + ръчно пуск)- Логва всичко в
backup.logс timestamp - Известия към ntfy.sh при успех или неуспех (по избор)
Код
#!/usr/bin/env bash
# ============================================================
# mikrotik-backup.sh — Автоматичен backup на MikroTik рутери
# Статия: https://linuxdevops.dev/tutorials/mikrotik-backup-avtomatizacia/
# ============================================================
set -euo pipefail
# ============================ КОНФИГУРАЦИЯ ============================
# Формат: "име|хост|ПОРТ|потребител"
# Портът е ТРЕТОТО поле — ако SSH ти слуша на нестандартен порт, запиши го там.
ROUTERS=(
"main|192.168.88.1|22|backup"
# "garage|192.168.88.2|22|backup"
# "office|10.0.0.254|22222|backup" ← пример: SSH на нестандартен порт
)
BACKUP_DIR="/var/backups/mikrotik" # къде се пазят локално
KEEP_DAYS=30 # колко дни да се пазят стари директории
SSH_TIMEOUT=20 # timeout за SSH връзката (сек)
NTFY_TOPIC="" # по избор: "https://ntfy.sh/таен-topic-тук"
LOG="$BACKUP_DIR/backup.log"
DATE="$(date +%F)"
LOCK="/tmp/mikrotik-backup.lock"
SSH_OPTS=(-o BatchMode=yes
-o ConnectTimeout="$SSH_TIMEOUT"
-o StrictHostKeyChecking=accept-new)
log() { printf '[%s] %s\n' "$(date '+%F %T')" "$*" | tee -a "$LOG"; }
notify() {
if [ -n "$NTFY_TOPIC" ]; then
curl -sS --max-time 10 -H "Title: MikroTik backup" -d "$1" "$NTFY_TOPIC" >/dev/null 2>&1 || true
fi
}
# Забрана на паралелни изпълнения (cron + ръчно пуск)
mkdir -p "$BACKUP_DIR"
exec 9>"$LOCK"
if ! flock -n 9; then
log "❌ Друг backup процес вече работи. Излизам."
exit 1
fi
# backup_router <име> <хост> <порт> <потребител>
backup_router() {
local name="$1" host="$2" port="$3" user="$4"
local dest="$BACKUP_DIR/$name/$DATE"
local bname="${name}-${DATE}"
mkdir -p "$dest"
log "→ $name ($host): започвам…"
# 1. Binary backup на рутера
if ! ssh "${SSH_OPTS[@]}" -p "$port" "$user@$host" \
"/system backup save name=$bname dont-encrypt=yes" >>"$LOG" 2>&1; then
log "❌ $name: не успях да създам binary backup"
return 1
fi
# 2. Текстов export (RouterOS v7: show-sensitive; за v6 махни флага)
if ! ssh "${SSH_OPTS[@]}" -p "$port" "$user@$host" \
"/export show-sensitive file=$bname" >>"$LOG" 2>&1; then
log "❌ $name: не успях да създам .rsc export"
return 1
fi
# 3. Сваляне на двата файла през SFTP
if ! scp -P "$port" "${SSH_OPTS[@]}" \
"$user@$host:$bname.backup" "$user@$host:$bname.rsc" "$dest/" >>"$LOG" 2>&1; then
log "❌ $name: не успях да сваля файловете"
return 1
fi
# 4. Верификация — празен бекъп е по-лош от липсващ
if [ ! -s "$dest/$bname.rsc" ] || [ ! -s "$dest/$bname.backup" ]; then
log "❌ $name: някой от файловете е празен!"
return 1
fi
# 5. Чисти временните файлове от рутера
ssh "${SSH_OPTS[@]}" -p "$port" "$user@$host" \
"/file remove [find name~\"$bname\"]" >>"$LOG" 2>&1 || true
log "✅ $name: OK — $(du -h "$dest/$bname.backup" | cut -f1) backup, $(du -h "$dest/$bname.rsc" | cut -f1) rsc"
}
cleanup_old() {
log "🧹 Изтривам бекъпи по-стари от $KEEP_DAYS дни…"
find "$BACKUP_DIR" -mindepth 2 -maxdepth 2 -type d \
-name "20*" -mtime "+$KEEP_DAYS" -exec rm -rf {} \; 2>>"$LOG" || true
}
log "🚀 MikroTik backup стартира за ${#ROUTERS[@]} рутер(а)"
OK=0; FAILED=0; FAILED_LIST=""
for entry in "${ROUTERS[@]}"; do
IFS='|' read -r name host port user <<< "$entry"
if backup_router "$name" "$host" "$port" "$user"; then
OK=$((OK + 1))
else
FAILED=$((FAILED + 1))
FAILED_LIST="$FAILED_LIST $name"
fi
done
cleanup_old
log "🏁 Край: ✅ $OK успешни, ❌ $FAILED неуспешни"
if [ "$FAILED" -gt 0 ]; then
notify "❌ MikroTik backup: $FAILED неуспешни рутера:$FAILED_LIST (✅ $OK успешни)"
exit 1
fi
notify "✅ MikroTik backup: всички $OK рутера са архивирани успешно."
exit 0
Използване
# Първо ръчно изпълнение (задължително преди cron)
chmod +x mikrotik-backup.sh
./mikrotik-backup.sh
# Резултатът отива в:
# /var/backups/mikrotik/<рутер>/YYYY-MM-DD/<рутер>-YYYY-MM-DD.{backup,rsc}
Преди cron винаги пусни веднъж ръчно — и провери връзката още по-рано с еднострочен тест:
ssh -i ~/.ssh/ключа -p ПОРТА backup@IP-НА-РУТЕРА "/system identity print"
# отпечатва името на рутера = връзката работи, скриптът ще работи
Конфигурация
Всичко е в горната част на скрипта:
| Променлива | Описание |
|---|---|
ROUTERS | Списък "име|хост|порт|потребител" — по един ред на рутер. Портът е третото поле — ако SSH не слуша на 22, просто запиши реалния |
BACKUP_DIR | Локална директория за бекъпите (препоръчително /var/backups/…) |
KEEP_DAYS | Колко дни да се пазят стари дневни директории |
SSH_TIMEOUT | Timeout на SSH връзката в секунди |
NTFY_TOPIC | ntfy.sh topic за известия — остави празно, ако не ползваш |
SSH на нестандартен порт
Смяна на порта е добра практика — автоматичните скенери блъскат по 22, а по 22222 никой не пита. Но тогава всичко трябва да сочи новия порт. Проверката кой порт всъщност слуша:
# в WinBox → New Terminal:
/ip service print
# редът "ssh" показва реалния PORT
Ако портът е друг (да речем 22222), настройката се разпростира на три места и всичко трябва да е съгласувано:
- Скриптът —
"main|192.168.88.1|22222|backup"(третото поле) - Ръчните команди —
ssh -p 22222 …(малка буква),scp -P 22222 …(ГЛАВНА буква — класическа грешка, при scp портът е сP) - Нищо друго — скриптът сам подава порта на ssh и scp с правилния флаг
И тъй като портът е сменен, затвори кръга с whitelist — SSH да е видим само за сървъра, който прави бекъпите:
# в WinBox → New Terminal (смени IP-то с това на своя сървър):
/ip service set ssh address=192.168.88.50/32
Резултатът: от целия интернет и от останалите устройства SSH-ът е невидим — няма какво да се сканира, независимо от порта. Единствено сървърът с бекъпите го вижда. Заедно с потребител, чиято политика е само read,ssh, дори компрометиран ключ не позволява писане по конфигурацията — само четене, което е точно всичко, от което backup-ът се нуждае.
Автоматизация с cron
# MikroTik backup — всеки ден в 03:00 (като root)
0 3 * * * /usr/local/bin/mikrotik-backup.sh >/dev/null 2>&1
Изисквания
- MikroTik рутер с RouterOS v7 (за v6 — махни
show-sensitiveот export командата) - Импортнат SSH публичен ключ на рутера за съответния потребител
- Linux машина с
openssh-clientиflock(стандартно на Debian/Ubuntu) - Ако SSH е на нестандартен порт — той се задава в
ROUTERS, скриптът не го уговаря
Бележки
.backupи.rscфайловете съдържат пароли и ключове — пази ги на сигурно място с ограничени права- За възстановяване:
/system backup load name=…(binary) или/import file-name=…(rsc след reset) - Тествай възстановяването веднъж поне — бекъп без тест е надежда, не backup