В примере на данной странице представлено развертывание Oxidized с целью автоматизированного сбора конфигураций с коммутаторов BDCOM. Для сбора с оборудования других производителей действия аналогичные с поправкой на их специфику подключения и получения конфигураций конкретных моделей.
Oxidized – это система автоматического резервного копирования конфигураций сетевого оборудования. Она подключается к маршрутизаторам, коммутаторам и другим устройствам, получает их текущие конфигурации и сохраняет версии файлов в Git-репозитории.
Страница проекта на github.com.
В данной инструкции для подключения к оборудованию и сбора конфигураций используется исключительно протокол SSH. Сам Oxidized кроме SSH поддерживает так же некоторые другие протоколы подключения.
Для развертывания Oxidized подготовлена виртуальная машина со следующими характеристиками:
CPU: 2 vCPU
RAM: 2 ГБ
Диск: 50 ГБ (система+данные)
Сеть: 1 Gbit/s
ОС: Ubuntu Server 24.04 LTS
Это характеристики для небольшой установки для бэкапа 20-30 сетевых устройств, а не универсальные параметры.
Размещение сервера Oxidized следует выполнять в соответствии с политиками информационной безопасности организации, руководствуясь принципом минимально необходимых сетевых доступов.
Предпочтительно размещать сервер в отдельном серверном VLAN или выделенном сегменте сети, предоставляя ему доступ к оборудованию через правила межсетевого экрана. Размещение Oxidized непосредственно в VLAN сетевого оборудования также допустимо, если это не противоречит требованиям ИБ и доступ к устройствам ограничен соответствующими ACL.
Выделение отдельного сегмента обеспечивает централизованный контроль и фильтрацию сетевого трафика, а также ограничивает возможности перемещения по сети в случае компрометации сервера. При этом оно не устраняет риск использования злоумышленником тех доступов к оборудованию, которые предоставлены самому Oxidized.
Создаем ВМ, если еще не создана. Устанавливаем операционную систему.
Раздача IP-адреса по DHCP с привязкой к MAC-адресу.
Настраиваем весь диск под систему и данные.
Открываем доступ в Интернет на время настроек.
Отмечаем установку SSH сервера.
Задаем понятное название, например, в данном случае название: sw-backup-server.
Создаем учетные данные пользователя и ожидаем установку.
Подключаемся по SSH.
Переходим в режим с правами root.
|
1 |
sudo -i |
(вводим пароль)
Проверяем доступ в Интернет (DNS и доступ к сайтам).
|
1 |
ping -c 4 1.1.1.1 |
|
1 |
curl -I --max-time 10 https://rubygems.org |
Обновляем систему.
|
1 |
apt update |
|
1 |
apt full-upgrade -y |
|
1 |
reboot |
Можно проверить версию Ubuntu после обновления.
|
1 |
lsb_release -a |
Затем отключаем автообновления и доступ в Интернет.
Установка Oxidized.
Устанавливаем зависимости Oxidized.
|
1 |
apt install -y ruby ruby-dev libsqlite3-dev libssl-dev pkg-config cmake libssh2-1-dev libicu-dev zlib1g-dev g++ libyaml-dev libzstd-dev git |
Можно проверить версии и готовность системы к установке.
|
1 2 3 |
ruby --version gem --version git --version |
Git-репозиторий – это хранилище файлов с историей их изменений. Оно сохраняет не только последнюю версию файла, но и предыдущие версии, позволяя просматривать, какие изменения вносились, когда и при необходимости возвращаться к прежнему состоянию.
Устанавливаем основной сборщик конфигураций Oxidized.
|
1 |
gem install oxidized |
Устанавливаем веб-интерфейс и REST API.
|
1 |
gem install oxidized-web |
Сам по себе основной Oxidized может работать без веб-интерфейса. oxidized-web – необязательный компонент.
Проверка
|
1 2 3 |
gem list '^oxidized$' gem list '^oxidized-web$' oxidized -version |
На момент установки актуальные версии были такие:
Создание системной учётной записи и первичная инициализация Oxidized.
Oxidized не рекомендуется запускать от имени root. Для его работы создаётся отдельная системная учётная запись oxidized. От её имени будет выполняться служба, храниться рабочая конфигурация и сохраняться резервные копии конфигураций сетевого оборудования.
Создаём пользователя.
Для примера выбрано имя: oxidized.
|
1 |
useradd --create-home --shell /bin/bash oxidized |
Проверка
|
1 |
id oxidized |
|
1 |
getent passwd oxidized |
|
1 |
ls -ld /home/oxidized |

Переключаемся на пользователя oxidized.
|
1 |
su - oxidized |
Выполняем первый запуск программы одноимённой командой. Это необходимо для создания начального файла конфигурации и пользовательских рабочих каталогов.
|
1 |
oxidized |
(в этом месте oxidized это команда, совпавшая с именем пользователя)
При первом запуске программа может сообщить, что конфигурация создана, либо завершиться с сообщением об отсутствии источника устройств.
Проверяем, какие файлы созданы:
|
1 |
ls -la ~/.config/oxidized/ |

Домашний каталог /home/oxidized важен не сам по себе – именно в нём Oxidized создаёт пользовательскую конфигурацию и связанные рабочие данные.
Завершаем сеанс пользователя oxidized.
|
1 |
exit |
Дальнейшее редактирование конфигурационного файла выполняется от имени администратора (root), поскольку далее необходимо не только изменить параметры работы программы, но и назначить соответствующие права доступа к файлу.
Редактирование основной конфигурации.
Делаем резервную копию конфигурации, чтоб было к чему вернуться.
|
1 |
cp /home/oxidized/.config/oxidized/config /home/oxidized/.config/oxidized/config.orig |
Редактируем содержимое файла конфигурации.
|
1 |
nano /home/oxidized/.config/oxidized/config |
Задаём параметры его работы:
-учётные данные для подключения к коммутаторам;
-модель оборудования BDCOM;
-периодичность сбора конфигураций;
-параметры подключения по SSH;
-Git-репозиторий для хранения конфигураций и истории изменений;
-источник списка оборудования (router.db);
-настройки веб-интерфейса.
Назначение параметров конфигурации.
Измененные параметры относительно дефолтной конфигурации подчеркнуты на скриншоте.
Назначение параметров.
username – имя пользователя для подключения к оборудованию по умолчанию.
password – пароль для подключения к оборудованию по умолчанию.
Если для устройства в router.db указаны индивидуальные учётные данные, то будут использоваться они.
Логины и пароли хранятся в открытом виде!
model: bdcom – модель оборудования по умолчанию. Если модель указана в router.db, применяется значение оттуда.
resolve_dns: false – отключает определение IP-адресов по DNS-именам устройств.
interval: 604800 – интервал опроса оборудования в секундах (604800 = 7 суток). Настраивается индивидуально под потребности в каждом конкретном случае. Можно забирать конфигурацию 1 раз в сутки если на оборудовании выполняется интенсивная работа, или 1 раз в месяц, если оборудование настроено и его больше не трогают.
debug: false – отключает режим отладки и подробное диагностическое журналирование.
run_once: false – Oxidized работает постоянно, а не выполняет только один цикл сбора конфигураций.
threads: 1 – количество одновременно работающих потоков сбора конфигураций.
use_max_threads: false – не использовать автоматически максимальное количество потоков.
timeout: 30 сек – время ожидания ответа при подключении к устройству.
timelimit: 300 сек – максимальное время выполнения сбора конфигурации одного устройства.
retries: 2 – количество повторных попыток при неудачном подключении или сборе конфигурации.
prompt – регулярное выражение для распознавания приглашения командной строки сетевого оборудования (окончание # или >).
next_adds_job: false – отключает автоматическое создание дополнительного задания при принудительном запуске опроса устройства через REST API. Для обычного периодического сбора конфигураций параметр несущественен.
vars: – начало блока дополнительных переменных, передаваемых модели оборудования.
enable: true – передавать модели BDCOM переменную enable со значением true (используется при работе с привилегированным режимом, без этого невозможно вывести конфигурацию).
groups: {} – словарь групп оборудования. В данной конфигурации группы не заданы.
group_map: {} – правила автоматического распределения устройств по группам. Не настроены.
models: {} – дополнительные индивидуальные настройки моделей оборудования. Не заданы.
pid – путь к файлу, в котором хранится идентификатор процесса Oxidized.
log – путь к файлу журнала работы Oxidized.

Веб-интерфейс Oxidized.
extensions – начало блока дополнительных расширений Oxidized.
oxidized—web – настройки расширения веб-интерфейса и REST API.
load: true – включает загрузку расширения Oxidized Web.
listen: 0.0.0.0 – разрешает принимать подключения на всех сетевых интерфейсах сервера. Поэтому доступ к веб-интерфейсу необходимо ограничивать правилами файервола или сетевого экрана.
port: 8888 – порт, на котором работает веб-интерфейс.
Подключение к сетевому оборудованию.
input – начало блока настроек получения конфигураций от оборудования.
default: ssh – использовать SSH в качестве протокола подключения по умолчанию.
debug: false – отключает отладочный режим для входных подключений.
ssh – настройки подключения по протоколу SSH.
secure: false – отключает проверку подлинности SSH-хоста по его ключу (host key verification). Шифрование SSH-соединения при этом сохраняется, однако Oxidized не проверяет, что подключается именно к ожидаемому устройству. Это упрощает первоначальную настройку, но снижает защиту от подмены SSH-сервера. Для повышения безопасности рекомендуется использовать строгую проверку SSH-ключей устройств (secure: true) с предварительным заполнением и сопровождением файла known_hosts.
timeout: 30 сек – время ожидания ответа при установлении SSH-соединения.
auth_methods: [«password»] – использовать парольную аутентификацию.
kex: []– отдельный список алгоритмов обмена ключами SSH не задан.
encryption: []– отдельный список алгоритмов шифрования SSH не задан.
host_key: []– отдельный список алгоритмов проверки ключей SSH-хоста не задан.
Параметры kex, encryption и host_key оставлены пустыми. Это означает, что мы не переопределяем списки алгоритмов SSH вручную. Фактически используемые алгоритмы определяются библиотекой SSH и её настройками.
Хранение конфигураций и история изменений.
output – начало блока настроек сохранения полученных конфигураций.
default: git – использовать Git для хранения конфигураций и ведения истории изменений. Это позволяет просматривать различия между версиями и при необходимости возвращаться к предыдущим.
git – настройки Git-репозитория.
user: Oxidized – имя автора изменений, которое будет отображаться в истории Git.
email: oxidized@localhost – электронный адрес автора изменений в записях Git. Это не адрес для отправки уведомлений.
repo – путь к локальному Git-репозиторию, в котором хранятся конфигурации и история их изменений.
Git сохраняет историю изменений конфигураций, а не историю каждого опроса оборудования. Если после очередного опроса конфигурация не изменилась, новая версия файла в Git не создаётся.

Источник списка сетевого оборудования.
source – начало блока настроек источника списка оборудования.
default: csv – использовать CSV-файл в качестве источника списка устройств.
csv – настройки CSV-источника.
file – путь к файлу router.db, содержащему список сетевого оборудования.
delimiter: !ruby/regexp /:/ – использовать двоеточие (:) в качестве разделителя полей файла.
map – определяет соответствие столбцов файла router.db параметрам Oxidized.
name: 0 – первый столбец – имя устройства.
ip: 1 – второй столбец – IP-адрес устройства.
model: 2 – третий столбец – модель оборудования.
username: 3 – четвёртый столбец – имя пользователя для подключения.
password: 4 – пятый столбец – пароль для подключения.
Таким образом, активирована возможность задавать индивидуальные учётные данные для каждого устройства.
Например, model: 2 – индивидуальное указание оборудования в файле router.db
Цифра 2 – это порядковый номер столбца, начиная с нуля (индексы массива).
Если строка в router.db выглядит так:
|
1 |
SW-1:192.168.1.10:bdcom:admin:password1 |
то Oxidized читает её следующим образом:
|
1 2 3 4 5 |
1 0 SW-1 2 1 192.168.1.10 3 2 bdcom 4 3 admin 5 4 password1 |
Поэтому в конфигурации:
|
1 2 3 4 5 6 |
map: name: 0 ip: 1 model: 2 username: 3 password: 4 |
model: 2 означает: взять значение модели из третьего столбца файла router.db.
Сопоставление моделей оборудования
model_map: {} – дополнительная таблица соответствия названий моделей оборудования. В текущей конфигурации не используется, поскольку отдельные правила сопоставления не заданы.
Настройка уведомлений об ошибках сбора конфигураций. Эта часть конфигурации относится к дополнительным настройкам и скрипту авто-архивирования, который описан в конце. Эти настройки могут понадобится не всем. Кому не нужно – удалить их.
hooks – начало блока дополнительных действий (обработчиков событий) Oxidized.
email_node_fail: – имя обработчика, предназначенного для уведомления об ошибке сбора конфигурации устройства.
type: exec – при возникновении события выполнить внешнюю команду или скрипт.
events: [node_fail] – запускать обработчик при возникновении ошибки сбора конфигурации устройства.
cmd – путь к выполняемому скрипту отправки уведомления по электронной почте.
async: true – выполнять скрипт асинхронно, не ожидая его завершения.
timeout: 30 сек – максимальное время выполнения обработчика.
Данный блок подключает внешний скрипт отправки уведомлений. При возникновении ошибки сбора конфигурации сетевого устройства Oxidized запускает скрипт /usr/local/sbin/oxidized-mail-alert.sh, который формирует и отправляет сообщение администратору по электронной почте. Настройка самого скрипта и почтовой службы рассматривается отдельно (в конце).
После внесения настроек назначаем владельцем файла пользователя oxidized и ограничиваем права доступа: чтение и запись разрешены только владельцу. Это необходимо для защиты учётных данных, используемых при подключении к сетевому оборудованию.
|
1 2 |
chown oxidized:oxidized /home/oxidized/.config/oxidized/config chmod 600 /home/oxidized/.config/oxidized/config |
Список устройств router.db.
Создаём список устройств.
|
1 |
nano /home/oxidized/.config/oxidized/router.db |
Начинать следует с одного устройства.
Добавляем в файл одну строку для тестового коммутатора.
|
1 |
BDCOM-S2900-01:192.168.1.10:bdcom |
Пароли в router.db хранятся в открытом виде. Поэтому файл должен иметь ограниченные права доступа, а резервные копии самого файла необходимо защищать наравне с основным конфигурационным файлом Oxidized.
Назначаем права файла – oxidized: владелец, чтение и запись.
|
1 2 |
chown oxidized:oxidized /home/oxidized/.config/oxidized/router.db chmod 600 /home/oxidized/.config/oxidized/router.db |
Выполняем тестовый запуск командой:
|
1 |
oxidized |
Проверяем результат в отдельной SSH сессии.
|
1 |
ps -ef | grep '[o]xidized' |
Проверяем журнал (лог):
|
1 |
tail -n 100 /home/oxidized/.config/oxidized/oxidized.log |
По логу:
-Oxidized starting – приложение запущено.
-Loaded 1 nodes – загружен один коммутатор.
-Oxidized-web server listening on 127.0.0.1:8888 – веб-интерфейс запущен, но пока доступен только с самого сервера.
(настройка для доступа с любых интерфейсов уже добавлен в конфигурацию, см. выше)
-Configuration updated for /BDCOM-S2900-01 – конфигурация узла обработана и сохранена в репозитории.
Папка configs.git создана, но пока нужно проверить содержимое резервной копии.
Проверяем, создался ли Git-репозиторий:
|
1 |
ls -la /home/oxidized/.config/oxidized/configs.git |

Проверяем содержание.
|
1 2 |
git --git-dir=/home/oxidized/.config/oxidized/configs.git \ show HEAD:BDCOM-S2900-01 |

Из вывода видно, что show fan-status – команда не выполняется. Возможно, другой синтаксис или вообще отсутствует в данной модели.
Проверяем по очереди команды в коммутаторе при подключении по SSH вручную (не через oxidized).
|
1 2 3 4 |
show running-config show version show power-status show fan-status |
Команда show fan-status так же не выполняется.![]()
Убираем неподдерживаемую команду. У кого в BDCOM есть вентиляторы, и такая команда выполняется – убирать её не нужно.
Открываем модель:
|
1 |
nano /var/lib/gems/3.2.0/gems/oxidized-0.37.0/lib/oxidized/model/bdcom.rb |
Удаляем следующий блок целиком:
|
1 2 3 |
cmd 'show fan-status' do |cfg| comment cfg end |

Сохраняем Ctrl+X, выходим.
Перезапускаем Oxidized
В терминале, где запущен Oxidized от пользователя oxidized, нажимаем Ctrl+C. Затем запускаем снова.
|
1 |
oxidized |
Ожидаем 15-30 секунд и проверяем результат от root.
|
1 |
tail -n 40 /home/oxidized/.config/oxidized/oxidized.log |
Проверяем что вывелось в конфигурацию при запрое из Oxidized.
|
1 2 |
git --git-dir=/home/oxidized/.config/oxidized/configs.git \ show HEAD:BDCOM-S2900-01 |

В сохранённом файле виден вывод конфигурации коммутатора.
Проверяем вход в WEB-интерфейс через браузер из компьютера администратора.
|
1 |
http://192.168.1.25:8888/nodes |
(у каждого свой IP-адрес)
Конфигурацию коммутатора можно просмотреть в браузере.
Из недостатка замечен доступ без логина и пароля.
Веб-интерфейс Oxidized не следует публиковать в общедоступных сетях. Доступ к нему необходимо ограничить межсетевым экраном, разрешив подключение только с рабочих мест администраторов. При необходимости организации более сложного разграничения доступа можно использовать обратный прокси-сервер с авторизацией пользователей.
Служба и автозапуск при старте системы.
Останавливаем ручной запуск
В терминале, где запускали oxidized от пользователя oxidized, нажимаем Ctrl+C.
Проверяем, что процесс остановлен:
|
1 |
ps -eo pid,user,args | grep '[o]xidized' |
Не должно остаться процесса:![]()
Создаём службу systemd.
Выполняем в терминале с правами root.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
cat > /etc/systemd/system/oxidized.service <<'EOF' [Unit] Description=Oxidized Network Configuration Backup After=network-online.target Wants=network-online.target [Service] Type=simple User=oxidized Group=oxidized Environment=HOME=/home/oxidized WorkingDirectory=/home/oxidized ExecStart=/usr/local/bin/oxidized Restart=on-failure RestartSec=10 [Install] WantedBy=multi-user.target EOF |
Или создаем файл вручную.
|
1 |
nano /etc/systemd/system/oxidized.service |
И добавляем содержание.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
[Unit] Description=Oxidized Network Configuration Backup After=network-online.target Wants=network-online.target [Service] Type=simple User=oxidized Group=oxidized Environment=HOME=/home/oxidized WorkingDirectory=/home/oxidized ExecStart=/usr/local/bin/oxidized Restart=on-failure RestartSec=10 [Install] WantedBy=multi-user.target |
Сохраняем Ctrl+X, выходим.
Включаем автозапуск.
|
1 |
systemctl daemon-reload |
Запускаем службу.
|
1 |
systemctl enable --now oxidized |
Проверяем работу.
|
1 |
systemctl status oxidized --no-pager |
Проверяем последние записи логов.
|
1 |
tail -n 15 /home/oxidized/.config/oxidized/oxidized.log |
Active: active (running) – служба работает.
enabled – будет запускаться автоматически после перезагрузки.
Загружен один узел.
Веб-интерфейс слушает 0.0.0.0:8888.
Заполняем файл router.db коммутаторами. Если логин и пароль отличаются, записываем их согласно формата в конце через двоеточие.
Например:
|
1 |
BDCOM-S2900-01:192.168.1.10:bdcom:user:password |
Система настроена и будет собирать конфигурации коммутаторов автоматически 1 раз в неделю.
Для повышения информационной безопасности на данном сервере необходимо выполнить следующие мероприятия:
Настроить доступ в сервер только с IP-адреса администратора и его дублера. (в iptables или другом используемом FW)
Отключить работу по IPv6 если не используется.
Дополнительно можно настроить работу SSH только по протоколу IPv4 (в файле /etc/ssh/sshd_config)
В каждом коммутаторе рекомендуется создавать отдельного пользователя с ограниченными правами для Oxidized.
Следует учитывать что router.db содержит учётные данные в открытом виде и не хранить файл в ненадежных местах.
Настроить оповещение о событиях на email.
Дополнения ниже описывают решение специфических задач и не являются обязательными в работе Oxidized.
ДОПОЛНЕНИЕ 1.
Пример добавления коммутатора Huawei S6730 По аналогии можно добавлять другие устройства, если для них есть подходящая модель Oxidized.
Определяем модель устройства. Для Huawei VRP используется модель vrp.
Можно проверить файл модели.
|
1 |
ls -l /var/lib/gems/3.2.0/gems/oxidized-0.37.0/lib/oxidized/model/vrp.rb |
Модель vrp подходит не автоматически для всех устройств Huawei. Нужно учитывать семейство оборудования, версию VRP и фактическую совместимость команд, используемых моделью Oxidized.
Перед массовым добавлением устройств необходимо проверить получение полной конфигурации на одном тестовом экземпляре.
Настраиваем индивидуальные учётные данные. В основной конфигурации это уже сделано. Глобальные username и password для существующих BDCOM оставляем без изменений.
Добавляем устройство в список.
Открываем файл router.db.
|
1 |
nano /home/oxidized/.config/oxidized/router.db |
Добавляем новую строку в формате:
|
1 |
ИМЯ:IP:МОДЕЛЬ:ЛОГИН:ПАРОЛЬ |
Пример Huawei:
|
1 |
SW-HUAWEI:192.168.1.2:vrp:Admin:Password |
Перезапускаем Oxidized
|
1 |
systemctl restart oxidized |
После перезапуска Oxidized загрузит список устройств и автоматически попытается получить конфигурацию нового коммутатора. Для доступа в SW Huawei по SSH может понадобится настройка его ACL.
Аналогично добавляются коммутаторы большинства известных производителей.
ДОПОЛНЕНИЕ 2.
При получении больших конфигураций MikroTik через SSH в отдельных условиях может происходить преждевременное завершение передачи данных. Проблема проявляется преимущественно при передаче больших объёмов информации по каналам с ограниченной пропускной способностью и повышенной задержкой. В рассматриваемом случае размер получаемой конфигурации составлял около 128 КБ.В Oxidized есть зарегистрированная проблема, когда конфигурация MikroTik обрывается при получении через SSH. В опубликованном в июле 2026 года случае обрыв происходил примерно на 128 КБ. Как раз этот случай и произошел. Конфигурация большая и размер почти 128Кб = обрыв.
Решение.
Редактируем конфигурацию.
|
1 |
nano /var/lib/gems/3.2.0/gems/oxidized-0.37.0/lib/oxidized/input/sshbase.rb |
Добавляем строку.
|
1 |
max_win_size: 2 * 1024 * 1024 |
Сохраняем, выходим.
Проверяем синтаксис.
|
1 |
ruby -c /var/lib/gems/3.2.0/gems/oxidized-0.37.0/lib/oxidized/input/sshbase.rb |
Перезапускаем Oxidized.
|
1 |
systemctl restart oxidized |
Проверяем статус.
|
1 |
systemctl status oxidized --no-pager |
Повторно получаем конфигурацию в GUI Oxidized. Конфигурация полная.
Изменение файла sshbase.rb относится к исходному коду установленного Oxidized. При обновлении программы или переустановке Ruby Gem внесённая правка может быть потеряна. Поэтому необходимо фиксировать её отдельно и повторно проверять после обновлений.
ДОПОЛНЕНИЕ 3.
Необходимость собирать архив из резервных копий 1 раз в месяц и хранить в защищенном месте вызвана политиками информационной безопасности, принятыми в организации.
Сценарий (скрипт) выполняет ежемесячное архивирование всех конфигураций собранных в Oxidized. Т.е. он не собирает конфигурации самостоятельно, а только проверяет и упаковывает в архив уже сохранённые файлы конфигураций.
Выполняется обработка всех устройств, перечисленных в router.db.
При добавлении нового коммутатора в router.db никаких дополнительных изменений в скрипт не требуется.
Перед созданием архива скрипт проверяет наличие конфигурации каждого устройства. Если хотя бы одна конфигурация отсутствует, выполнение прекращается с сообщением об ошибке.
Скрипт использует последние сохранённые в Git конфигурации. Наличие конфигурации в репозитории не гарантирует, что последнее обращение к устройству завершилось успешно. Поэтому перед архивированием желательно контролировать журнал работы Oxidized и наличие ошибок опроса оборудования.
Скрипт разделен на два скрипта для упрощения и контроля. Первый отвечает исключительно за создание архивов, второй – за запуск первого, контроль результата и уведомление администратора по электронной почте.
Скрипт №1 – oxidized-monthly-backup.sh
|
1 |
nano /usr/local/sbin/oxidized-monthly-backup.sh |
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 |
#!/bin/bash set -euo pipefail REPO="/home/oxidized/.config/oxidized/configs.git" NODES="/home/oxidized/.config/oxidized/router.db" BACKUP_DIR="/var/backups/oxidized/monthly" DATE="$(date +%F)" TMP="$(mktemp -d)" trap 'rm -rf "$TMP"' EXIT COUNT=0 while IFS=: read -r NODE IP USERNAME REST; do [[ -z "${NODE//[[:space:]]/}" ]] && continue [[ "$NODE" =~ ^[[:space:]]*# ]] && continue if ! git --git-dir="$REPO" cat-file -e "HEAD:$NODE" 2>/dev/null; then echo "ERROR: configuration missing for $NODE" >&2 exit 1 fi git --git-dir="$REPO" show "HEAD:$NODE" > "$TMP/$NODE.cfg" COUNT=$((COUNT + 1)) done < "$NODES" if [[ "$COUNT" -eq 0 ]]; then echo "ERROR: no configurations found in router.db" >&2 exit 1 fi mkdir -p "$BACKUP_DIR" ARCHIVE="$BACKUP_DIR/switch-configs-$DATE.tar.gz" tar -czf "$ARCHIVE" -C "$TMP" . chmod 600 "$ARCHIVE" find "$BACKUP_DIR" -maxdepth 1 -type f -name "switch-configs-*.tar.gz" -mtime +365 -delete echo "$(date '+%F %T') SUCCESS: $ARCHIVE ($COUNT configurations)" |

Назначаем права.
|
1 |
chmod 700 /usr/local/sbin/oxidized-monthly-backup.sh |
Проверка синтаксиса сценария.
|
1 |
bash -n /usr/local/sbin/oxidized-monthly-backup.sh |
Проверка выполнения.
|
1 |
/usr/local/sbin/oxidized-monthly-backup.sh |

Скрипт №2 – oxidized-monthly-backup-notify.sh
Скрипт запуска архивирования и отправки уведомлений по электронной почте.
|
1 |
nano /usr/local/sbin/oxidized-monthly-backup-notify.sh |
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 |
#!/bin/bash set -u BACKUP_SCRIPT="${BACKUP_SCRIPT:-/usr/local/sbin/oxidized-monthly-backup.sh}" RECIPIENT="моя_почта@yandex.ru" RUN_LOG="$(mktemp)" trap 'rm -f "$RUN_LOG"' EXIT START_TIME="$(date '+%F %T')" if "$BACKUP_SCRIPT" >"$RUN_LOG" 2>&1; then STATUS="УСПЕХ" RC=0 else RC=$? STATUS="ОШИБКА" fi END_TIME="$(date '+%F %T')" # Вывод архиватора попадёт в журнал cron cat "$RUN_LOG" { printf 'To: %s\n' "$RECIPIENT" printf 'From: моя_почта@yandex.ru\n' printf 'Subject: [Oxidized Backup] %s\n' "$STATUS" printf 'Content-Type: text/plain; charset=UTF-8\n' printf '\n' printf 'Результат ежемесячного архива Oxidized: %s\n' "$STATUS" printf 'Начало: %s\n' "$START_TIME" printf 'Завершение: %s\n' "$END_TIME" printf 'Код завершения: %s\n' "$RC" printf 'Каталог архивов: /var/backups/oxidized/monthly\n\n' printf '%s\n' 'Вывод скрипта архивации:' cat "$RUN_LOG" } | /usr/bin/msmtp --file=/etc/msmtprc -t MAIL_RC=$? if [[ "$MAIL_RC" -ne 0 ]]; then echo "ERROR: email notification failed, msmtp exit code $MAIL_RC" >&2 fi exit "$RC" |

Выполнение скрипта вручную.
|
1 |
/usr/local/sbin/oxidized-monthly-backup-notify.sh |
После создания скрипта назначаем владельца, группу и права доступа:
|
1 2 |
chown root:root /usr/local/sbin/oxidized-monthly-backup-notify.sh chmod 755 /usr/local/sbin/oxidized-monthly-backup-notify.sh |
Права 755 позволяют владельцу читать, изменять и выполнять скрипт, а остальным пользователям – читать и выполнять его.
Скачивание архива через MobaXterm.
Если понадобится получить доступ к архиву, скачиваем его. Для этого просматриваем содержание папки.
|
1 |
ls -lh /var/backups/oxidized/monthly/ |
Выбираем нужный архив и подставляем его название в команду копирования.
Копируем созданный архив в папку tmp.
|
1 2 |
cp /var/backups/oxidized/monthly/switch-configs-2026-10-21.tar.gz \ /tmp/switch-configs-2026-10-21.tar.gz |
Назначаем права того пользователя, который подключен в MobaExterm.
|
1 2 |
chown admin:admin /tmp/switch-configs-2026-10-21.tar.gz chmod 600 /tmp/switch-configs-2026-10-21.tar.gz |
Скачиваем к себе на ПК через менеджер (SFTP) MobaXterm.
После скачивания удаляем временную копию:
|
1 |
rm -f /tmp/switch-configs-2026-10-21.tar.gz |
Исходный архив останется на сервере.
Очистка папки с архивами. (если понадобится)
|
1 |
rm -f /var/backups/oxidized/monthly/switch-configs-*.tar.gz |
Проверка.
|
1 |
ls -lh /var/backups/oxidized/monthly/ |
В скрипт добавлена строка, которая автоматически удаляет архивы старше 365 дней. Она будет запускаться после успешного создания нового архива.
При добавлении устройства от другого производителя, дополнительных изменений в скрипте архивации и расписании не требуется.
В архив попадут устройства, перечисленные в router.db, если их конфигурации уже сохранены в Git.
Настройка автоматического запуска архивирования по расписанию.
Для автоматического ежемесячного запуска архивирования используется системное расписание Cron.
Файл задания:
|
1 |
/etc/cron.d/oxidized-monthly-backup |
Создаем или открываем файл.
|
1 |
nano /etc/cron.d/oxidized-monthly-backup |
Добавляем строку:
|
1 |
0 2 1 * * root /usr/local/sbin/oxidized-monthly-backup-notify.sh >> /var/log/oxidized-monthly-backup.log 2>&1 |
В результате архивирование будет выполняться **первого числа каждого месяца в 02:00** от имени пользователя root.
При запуске используется скрипт oxidized-monthly-backup-notify.sh, который выполняет основной сценарий архивирования и отправляет уведомление о результате на электронную почту.
Вывод выполнения и сообщения об ошибках записываются в журнал:
|
1 |
/var/log/oxidized-monthly-backup.log |
Проверить настройку можно командой:
|
1 |
cat /etc/cron.d/oxidized-monthly-backup |
Настройка отправки уведомлений.
Для отправки уведомлений о результатах архивирования используется программа msmtp.
Перед использованием скрипта oxidized-monthly-backup-notify.sh необходимо настроить SMTP-параметры и учётные данные почтового ящика. Порядок настройки приведён в дополнении 4.
ДОПОЛНЕНИЕ 4.
Настройка SMTP для системного пользователя root. Она нужна чтоб отправлялись уведомления из скрипта oxidized-monthly-backup-notify.sh (ежемесячное архивирование). Скрипт oxidized-monthly-backup-notify.sh запускается через Cron от имени root.
Используется почтовый сервер smtp.yandex.ru по порту 587 с STARTTLS.
Отправитель: моя_почта@yandex.ru
Получатель: моя_почта@yandex.ru
Программа отправки: msmtp
Настраиваем основной конфигурационный файл:
|
1 |
nano /etc/msmtprc |
В нём заданы SMTP-сервер, порт, TLS и параметры учётной записи. Пароль хранится отдельно в /etc/msmtp-credentials, а не непосредственно в конфигурации.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
defaults auth on tls on tls_starttls on tls_certcheck on tls_trust_file /etc/ssl/certs/ca-certificates.crt account мой_аккаунт host smtp.yandex.ru port 587 from моя_почта@yandex.ru user моя_почта@yandex.ru passwordeval "cat /etc/msmtp-credentials" account default : мой_аккаунт |

Назначаем владельца и права на скрипт.
|
1 2 |
chown root:root /usr/local/sbin/oxidized-mail-alert.sh chmod 755 /usr/local/sbin/oxidized-mail-alert.sh |
Пользователь oxidized сможет запускать скрипт, но не сможет изменять его содержимое.
Назначаем владельца и права файла msmtp-credentials.
|
1 2 |
chown root:root /etc/msmtprc /etc/msmtp-credentials chmod 600 /etc/msmtprc /etc/msmtp-credentials |
Настройка SMTP для пользователя oxidized.
Настраиваем отдельную SMTP-конфигурацию для Oxidized. Она используется для уведомлений об ошибках опроса оборудования. Oxidized работает от системного пользователя oxidized, поэтому для него нужно создавать отдельный файл.
Создаем параметры SMTP для Oxidized. Аналогичные параметрам, представленным выше.
|
1 |
nano /home/oxidized/.config/oxidized/.msmtprc |
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
defaults auth on tls on tls_starttls on tls_certcheck on tls_trust_file /etc/ssl/certs/ca-certificates.crt account мой_аккаунт host smtp.yandex.ru port 587 from моя_почта@yandex.ru user моя_почта@yandex.ru passwordeval "cat /etc/msmtp-credentials" account default : мой_аккаунт |
Задаем пароль SMTP (от почтового ящика).
|
1 |
nano /home/oxidized/.config/oxidized/msmtp-credentials |
Назначаем владельца и права.
|
1 2 |
chown oxidized:oxidized /home/oxidized/.config/oxidized/.msmtprc chown oxidized:oxidized /home/oxidized/.config/oxidized/msmtp-credentials |
|
1 2 |
chmod 600 /home/oxidized/.config/oxidized/.msmtprc chmod 600 /home/oxidized/.config/oxidized/msmtp-credentials |
Права 600 означают, что читать и изменять файлы может только их владелец.
Проверка результата по правам.
|
1 |
ls -l /home/oxidized/.config/oxidized/.msmtprc |
|
1 |
ls -l /home/oxidized/.config/oxidized/msmtp-credentials |
Проверяем отправку. Тестовое письмо успешно доставлено.
|
1 |
runuser -u oxidized -- bash -c 'printf "To: моя_почта@yandex.ru\nFrom: моя_почта@yandex.ru\nSubject: Oxidized SMTP test\nContent-Type: text/plain; charset=UTF-8\n\nТест отправки почты от пользователя oxidized.\n" | /usr/bin/msmtp --file=/home/oxidized/.config/oxidized/.msmtprc -t' |
Если команда завершилась без ошибок (код возврата 0), значит msmtp успешно передал письмо почтовому серверу.
Скрипт отправки уведомлений.
Создаем файл.
|
1 |
nano /usr/local/sbin/oxidized-mail-alert.sh |
Содержание.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
#!/bin/bash set -u NODE="${OX_NODE_NAME:-unknown}" EVENT="${OX_EVENT:-unknown}" REASON="${OX_ERR_REASON:-Причина не указана}" { printf 'To: моя_почта@yandex.ru\n' printf 'From: моя_почта@yandex.ru\n' printf 'Subject: [Oxidized] Ошибка опроса: %s\n' "$NODE" printf 'Content-Type: text/plain; charset=UTF-8\n' printf '\n' printf 'Oxidized не смог получить конфигурацию устройства.\n\n' printf 'Устройство: %s\n' "$NODE" printf 'Событие: %s\n' "$EVENT" printf 'Причина: %s\n' "$REASON" } | /usr/bin/msmtp \ --file=/home/oxidized/.config/oxidized/.msmtprc \ -t |

Скрипт получает от Oxidized информацию о сбое и отправляет письмо со следующими данными:
-имя устройства;
-тип события;
-причина ошибки.
В скрипте используется SMTP-конфигурация пользователя oxidized.
Назначаем владельца и права доступа:
|
1 2 |
chown root:root /usr/local/sbin/oxidized-mail-alert.sh chmod 755 /usr/local/sbin/oxidized-mail-alert.sh |
Проверка.
|
1 |
ls -l /usr/local/sbin/oxidized-mail-alert.sh |
Чтоб скрипт работал, в главный конфигурационный файл добавлен обработчик событий Oxidized.
|
1 |
nano /home/oxidized/.config/oxidized/config |
В конец файла добавлен блок:
|
1 2 3 4 5 6 7 |
hooks: email_node_fail: type: exec events: [node_fail] cmd: '/usr/local/sbin/oxidized-mail-alert.sh' async: true timeout: 30 |
type: exec – запуск внешней команды;
events: [node_fail] – событие, возникающее после исчерпания заданного количества попыток опроса устройства;
cmd – путь к скрипту отправки письма;
async: true – выполнение без ожидания завершения отправки в основном процессе;
timeout: 30 – тайм-аут выполнения обработчика.
Количество попыток подключения и интервал опроса определяются другими параметрами Oxidized, в частности retries и interval.
hooks: должен находиться на верхнем уровне YAML, без отступа слева.
Если в конфигурации уже существует раздел hooks:, нужно добавить обработчик внутрь него, а не создавать второй одноимённый раздел.
Перезапускаем службу.
|
1 |
systemctl restart oxidized |
Проверяем статус.
|
1 |
systemctl status oxidized --no-pager |
Проверяем выполнение сценария.
На одном из коммутаторов заблокирован SSH-доступ и запущен oxidized. Подключение не произошло, о чём было отправлено уведомление на email.
Просмотр логов.
|
1 |
tail -n 100 /home/oxidized/.config/oxidized/oxidized.log |
Ручной запуск скрипта
|
1 |
runuser -u oxidized -- env OX_NODE_NAME="TEST" OX_EVENT="node_fail" OX_ERR_REASON="Тест" /usr/local/sbin/oxidized-mail-alert.sh |
Если ручной запуск завершился с кодом 0, это означает, что команда отправки завершилась успешно.
Настройка получилась достаточно сложной. Как вариант упрощения можно попробовать отправлять письма непосредственно из Hook, тем самым исключить скрипт отправки. Но этот способ не тестировался.


