👋

自宅インフラバックアップAnsible書いてみた

に公開

ホームネットワーク機器の設定ファイルが複数サーバに散らばっており、障害時の復旧が面倒になってきたため、Ansible を使った一元的なバックアップ体制を構築することにした。

構成例

今回構築したシステムの構成は以下の通り:

対象サーバ:

  • ルータ(Raspberry Pi): dnsmasq, iptables, WireGuard設定
  • Wi-Fi AP(Raspberry Pi): hostapd, dhcpcd設定
  • 開発サーバ: Docker環境(Prometheus等)

ディレクトリ構成:

ansible-backup/
├── ansible.cfg          # 基本設定
├── inventory/hosts      # サーバ一覧
├── playbooks/backup.yml # メインPlaybook
└── files/backup-script.sh # 実行スクリプト

実装したPlaybook例

inventory/hosts

[routers]
router-pi ansible_host=192.168.1.1 ansible_user=admin

[access_points]  
ap-pi ansible_host=192.168.1.10 ansible_user=admin

[dev_servers]
dev-server ansible_host=192.168.1.20 ansible_user=devuser

[all:vars]
ansible_ssh_common_args='-o StrictHostKeyChecking=no'
backup_date="{{ ansible_date_time.date }}"
backup_base_dir="/home/{{ ansible_user }}/backups"

playbooks/backup.yml(抜粋)

---
- name: Backup Router Config
  hosts: routers
  become: yes
  vars:
    config_files:
      - /etc/dnsmasq.conf
      - /etc/iptables/rules.v4
      - /etc/wireguard/wg0.conf
  tasks:
    - name: Create latest backup directory
      file:
        path: "{{ backup_base_dir }}/latest"
        state: directory
        mode: '0755'

    - name: Backup router config files to latest
      copy:
        src: "{{ item }}"
        dest: "{{ backup_base_dir }}/latest/"
        remote_src: yes
      register: router_backup_result
      loop: "{{ config_files }}"
      ignore_errors: yes

    - name: Check if router files changed
      set_fact:
        router_changed: "{{ router_backup_result.results | selectattr('changed', 'equalto', true) | list | length > 0 }}"

    - name: Create dated router backup if changed
      copy:
        src: "{{ backup_base_dir }}/latest/"
        dest: "{{ backup_base_dir }}/router-{{ backup_date }}/"
        remote_src: yes
      when: router_changed

調べた疑問点

バックアップ体制を設計する際に、特に次の点を検討する必要があると感じた:

  1. 同一内容のファイルを毎回バックアップするのは効率的か
  2. synchronize と copy の使い分けはどうすべきか
  3. 月1実行で十分な頻度なのか
  4. Discord通知にはどの程度の情報を含めるべきか
  5. systemd-timer と cron のどちらが適切か

差分検出による効率的なバックアップ戦略

今回実装したバックアップシステムでは、**「差分発生時のみスナップショット保存、同一内容は最新版のみ保持」**という方針を採用した。

従来のバックアップでは、毎回日付フォルダを作成していたため、

  • 同一内容でも毎回容量を消費
  • 古いバックアップの管理が煩雑
  • 変更履歴の把握が困難
    という問題があった。

今回の方式では、

  • latest/ フォルダに常に最新状態を保持
  • 変更検出時のみ日付フォルダに保存
  • 容量効率と変更履歴の両立
    が可能になった。

結果として ストレージ使用量を最適化しつつ、変更追跡ができる仕組みとなった。

特に効果が大きいのは以下のパターン:

  • 設定ファイル(変更頻度が低く、容量も小さい)
  • 定期実行バックアップ(毎日実行でも無駄な重複を避けられる)
  • 複数サーバ管理(サーバごとの変更タイミングが異なる)

Ansible の synchronize タスクが失敗する理由

当初、Prometheus ディレクトリのバックアップで synchronize モジュールを使用したが、rsync エラーで失敗した。

synchronize の問題点

  • rsync の同期方向が「ターゲットホスト → 制御ホスト」となる
  • Ansible の通常動作(制御ホスト → ターゲットホスト)と逆向き
  • SSH 接続の設定によってはパス解決が曖昧になる

これらの場合、synchronize は複雑になりがち。

copy モジュールの利点

  • remote_src: yes で同一ホスト内コピーが可能
  • 接続方向がシンプル
  • パス指定が直感的
  • エラー処理がわかりやすい

結果として、ファイルサイズが小さい設定ファイル群では copy の方が適している。

使い分けの指針

  • 小容量ファイル → copy + remote_src
  • 大容量・多数ファイル → synchronize(ただし接続設定を慎重に)
  • 外部サーバとの同期 → synchronize

systemd-timer による自動化のメリット

月1実行のバックアップ自動化では、cron より systemd-timer を選択した。

cron と比較した systemd-timer の利点:

  • ログ統合(journalctl で確認可能)
  • 依存関係管理(ネットワーク起動後に実行など)
  • 実行時刻のランダマイゼーション(負荷分散)
  • 失敗時の通知機能

設定のポイント

OnCalendar=monthly
Persistent=true
RandomizedDelaySec=600
  • monthly:毎月1日に実行
  • Persistent=true:システム停止中も実行予定を保持
  • RandomizedDelaySec=600:±10分のランダム遅延で負荷分散

これにより 運用負荷を下げつつ、確実な実行が保証される。


Discord 通知による運用可視化

バックアップ実行状況をDiscordで通知することで、運用状況の把握を自動化した。

通知内容は以下の3段階:

開始通知(青色)

  • 実行開始をリアルタイム通知
  • 長時間実行の場合の状況把握

成功通知(緑色)

  • 完了時刻
  • 変更ファイル数
  • 差分有無の判定結果

失敗通知(赤色)

  • エラーメッセージ
  • ログファイルの該当箇所

記事が強調している運用自動化の要点は、**「人手による確認作業の削減」**にある。

systemd-timer設定例

/etc/systemd/system/ansible-backup.service

[Unit]
Description=Ansible Backup Service
After=network.target

[Service]
Type=oneshot
User=devuser
ExecStart=/home/devuser/ansible-backup/files/backup-script.sh
WorkingDirectory=/home/devuser/ansible-backup
StandardOutput=journal
StandardError=journal

/etc/systemd/system/ansible-backup.timer

[Unit]
Description=Run Ansible Backup Monthly
Requires=ansible-backup.service

[Timer]
OnCalendar=monthly
Persistent=true
RandomizedDelaySec=600

[Install]
WantedBy=timers.target

バックアップ体制が現場判断で意味を持つポイント

今回構築したシステムを踏まえ、実務で考慮すべき点は次にまとめられる。

Ansible一元管理を使うべき状況

  • 複数サーバの設定管理
  • 手動バックアップが煩雑になった
  • 障害復旧の手順を標準化したい
  • 設定変更の履歴を追跡したい

差分検出バックアップが有効な状況

  • 変更頻度が低い設定ファイル群
  • ストレージ容量を節約したい
  • 変更タイミングの把握が重要
  • 定期実行で無駄を省きたい

systemd-timer が適切な状況

  • ログ統合が重要
  • 依存関係を明確にしたい
  • 負荷分散を考慮する必要がある
  • 現代的な Linux 環境

まとめ

今回のバックアップ体制構築では次の3点が特に有用であると感じた。

  • 差分検出による効率的なストレージ使用
  • Ansible による複数サーバの一元管理
  • systemd-timer + Discord通知による運用自動化

いずれも「手動運用の削減」や「障害時の迅速な復旧」という明確な価値があり、ホームネットワーク環境では十分な恩恵が得られる。


参考資料

  • Ansible 公式ドキュメント(synchronize, copy モジュール)
  • systemd.timer マニュアル
  • Discord Webhook API ドキュメント

Discussion