LibreNMS && Oxidized 備份網管設備設定檔
BUBU 之前看到節省哥分享這個服務,曾經試著架設過一次,但後來失敗了。最近又看到相關的文章,因此再次嘗試架設,目前已架設成功並可正常運行。
這套工具可以定期自動備份每一台網通設備的設定檔,管理人員不必再手動逐台備份。另一個優點是可以和先前的版本比對差異,設備出問題時能找回上一版的設定來還原。
2026.07.11 系統採用 Ubuntu 系統來做建置
2026.10.06 系統採用 Debian 系統來做建置
運行環境
環境皆架設於「Proxmox VE」虛擬系統,預設以「LXC」模式為主,除非有特殊狀況才會改用「VM」模式。
- 系統環境:Ubuntu 22.04、Debian 12、13
- Oxidized 版本:0.37(Ruby 需 3.0 以上)
安裝過程
以下指令除了切換為 oxidized 使用者的步驟之外,皆以 root 身分執行。
安裝官方套件
- Ubuntu 系列要先啟用 universe 套件庫
apt install software-properties-common -y && add-apt-repository universe
- 安裝必要套件
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
- 安裝 Oxidized 服務
gem install oxidized
- 選用套件(要與 LibreNMS 整合須安裝
oxidized-web)
gem install oxidized-web # Web 介面和 REST API
gem install oxidized-script # 以腳本為基礎的輸入/輸出擴充
- 建立服務使用者並設定密碼
adduser oxidized
- 切換使用者
su - oxidized
- 執行一次
oxidized,系統會在家目錄產生隱藏目錄.config,並建立預設設定檔~/.config/oxidized/config
oxidized
- 確認目錄是否正常產生
ls -la
LibreNMS && Oxidized 設定
- 備份 Oxidized 預設設定檔
mv /home/oxidized/.config/oxidized/config /home/oxidized/.config/oxidized/config.bak
- 建立新的設定檔
vim /home/oxidized/.config/oxidized/config
# Oxidized 設定檔範本(Oxidized 0.37,搭配 LibreNMS)
# 位置:/home/oxidized/.config/oxidized/config;修改後須重啟 oxidized。
# 帳密優先序(低→高):全域 < models < groups < groups 內的 models < 單一設備。
# ===== 全域預設帳密 =====
# 優先序最低。填一組無法登入的假帳密:漏設帳密的設備會直接失敗,不會誤用共用帳密。
username: nologin
password: invalid_placeholder
# ===== 全域預設 model =====
# 來源未提供 model 時才套用;LibreNMS 一律會回傳 os,實務上用不到。
model: junos
# false:設備名稱原樣交給連線模組,不先解析 DNS。
resolve_dns: false
# ===== 抓取排程 =====
# 每台設備的抓取間隔(秒):86400=每天,3600=每小時。
# 由 Oxidized 自行排程;內容未變不會產生新版本。
# 0=停用定期抓取,只在被指定時抓(LibreNMS 重新整理鈕、API /node/next/<設備>)。
interval: 86400
debug: false # true:輸出除錯日誌
threads: 30 # 同時抓取的執行緒上限
timeout: 120 # 單一操作的等待上限(秒);設定內容大的設備可調高
timelimit: 300 # 單台抓取的總時間上限(秒),逾時強制中止
retries: 3 # 失敗後的重試次數
# 預設的提示字元樣式;多數 model 自帶,通常不必改。
prompt: !ruby/regexp /^([\w.@-]+[#>]\s?)$/
# ===== 日誌 =====
# 輸出到 stderr,由 systemd journal 收:journalctl -u oxidized
# 0.34 起取代舊的 use_syslog/log。
logger:
appenders:
- type: stderr
# ===== Web 介面與 REST API =====
# LibreNMS 由此讀取設定。需 oxidized-web 0.16 以上;0.33 起取代舊的 rest: 寫法,兩者並存時本區段會被忽略。
# oxidized-web 沒有登入驗證,預設只聽 127.0.0.1(與 LibreNMS 同機)。
# 不同機時 listen 改為本機對內的單一位址,並以防火牆只放行 LibreNMS;0.0.0.0 會對所有介面開放。
extensions:
oxidized-web:
load: true
listen: 127.0.0.1
port: 8888
# false:/node/next 只把設備排到佇列最前;true:立即抓取。
next_adds_job: false
# 全域變數。常用:remove_secret: true(遮蔽密碼)、enable: <密碼>(特權模式)。
vars: {}
# ===== 依機型(model)設定帳密 =====
# 同機型共用一組帳密時使用;名稱須為 Oxidized 的 model 名稱。
models:
# FortiGate 防火牆(0.36 起為獨立 model)
fortigate:
username: fortiadmin
password: forti_pass
# Fortinet 每次輸出都會重新加密密碼,造成假異動;啟用後只在實質變更時存檔(只改密碼時不會存檔)。
# vars:
# output_store_mode: on_significant
# FortiManager、FortiAnalyzer、FortiSwitch
fortios:
username: fortiadmin
password: forti_pass
# vars:
# output_store_mode: on_significant
# Cisco IOS(IOS-XE、NX-OS 是不同的 model:iosxe、nxos,要用時須另外列)
ios:
username: ciscoadmin
password: cisco_pass
# Juniper
junos:
username: junosadmin
password: junos_pass
# MikroTik
routeros:
username: admin
password: mikrotik_pass
# UniFi AP(Oxidized 沒有名為 unifi 的 model)
unifiap:
username: ubnt
password: ubnt_pass
# D-Link
dlink:
username: dlinkadmin
password: dlink_pass
# ===== 依群組(group)設定帳密 =====
# 同站點共用一組帳密時使用,會覆寫 models。
# 前提:LibreNMS 有送出 group(見下方 source 與 LibreNMS 的 group_support)。不需要可整段移除。
groups:
site_a:
username: site_a_admin
password: site_a_pass
site_b:
username: site_b_admin
password: site_b_pass
# 群組內再依機型區分;優先序僅次於單一設備。
site_c:
models:
fortigate:
username: fortiadmin
password: forti_pass_site_c
ios:
username: ciscoadmin
password: cisco_pass_site_c
# PID 檔
pid: "/home/oxidized/.config/oxidized/pid"
# 程式異常時的記錄
crash:
directory: "/home/oxidized/.config/oxidized/crashes"
hostnames: false
# ===== 連線方式 =====
input:
default: ssh, telnet # 依序嘗試;沒有只能用 Telnet 的設備時改為 ssh
debug: false # true:記錄每台設備的連線過程,僅供除錯
ssh:
secure: false # true:嚴格驗證 SSH 主機金鑰(設備須已在 known_hosts 內);false:不驗證
ftp:
passive: true
utf8_encoded: true # 設備輸出視為 UTF-8
# ===== 儲存:Git =====
# 每次變更產生一筆 commit,LibreNMS 據此顯示版本與差異;沒有保留份數上限。
# 使用 group 時預設每個群組一個 repo;加 single_repo: true 可合併為一個。
output:
default: git
git:
user: "your name" # commit 作者名稱
email: [email protected] # commit 作者信箱
repo: "/home/oxidized/.config/oxidized/oxidized.git"
# ===== 設備來源:LibreNMS =====
# 設備清單取自 LibreNMS API;帳密不由此帶入,由上方 models/groups 決定(採用補充說明的方式一時例外)。
# LibreNMS 使用自簽憑證時,可在 http 底下加 secure: false 關閉憑證驗證(有被中間人攔截的風險)。
source:
default: http
debug: false
http:
url: https://librenms/api/v0/oxidized # 改為 LibreNMS 的位址
map:
name: hostname
model: os # 以 LibreNMS 的 os 作為 model
group: group # 使用 groups 帳密時必須保留
headers:
X-Auth-Token: "<LibreNMS API Token>"
# ===== model 名稱對應(來源給的名稱 → Oxidized model) =====
# LibreNMS 會自動把多數 os 對應到 Oxidized 的 model,這裡只需補它沒涵蓋的(例如 unifi);對不上時日誌會出現 ModelNotFound。
# juniper、cisco 兩筆是 Oxidized 的預設值;LibreNMS 的 os 實際為 junos、ios、routeros、dlink,與 model 同名,不需對應。
# fortigate 不可對應到 fortios(0.36 起各為獨立 model)。
model_map:
juniper: junos
cisco: ios
mikrotik: routeros
unifi: unifiap
dlink: dlink
- 設定檔內含明文帳密與 API Token,把權限限縮為只有擁有者可讀寫
chmod 600 /home/oxidized/.config/oxidized/config
- 在 LibreNMS 主機啟用 Oxidized 整合,也可以從 Web 介面的 Global Settings → External Settings → Oxidized Settings 設定
lnms config:set oxidized.enabled true
lnms config:set oxidized.url http://127.0.0.1:8888 # Oxidized Web 介面的位址,不同機時改為 Oxidized 主機的位址
lnms config:set oxidized.features.versioning true # 顯示歷史版本與差異(需 Git 輸出)
lnms config:set oxidized.group_support false # 要使用 groups 帳密須改為 true
lnms config:set oxidized.reload_nodes true # 新增設備後通知 Oxidized 重新載入清單
lnms config:set oxidized.ignore_os '["ping", "linux", "generic"]' # 不交給 Oxidized 備份的 os
- 舊版寫法(備用):修改 LibreNMS 設定檔
config.php。同一個設定不要同時用上面的指令(或 Web 介面)與config.php設定
# Oxidized 整合
$config['oxidized']['enabled'] = true;
$config['oxidized']['url'] = 'http://oxidized 位置:8888'; # Oxidized Web 介面的位址
$config['oxidized']['features']['versioning'] = true; # 顯示歷史版本與差異(需 Git 輸出)
$config['oxidized']['group_support'] = false; # 要使用 groups 帳密須改為 true
$config['oxidized']['default_group'] = false; # 預設群組;false=不設(官方預設值)
$config['oxidized']['reload_nodes'] = true; # 新增設備後通知 Oxidized 重新載入清單
# 群組對應範例:os 為 pfsense 的設備歸入 pfsense 群組
#$config['oxidized']['maps']['group']['os'][] = array('match' => 'pfsense', 'group' => 'pfsense');
# 不交給 Oxidized 備份的 os
$config['oxidized']['ignore_os'] = array('ping', 'linux', 'generic');
- 確認 Oxidized 主機能正常連線到 LibreNMS API(網址與 Token 請改為實際值)。回傳內容須為非空的設備清單,否則 Oxidized 啟動後會直接結束
curl -H 'X-Auth-Token: YOURAPITOKENHERE' https://librenms/api/v0/oxidized
設定 oxidized 服務檔
- 離開
oxidized使用者,回到 root
exit
- 建立服務檔
vim /etc/systemd/system/oxidized.service
# Put this file in /etc/systemd/system.
#
# To set OXIDIZED_HOME instead of the default,
# ~oxidized/.config/oxidized, uncomment (and modify as required) the
# "Environment" variable below so systemd sets the correct
# environment.
[Unit]
Description=Oxidized - Network Device Configuration Backup Tool
After=network-online.target multi-user.target
Wants=network-online.target
[Service]
ExecStart=/usr/local/bin/oxidized
User=oxidized
KillSignal=SIGKILL
#Environment="OXIDIZED_HOME=/etc/oxidized"
Restart=on-failure
RestartSec=300s
[Install]
WantedBy=multi-user.target
- 啟動服務並設為開機自動啟動
systemctl daemon-reload && systemctl enable --now oxidized.service
- 確認服務執行狀態
systemctl status oxidized.service
- 再到 LibreNMS 上確認是否可以看到該網通設備的設定檔
- 也可以到 Oxidized 頁面查看
http://oxidized 位置:8888(listen為 127.0.0.1 時只能從 Oxidized 主機本機連線)
補充說明
BUBU 公司裡各設備的帳密不盡相同,因此需要在設定檔另外處理,以下提供兩種方式。
- 方式一:由 LibreNMS 帶入帳密,Oxidized 與 LibreNMS 兩邊都要設定。由此帶入的帳密優先序最高,會蓋過
models、groups的設定;帳密也會以明文存在 LibreNMS 的設定裡並經由 API 回傳,建議優先採用方式二。先在 Oxidized 設定檔的source區段加入username、password對應
source:
default: http
debug: false
http:
url: https://librenms/api/v0/oxidized
map:
name: hostname
model: os
group: group
# 新增加以下兩個參數
username: username
password: password
headers:
# 由 LibreNMS 的 API 設定頁面產生的金鑰
X-Auth-Token: "<LibreNMS API Token>"
- 再到 LibreNMS 設定各 os 對應的群組與帳密。
match比對的是 LibreNMS 的 os 值(FortiGate 防火牆的 os 是fortigate,請依實際設備填寫);群組對應要group_support為 true 才會生效
lnms config:set oxidized.group_support true
lnms config:set oxidized.maps.group.os.+ '{"match": "fortios", "value": "fortios"}'
lnms config:set oxidized.maps.username.os.+ '{"match": "fortios", "value": "admin"}'
lnms config:set oxidized.maps.password.os.+ '{"match": "fortios", "value": "PW_A"}'
- 舊版寫法(備用)
$config['oxidized']['maps']['group']['os'][] = array('match' => 'fortios', 'group' => 'fortios');
$config['oxidized']['maps']['username']['os'][] = array('match' => 'fortios', 'username' => 'admin');
$config['oxidized']['maps']['password']['os'][] = array('match' => 'fortios', 'password' => 'PW_A');
- 查到的範例(舊版寫法)
$config['oxidized']['ignore_os'] = array('linux','windows');
$config['oxidized']['ignore_types'] = array('server','power');
$config['oxidized']['maps']['group']['os'][] = array('match' => 'ios', 'group' => 'Cisco');
$config['oxidized']['maps']['group']['os'][] = array('match' => 'iosxe', 'group' => 'Cisco');
$config['oxidized']['maps']['group']['os'][] = array('match' => 'nxos', 'group' => 'Nexus');
$config['oxidized']['maps']['group']['os'][] = array('match' => 'procurve', 'group' => 'Aruba');
$config['oxidized']['maps']['group']['os'][] = array('match' => 'arista_eos', 'group' => 'Arista');
$config['oxidized']['maps']['username']['os'][] = array('match' => 'procurve', 'username' => 'admin');
$config['oxidized']['maps']['password']['os'][] = array('match' => 'procurve', 'password' => 'PW_A');
$config['oxidized']['maps']['username']['os'][] = array('match' => 'arista_eos', 'username' => 'admin');
$config['oxidized']['maps']['password']['os'][] = array('match' => 'arista_eos', 'password' => 'PW_B');
$config['oxidized']['maps']['username']['os'][] = array('regex' => '/^(ios|nxos|iosxe)$/', 'username' => 'oxidized');
$config['oxidized']['maps']['password']['os'][] = array('regex' => '/^(ios|nxos|iosxe)$/', 'password' => 'PW_Z');
- 方式二:直接在 Oxidized 設定檔
vim /home/oxidized/.config/oxidized/config的models:區段依機型設定帳密。設定檔若已有models:區段(如上方範本),請在該區段內增修,不要在檔尾再加一個models:,重複的鍵會互相覆蓋
models:
fortios:
username: admin
password: PW_A
參考相關網頁
補充說明-更新版本
BUBU 在處理專案時發現客戶的 Oxidized 版本是 0.30,版本較舊,和新版 LibreNMS 搭配時容易報錯,因此協助客戶更新到官方目前最新的 0.37 版。以下記錄整個更新流程,更新之前請先備份資料,並替整台主機做快照。
- 確認目前的 Oxidized 版本及 Ruby 版本
oxidized --version
ruby -v
Ruby 低於 3.0 時不能直接升級 Oxidized,要先升級 Ruby(通常等於升級作業系統版本)
- 停止服務
systemctl stop oxidized
- 備份資料(設定檔、Git 儲存庫與服務檔;Git 儲存庫若放在其他路徑,請一併加入)
tar czf /root/oxidized_backup_$(date +%Y%m%d_%H%M%S).tgz \
/home/oxidized/.config/oxidized /etc/systemd/system/oxidized.service
- 記錄升級前的版本
gem list | grep -i oxidized > /root/oxidized_gem_versions_before.txt
- 升級(兩個套件要一起升,oxidized-web 0.18.1 需要 oxidized 0.34.1 以上)
gem install oxidized oxidized-web
-
調整 Oxidized 設定檔以符合 0.37 版(啟動服務之前完成,寫法可對照上方範本)
rest:改為extensions底下的oxidized-web區段(0.33 起),並移除舊的rest:,兩者並存時新寫法會被忽略use_syslog、log改為logger區段(0.34 起)models新增fortigate區段放 FortiGate 防火牆的帳密,並移除model_map裡的fortigate: fortios(0.36 起兩者為不同的 model)timosmodel 已於 0.35 移除,改用sros
-
啟動服務
systemctl start oxidized
- 確認服務日誌沒有錯誤訊息
journalctl -u oxidized --since '10 minutes ago'
疑難排解
備份失敗,或 LibreNMS 上看不到設定檔時,可以依下列順序查看 Oxidized 的記錄,先確認問題出在哪一段。
- 服務狀態與服務日誌:Oxidized 的日誌輸出到 systemd journal(設定檔
logger區段的stderr)
systemctl status oxidized.service
journalctl -u oxidized -f # 即時追蹤
journalctl -u oxidized --since '1 hour ago' # 最近一小時
journalctl -u oxidized --since today | grep -i '設備名稱或 IP' # 只看特定設備
- 想把日誌另外寫成檔案,可在設定檔的
logger區段加一個file輸出,修改後重啟 oxidized
logger:
appenders:
- type: stderr
- type: file
file: /home/oxidized/.config/oxidized/oxidized.log
- 從 Oxidized 的 REST API 查看設備狀態(在 Oxidized 主機上執行)。
last底下的status為success表示上次抓取成功;no_connection表示所有連線方式都失敗(連不上、登入失敗或逾時)。查不到該設備代表它沒有被載入,請回頭看日誌有沒有ModelNotFound
curl -s http://127.0.0.1:8888/nodes.json # 全部設備與上次抓取結果
curl -s 'http://127.0.0.1:8888/node/show/設備名稱?format=json' # 單一設備
curl -s http://127.0.0.1:8888/node/next/設備名稱 # 把該設備排到下一個抓取
curl -s http://127.0.0.1:8888/reload.json # 重新向 LibreNMS 載入設備清單
- 想看某台設備的連線過程,把設定檔
input區段的debug改為true後重啟 oxidized,每次連線會在logs目錄留下記錄檔,檔名為「設備 IP-連線方式-時間」。記錄檔含設備輸出的完整內容,查完記得改回false並清掉檔案
ls -lt /home/oxidized/.config/oxidized/logs/ | head
- 程式異常結束時的記錄,放在設定檔
crash區段指定的目錄
ls -lt /home/oxidized/.config/oxidized/crashes/
- LibreNMS 端的記錄(路徑依 LibreNMS 的安裝位置而定)
tail -f /opt/librenms/logs/librenms.log
- 錯誤訊息:
ModelNotFound(例如fortigate not found for node) 解決方式: LibreNMS 給的 os 名稱在 Oxidized 找不到同名的 model,該設備不會被載入,LibreNMS 的 Config 分頁會顯示「The request failed. Try again.」。確認 Oxidized 的版本是否有該 model(FortiGate 需 0.36 以上),或在model_map補上對應。 - 錯誤訊息:
Timeout::Error、execution expired解決方式: 已經登入設備,但指令的輸出沒有在timeout秒數內回來,常見於設定內容較大的設備。調高設定檔的timeout,BUBU 這次由 20 調到 120 之後就恢復正常。 - 錯誤訊息:
Net::OpenTimeout、timed out while opening a connection to the host解決方式: 連不上設備的連接埠,確認設備有開 SSH、來源 IP 有被允許。input設為ssh, telnet時,SSH 失敗後改試 Telnet 也會出現這一行,要往前找 SSH 失敗的原因。 - 錯誤訊息:
source returns no usable nodes解決方式: 向 LibreNMS 取回的設備清單是空的,用安裝過程中的curl指令確認 API 網址與 Token 是否正確。 - 錯誤訊息:
oxidized-web not found解決方式: 設定檔啟用了extensions的oxidized-web卻沒有安裝該套件,執行gem install oxidized-web。
備註
BUBU 最近在公司發現 LibreNMS 上無法正常查看網通設備的設定檔,找了一些相關資訊卻一直沒有找到正確答案。後來向社群裡的節省哥請教,查看 Log 檔之後才知道原因出在 PHP 的記憶體上限預設只有 128M,調整到 512M 就可以正常顯示了。
- 調整 php.ini 檔
vim /etc/php/8.0/fpm/php.ini(路徑中的版本號依實際安裝的 PHP 版本調整)
; 調整前
; 記憶體用量上限
memory_limit = 128M
; 調整後
; 記憶體用量上限
memory_limit = 512M
- 重新啟動 PHP-FPM 讓設定生效(服務名稱中的版本號同上)
systemctl restart php8.0-fpm
參考相關網頁
- oxidized 官方 github
- Oxidized Getting Started
- LibreNMS 文件 Oxidized intro
- Pre-Built LibreNMS OVF with Oxidized + Ryslog + 1 Min Polling
- Oxidized – Part 1
- Oxidized – Part 2
- Oxidized Gitlab Storage Backend
- LibreNMS Oxidized-影片
- How to Install & Integrate Oxidized Into LibreNMS | librenms oxidized- 影片
- How to Install & Integrate Oxidized Into LibreNMS
- Oxidized随笔:安装篇
- 构建企业级网络设备自动备份平台 -- Oxidized (一)
- 构建企业级网络设备自动备份系统 -- Oxidized (二)

