ZFSのバックアップの設定
κeenです。一昨年ファイルシステムをbtrfsからZFSに移行したあとそういやバックアップの話を書いてなかったので書き残します。
前提として、デスクトップで使っているUbuntuで、ルートにZFSを使っています。
ここではバックアップを2系統に分けて考えます。
- 軽~中程度の破損
- 例: ファイルをうっかり削除してしまったので復元したい
- 重程度の破損
- 例: PCが燃えたので一から組み直すことになった
軽~中はZFSのスナップショットを、重はファイルを丸ごとクラウドに同期する戦略を取ります。 因みに私はRAID Zを組んでるのでディスク破損は想定してませんが、そうでない方はディスク破損も重に入ると思います。
スナップショット
軽~中程度の破損の対策です。 ZFSにスナップショットの仕組み自体はあるのですが、それを定期的に取ったり古いスナップショットを退役させたりするのは一手間かかるので管理ツールを導入します。簡素な仕組みで動くzfs-auto-snapshotというツールです。
インストールすると /etc/cron.{d,daily,hourly,monthly,weekly} にこんな感じの zfs-auto-snapshot というファイルが作られます(なかったらどこかにあるはずなのでコピーしてきて下さい)
#!/bin/sh
# Only call zfs-auto-snapshot if it's available
which zfs-auto-snapshot > /dev/null || exit 0
exec zfs-auto-snapshot --quiet --syslog --label=weekly --keep=8 -r bpool/BOOT rpool/ROOT rpool/USERDATA
あとは好みに応じて man zfs-auto-snapshot をみながら細かい設定を調整していきます。
/etc/cron.d/ は定期実行で有名ですね。それ以外の cron.weekly とかはそこにシェルスクリプトを置いておくと勝手に時次・日次・週次・月次でのそスクリプトを実行してくれます。 /etc/cron.d/ と違って冒頭の実行間隔指定がないので書きやすいですね。
↑のスクリプトは /etc/cron.weekly/ に置いてあるもので、週次のスナップショットを最大8つまで取る設定になっています。
因みに /etc/cron.d/ のものはこうなっています。
PATH="/usr/bin:/bin:/usr/local/sbin:/usr/sbin:/sbin"
*/15 * * * * root which zfs-auto-snapshot > /dev/null || exit 0 ; zfs-auto-snapshot --quiet --syslog --label=frequent --keep=4 -r bpool/BOOT rpool/ROOT rpool/USERDATA
15分に一回、最大4つまで取る設定になってます。1時間経ったら時次のスナップショットに引継ぎですね。
私はそんな感じで15分ごとを4つ、1時間ごとを24つ、1日ごとを7つ、1週間ごとを8つという設定にしています。デフォルトだと1月ごとを12つとかの設定もあるので長すぎるなと感じる人は調整して下さい。
撮ったスナップショットの一覧を取得するのは zfs list -t snapshot なので動作してるか確認したい人は活用して下さい。
正しく動くとこんな感じでファイルシステムに .zfs という隠し(というか ls -a に出てこない)ディレクトリが作られて、その中にスナップショットが見えるようになります。
$ ls ~/.zfs/snapshot
zfs-auto-snap_daily-2026-03-30-0106 zfs-auto-snap_hourly-2026-04-02-1217 zfs-auto-snap_hourly-2026-04-04-1417
zfs-auto-snap_daily-2026-03-31-0109 zfs-auto-snap_hourly-2026-04-02-1317 zfs-auto-snap_hourly-2026-04-04-1517
zfs-auto-snap_daily-2026-04-01-0029 zfs-auto-snap_hourly-2026-04-02-1417 zfs-auto-snap_hourly-2026-04-05-0317
zfs-auto-snap_daily-2026-04-02-0152 zfs-auto-snap_hourly-2026-04-02-1517 zfs-auto-snap_hourly-2026-04-05-0417
zfs-auto-snap_daily-2026-04-02-2237 zfs-auto-snap_hourly-2026-04-02-1617 zfs-auto-snap_hourly-2026-04-05-0517
zfs-auto-snap_daily-2026-04-04-1356 zfs-auto-snap_hourly-2026-04-02-2217 zfs-auto-snap_weekly-2026-02-02-0017
zfs-auto-snap_daily-2026-04-05-0303 zfs-auto-snap_hourly-2026-04-02-2317 zfs-auto-snap_weekly-2026-02-09-0336
zfs-auto-snap_frequent-2026-04-05-0515 zfs-auto-snap_hourly-2026-04-03-0017 zfs-auto-snap_weekly-2026-02-16-0120
zfs-auto-snap_frequent-2026-04-05-0530 zfs-auto-snap_hourly-2026-04-03-0117 zfs-auto-snap_weekly-2026-02-24-0329
zfs-auto-snap_frequent-2026-04-05-0545 zfs-auto-snap_hourly-2026-04-03-0217 zfs-auto-snap_weekly-2026-03-12-1308
zfs-auto-snap_frequent-2026-04-05-0600 zfs-auto-snap_hourly-2026-04-03-0317 zfs-auto-snap_weekly-2026-03-19-0158
zfs-auto-snap_hourly-2026-04-02-0817 zfs-auto-snap_hourly-2026-04-03-0417 zfs-auto-snap_weekly-2026-03-25-2337
zfs-auto-snap_hourly-2026-04-02-0917 zfs-auto-snap_hourly-2026-04-03-0517 zfs-auto-snap_weekly-2026-04-02-0251
zfs-auto-snap_hourly-2026-04-02-1017 zfs-auto-snap_hourly-2026-04-03-0617
zfs-auto-snap_hourly-2026-04-02-1117 zfs-auto-snap_hourly-2026-04-03-0717
それぞれがスナップショットされたツリーになっているので、普通に cat やら cp やらで簡単にファイルを取り出せます。
クラウド同期
重程度の破損の対策です。割り切ってホームディレクトリ以下を tar にまとめて圧縮してDropboxに放り込みます。ZFSのアーカイブ機能もありますが、復元するときもZFSじゃないといけないのでもっと可搬性のある tar を採用しました。
ZFSのスナップショットで静止点を取れるので最新のスナップショットをそのままtarにまとめれば済みますね。
そういうシェルスクリプトを書きました。
#!/bin/sh
# templated by http://qiita.com/blackenedgold/items/c9e60e089974392878c8
usage() {
cat <<HELP
NAME:
$0 -- backup home
SYNOPSIS:
$0 [-h|--help]
$0 [--verbose]
DESCRIPTION:
Backup home from the latest snapshot. It logs to $LOG_FILE
-h --help Print this help.
--verbose Enables verbose mode.
HELP
}
main() {
SCRIPT_DIR="$(cd $(dirname "$0"); pwd)"
while [ $# -gt 0 ]; do
case "$1" in
--help) usage; exit 0;;
--verbose) set -x; shift;;
--) shift; break;;
-*)
OPTIND=1
while getopts h OPT "$1"; do
case "$OPT" in
h) usage; exit 0;;
esac
done
shift
;;
*) break;;
esac
done
latest_snapshot="$(ls --color=never -t .zfs/snapshot | head -n1)"
echo "Taking backup of $latest_snapshot"
ls -l .zfs/snapshot | grep "$latest_snapshot"
mv -f Dropbox/backup/home.tar.xz Dropbox/backup/home.old.tar.xz || true
mv -f Dropbox/backup/home.tar.xz.sha1 Dropbox/backup/home.old.tar.xz.sha1 || true
nice tar cJvf Dropbox/backup/home.tar.xz \
--sparse \
-p --xattrs \
--exclude=./Dropbox \
--exclude=./.cache \
--exclude=./.steam \
-C ".zfs/snapshot/$latest_snapshot/" \
.
sha1sum Dropbox/backup/home.tar.xz > Dropbox/backup/home.tar.xz.sha1
}
set -e
cd $HOME
export PATH=/usr/bin:/usr/sbin
start_time="$(date +%s)"
main "$@"
end_time="$(date +%s)"
echo "$(($end_time - $start_time)) seconds"
date
バックアップの話題は何度かしてるので過去に登場したことがありますが、細かいアップデートがあります。ユーザのホームディレクトリをバックアップするのでユーザ権限のSystemdで動かすようにしたり、エラーハンドリングとかログとかもちょっとだけ増やしました。
あとはSystemdの設定です。毎週走るようにタイマーを設定しましょう。 ~/.config/systemd/user/backuphome.service に以下を置き、
[Unit]
Description="Backup home"
[Service]
ExecStart=/path/to/backup-home.sh
~/.config/systemd/user/backuphome.timer に以下を置きます。
[Unit]
Description="run backup-home weekly"
[Timer]
OnCalendar=weekly
Persistent=true
[Install]
WantedBy=timers.target
多分置いただけだと設定が反映されないのでリロードしときましょう。
$ systemctl --user daemon-reload
そしたら systemctl --user status backuphome.service や systemctl --user status backuphome.timer などで様子をみます。
$ systemctl --user status backuphome.service
● backuphome.service - "Backup home"
Loaded: loaded (/home/shun/.config/systemd/user/backuphome.service; linked; preset: enabled)
Active: active (running) since Sun 2026-04-05 15:18:06 JST; 29min ago
Invocation: 7cbd43ee1aa1487ebe6d75ac62f6491e
Main PID: 2455894 (backup-home.sh)
Tasks: 132 (limit: 303067)
Memory: 19.3G (peak: 19.3G)
CPU: 1d 39min 25.655s
CGroup: /user.slice/user-1000.slice/user@1000.service/app.slice/backuphome.service
$ systemctl --user status backuphome.timer
● backuphome.timer - "run backup-home weekly"
Loaded: loaded (/home/shun/.config/systemd/user/backuphome.timer; enabled; preset: enabled)
Active: active (waiting) since Sun 2026-04-05 16:22:21 JST; 2h 12min ago
Invocation: 00f1c20be510416eaff2802540f6825b
Trigger: Mon 2026-04-06 00:00:00 JST; 5h 25min left
Triggers: ● backuphome.service
4月 05 16:22:21 mini systemd[6953]: Started backuphome.timer - "run backup-home weekly".
設定したときの記憶が薄いので他にも操作が必要かもしれません。systemctl --user enable backuphome.timer とかを叩きましょう。 systemctl --user list-timers --all とかでタイマーが設定されていることを確認できればOKです。
ユーザモードでSystemdのタイマーを設定できれば毎週ユーザ権限でバックアップを走らせてくれます。パスとかファイルのownerとかの問題が解決して嬉しいですね。