3年前、私のチームの新人エンジニアが業務時間中に誤ったVLAN設定をコアスイッチに投入してしまいました。数分以内にオフィスの半分が接続を失い、復旧に2時間かかりました――問題が複雑だったからではなく、変更前のスイッチ設定がどうなっていたか誰も把握していなかったからです。記憶を頼りに対応するしかありませんでした。
そのインシデントで学んだことを、私は新しいエンジニア全員に伝えています:コンフィグのバックアップは任意ではありません。手動エクスポートに頼るのは、バックアップが存在しないのと同じです。
誰も語らないコンフィグ消失問題
ほとんどのネットワークチームには似たような話があります。誰かが変更を加え、何かが壊れ、元の設定を思い出そうと全員が右往左往する。「バックアップ」は前回のメンテナンス後に誰も更新していない半年前のエクスポートファイルだったりします。
障害のパターンは多くの人が想定するより広範です:
- ハードウェア障害で交換機器をゼロから設定しなければならないケース
- ロールバックの基準点がない誤設定
- 時系列での設定変更証明を求めるコンプライアンス監査
- 担当者の離職による暗黙知の喪失
手動バックアップスクリプトが必ず壊れる理由
直感的な解決策は、各デバイスにSSHで接続してrunning configをファイルに保存するcronジョブです。最初の1週間はうまく動きます。しかし誰かが新しいスイッチを追加してスクリプトの更新を忘れます。パスワードがローテーションされます。SSHキーが期限切れになります。スクリプトは3ヶ月間サイレントに失敗し続け、全員がバックアップは正常に動いていると思い込んでいます。
根本原因は怠慢ではありません。スクリプトはデバイスのインベントリを認識しません。ベンダーごとのコマンド構文の違いに対応できません。実行間で実際に何が変わったかを検出する仕組みがありません。タイムスタンプ付きのテキストファイルの山ができあがり、「月曜から火曜の間にこのルーターで何が変わったか」という質問に簡単に答えられません。
スイッチ5台なら管理できます。Cisco IOS、Juniper JunOS、MikroTik RouterOS、HP ProCurveにまたがる50台のデバイスとなると、バックアップシステムではなくメンテナンスツールのメンテナンスをする羽目になります。
選択肢の比較:RANCID vs スクリプト vs Oxidized
RANCID(Really Awesome New Cisco confIg Differ)はクラシックなソリューションです。2000年代初頭から存在し、CVSやSubversionによるバージョン管理でマルチベンダーデバイスに対応しています。最大の障壁はセットアップで、重厚なPerlの設定、特定のディレクトリ構造が必要で、ワークフローも現代のGitツールと比べると時代遅れに感じます。
Ansibleのプレイブックはデバイスのコンフィグを取得できますが、設定変更の投入のために設計されており、継続的なコンフィグ収集には向いていません。コンフィグ取得のためにプレイブックを毎時間実行することは技術的には可能ですが、無駄が多く運用上も扱いにくいです。
Oxidizedはまさにこの問題のために作られました。Rubyで書かれており、Cisco、Juniper、MikroTik、Arista、HP ProCurveなど100以上のデバイスタイプをSSHまたはTelnetでネイティブなGit統合とともにサポートしています。デーモンとして動作し、スケジュールに従ってデバイスをポーリングし、検出した変更をGitリポジトリに直接コミットします。そのリポジトリがネットワーク全体のすべての設定変更の完全な検索可能な履歴となります。
OxidizedとGitバックエンドのセットアップ
インストール
OxidizedにはRuby 2.5以上が必要です。Debian/Ubuntuの場合:
sudo apt update
sudo apt install -y ruby ruby-dev libsqlite3-dev libssl-dev pkg-config cmake libgit2-dev
sudo gem install oxidized oxidized-script oxidized-web
RHEL/Rocky Linuxの場合:
sudo dnf install -y ruby ruby-devel sqlite-devel openssl-devel cmake libgit2-devel
sudo gem install oxidized oxidized-script oxidized-web
基本設定
Oxidizedは設定を~/.config/oxidized/configに保存します。最小限の動作する設定を作成します:
---
username: netbackup
password: yourpassword
model: ios
resolve_dns: true
interval: 3600
use_syslog: false
debug: false
pid: "/var/run/oxidized/oxidized.pid"
output:
default: git
git:
single_repo: true
path: /opt/oxidized/configs
source:
default: csv
csv:
file: /etc/oxidized/router.db
delimiter: !ruby/regexp /:/
map:
name: 0
ip: 1
model: 2
username: 3
password: 4
model_map:
cisco: ios
juniper: junos
mikrotik: routeros
理解しておくべき主要な設定:
interval: 3600— 各デバイスを3600秒(1時間)ごとにポーリングoutput.git.single_repo: true— すべてのデバイスコンフィグを1つのGitリポジトリに保存source.csv— プレーンなCSVファイルからデバイスインベントリを読み込み
デバイスインベントリファイル
/etc/oxidized/router.dbにデバイスリストを作成します。各行のフォーマットはホスト名:IP:モデル:ユーザー名:パスワードです:
core-sw-01:192.168.1.1:ios:admin:secretpass
core-sw-02:192.168.1.2:ios:admin:secretpass
edge-router:192.168.1.254:junos:netbackup:junpass
mikrotik-ap:192.168.2.1:routeros:admin:mtpass
Gitリポジトリの初期化
OxidizedはGitリポジトリを自動作成しません。先に初期化が必要です:
mkdir -p /opt/oxidized/configs
cd /opt/oxidized/configs
git init
git config user.email "[email protected]"
git config user.name "Oxidized Backup"
リモートリポジトリ(GitHub、GitLab、またはセルフホストのGitea)にプッシュしたい場合は今追加します:
git remote add origin [email protected]:yourorg/network-configs.git
Oxidizedはローカルへのコミットを担当します。各コミット後にリモートへプッシュするには、post-commitフックか別のcronジョブを設定してください。
Oxidizedをサービスとして実行する
バックグラウンドサービスとして常駐させる前に、まず手動で起動して接続エラーを確認します:
oxidized
初回起動時によく発生する問題が2つあります。1つ目はSSHホスト鍵の受け入れ失敗です。管理ネットワークの範囲に対して/etc/ssh/ssh_configに以下を追加します:
Host 192.168.1.*
StrictHostKeyChecking no
UserKnownHostsFile /dev/null
2つ目はモデル検出の不一致で、デバイスのプロンプトがOxidizedの期待するパターンと一致しない場合です。デバイスが到達不能として表示されるのに手動のSSHは正常に機能する場合は、oxidized -dを実行して生のセッション出力を確認し、不一致を特定してください。
最初のポーリングが成功したら、OxidizedをSystemdサービスに変換します:
sudo useradd -r -s /bin/false oxidized
sudo chown -R oxidized:oxidized /opt/oxidized /etc/oxidized
sudo tee /etc/systemd/system/oxidized.service <<EOF
[Unit]
Description=Oxidized ネットワークコンフィグバックアップ
After=network.target
[Service]
User=oxidized
ExecStart=/usr/local/bin/oxidized
Restart=on-failure
RestartSec=30
[Install]
WantedBy=multi-user.target
EOF
sudo systemctl enable --now oxidized
sudo systemctl status oxidized
GitでコンフィグのHistoryを確認する
最初のポーリングが成功すると、Gitリポジトリには到達可能な各デバイスのコミットが1件ずつ作成されます。以降のポーリングで変更が検出されるたびに新しいコミットが追加され、完全な監査証跡が構築されます:
cd /opt/oxidized/configs
# 特定デバイスのすべての変更を確認
git log --oneline -- core-sw-01
# 今日のコンフィグと先週のコンフィグを比較
git diff HEAD~7 HEAD -- core-sw-01
# 行レベルの差分を含む完全な変更履歴
git log --follow -p -- edge-router
差分出力にはコミット間で変更された正確な行が表示されます:
-interface GigabitEthernet0/1
- description Old_Uplink
- switchport mode trunk
+interface GigabitEthernet0/1
+ description Uplink_to_Core
+ switchport mode trunk
+ switchport trunk allowed vlan 10,20,30
この差分があれば、冒頭で紹介したインシデントの2時間を節約できていたでしょう。
本番環境でのクレデンシャルセキュリティ
router.dbの平文パスワードは、Oxidizedの基本セットアップにおける最も明白な弱点です。本番環境では:
- 各デバイスにコンフィグ読み取り権限のみを持つ専用の読み取り専用バックアップアカウントを作成する
- Oxidizedの
!ruby/object:Oxidized::Env構文を使って環境変数で共有クレデンシャルを管理する - コンフィグに機密IPアドレスやSNMPコミュニティストリングが含まれる場合はGitリポジトリをプライベートに保つ
- 管理対象デバイスのACLでOxidizedサーバーのIPからのSSHアクセスのみを許可する
Cisco IOSで最小限の読み取り専用アカウントを作成する例:
username netbackup privilege 1 secret StrongBackupPass!
ip access-list standard MGMT-ACL
permit 192.168.100.10
line vty 0 4
login local
access-class MGMT-ACL in
Oxidized稼働1週間後の気づき
1週間稼働後にgit logを実行してみてください。NMS ソフトウェアが自動更新を投入していたり、他のエンジニアがこっそり調整を加えていたり、誰も気づかないまま蓄積した設定のドリフトなど、知らなかった変更がほぼ確実に見つかります。その可視性だけでセットアップの時間は十分に元が取れます。
このリポジトリは監査証跡、コンプライアンス証拠、障害復旧の出発点としても機能します。「そのスイッチが壊れる前は何が入っていたっけ?」と悩む代わりに、git show HEAD:core-sw-01を実行するだけです。1秒以内に完全な答えが得られます。

