この記事が想定している読者
サービスが少しずつ増えてきて、Docker Composeの定義ファイルや各種設定ファイルが複数サービス分たまってきた。そろそろバックアップを手順化したい。けれど現状は、別ディレクトリへの手コピーか、一度も復元を試していないスクリプトで止まっている――そういう状態の自宅運用者を想定しています。
このとき本当に怖いのは「バックアップを取り忘れること」よりも、「取ったつもりで、いざというときに復元できないこと」「世代を整理するつもりが必要なsnapshotまで消すこと」「暗号化パスワードやリポジトリ指定のミスで、非常時に手が止まること」です。
そこで本記事では、resticを採用すると決める前に、どの失敗条件まで確認しておくべきかを、使い捨てVM上の実コマンドと実出力で確認します。backupが成功したログではなく、復元できない条件と削除候補の見え方からresticの実用性を判断します。
比較:手動コピー / tar+gpg / restic
読者が自然に比べているのは、有償製品ではなく「いまの手段」と「次の手段」です。
| 観点 | 手動コピー | tar + gpg | restic |
|---|---|---|---|
| 暗号化 | なし(別途必要) | gpgで可能 | リポジトリ単位で標準装備 |
| 世代管理 | 自前で命名・管理 | 自前で命名・管理 | snapshotとforgetポリシーで管理 |
| 復元確認のしやすさ | cpで戻すだけだが検証は手作業 | tar展開+復号、検証は手作業 | restoreコマンドと差分照合で確認しやすい |
| 失敗ログの読みやすさ | OS依存、暗黙的に失敗しがち | gpg/tarのエラーが分散 | Fatalメッセージと終了コードが揃う |
| 重複排除 | なし | なし | ブロック単位で重複排除 |
手動コピーとtar+gpgが悪いわけではありません。ただ、世代管理と暗号化を一つのツールでまとめ、しかも「失敗したときに何が起きたか」をコマンド出力で読みやすいのはresticの利点です。本記事はその利点が、実際に失敗させたときに成立するかを確認します。
検証環境
- 環境: 使い捨ての一時VM(Docker利用可、apt導入が可能なレーン)
- restic: 0.14.0(go1.19.8 / linux/amd64)
- リポジトリ: VM内ローカルパスのみ(リモートrepoは未使用)
- 対象データ: ダミーの設定ファイル3点(compose.yml / app.env / readme.txt)
- 本番データ・本番リポジトリは一切使用していません。検証後にVM内データは削除しています。
resticは標準のDebian環境や軽量コンテナに最初から入っているとは限らないため、パッケージ導入から確認しています。以下のパスワードはすべて検証用のプレースホルダです。実運用では使い回さない、十分に強いパスフレーズを別管理してください。
実行ログ
1. 導入とバージョン確認
# apt-get update && apt-get install -y restic
# restic version
restic 0.14.0 compiled with go1.19.8 on linux/amd64
2. テスト用ダミーデータの準備
# mkdir -p /tmp/restic-lab/data /tmp/restic-lab/repo
# printf 'service: web\nimage: nginx:stable\n' > /tmp/restic-lab/data/compose.yml
# printf '設定項目=lab\nTOKEN=dummy\n' > /tmp/restic-lab/data/app.env
# printf 'home lab config note\n' > /tmp/restic-lab/data/readme.txt
# ls -l /tmp/restic-lab/data
total 12
-rw-r--r-- 1 root root 24 app.env
-rw-r--r-- 1 root root 33 compose.yml
-rw-r--r-- 1 root root 21 readme.txt
3. リポジトリの初期化(init)
# export 設定項目=/tmp/restic-lab/repo
# export 設定項目='example-passphrase'
# restic init
created restic repository 2602e69ea2 at /tmp/restic-lab/repo
Please note that knowledge of your password is required to access
the repository. Losing your password means that your data is
irrecoverably lost.
ここで表示される「パスワードを失うとデータは復旧できない」という警告は、暗号化バックアップの本質です。後述の誤パスワードの挙動と合わせて読んでください。
4. 正常なbackupとsnapshot確認
# restic backup /tmp/restic-lab/data
# restic snapshots
no parent snapshot found, will read all files
Files: 3 new, 0 changed, 0 unmodified
Dirs: 3 new, 0 changed, 0 unmodified
Added to the repository: 2.132 KiB (1.569 KiB stored)
processed 3 files, 78 B in 0:00
snapshot 6a78451a saved
ID Time Host Tags Paths
-----------------------------------------------------------------
6a78451a 2026-06-28 03:18:35 labhost /tmp/restic-lab/data
-----------------------------------------------------------------
1 snapshots
ここまでが「バックアップを取った」という状態です。多くの場合、ここで安心して終わります。本記事はここから先を見ます。
5. 誤パスワードでのアクセス失敗(終了コード1)
# 設定項目='wrong-passphrase' restic snapshots
Fatal: wrong password or no key found
終了コードは1でした。パスワードが違うと一覧すら取れず、Fatal: wrong password or no key found と明確に表示されます。非常時にこの表示を初めて見るより、平時に一度見ておくほうが落ち着いて対処できます。パスワードの管理が、復元可否そのものだと分かります。
6. 対象パス指定ミス時のbackup挙動(終了コード1)
# restic backup /tmp/restic-lab/does-not-exist
/tmp/restic-lab/does-not-exist does not exist, skipping
Fatal: all target directories/files do not exist
存在しないパスを指定すると、skipの行に続いて Fatal: all target directories/files do not exist で終了コード1になります。重要なのは、対象がすべて存在しないと止まる一方で、複数指定のうち一部だけ存在する場合はskipして進む可能性がある点です。「終了コードが0だったから全部取れている」と思い込まず、対象パスの綴りはbackup定義の時点で確認しておくべきです。
7. restoreと元ファイルの一致確認(終了コード0)
# mkdir -p /tmp/restic-lab/restore
# restic restore latest --target /tmp/restic-lab/restore
# diff -r /tmp/restic-lab/data /tmp/restic-lab/restore/tmp/restic-lab/data
restoring <Snapshot 6a78451a of [/tmp/restic-lab/data] at 2026-06-28 03:18:35 ...> to /tmp/restic-lab/restore
diff -r は差分を出力せず終了コード0でした。つまり復元したファイル群が元データと一致しています。snapshot一覧に行が見えることではなく、restore して diff が無言で返ることが「復元できる」の最小限の証拠です。restoreは元のパス構造を再現するため、--target 配下に元の絶対パスがぶら下がる点も確認しておくと、戻し先を間違えません。
8. 2世代目backupとforget –prune –dry-run
# printf 'second generation change\n' >> /tmp/restic-lab/data/readme.txt
# restic backup /tmp/restic-lab/data
# restic forget --keep-last 1 --prune --dry-run
using parent snapshot 6a78451a
Files: 0 new, 1 changed, 2 unmodified
Dirs: 0 new, 3 changed, 0 unmodified
Added to the repository: 2.098 KiB (1.393 KiB stored)
processed 3 files, 103 B in 0:00
snapshot 8f30adcf saved
Applying Policy: keep 1 latest snapshots
keep 1 snapshots:
ID Time Host Tags Reasons Paths
--------------------------------------------------------------------------
8f30adcf 2026-06-28 03:18:39 labhost last snapshot /tmp/restic-lab/data
--------------------------------------------------------------------------
1 snapshots
remove 1 snapshots:
ID Time Host Tags Paths
-----------------------------------------------------------------
6a78451a 2026-06-28 03:18:35 labhost /tmp/restic-lab/data
-----------------------------------------------------------------
1 snapshots
Would have removed the following snapshots:
{6a78451a}
to repack: 3 blobs / 360 B
this removes: 1 blobs / 62 B
to delete: 4 blobs / 1.093 KiB
total prune: 5 blobs / 1.153 KiB
remaining: 7 blobs / 1.328 KiB
--dry-run を付けているので、keep 1 と remove 1、そして Would have removed the following snapshots: {6a78451a} という形で「消える予定」が表示されるだけで、実際の削除は行われません。確認のため一覧を取り直すと、1世代目(6a78451a)も2世代目(8f30adcf)も残っていました。
forget --prune は世代を実際に消す操作です。最初から本番で実行せず、まず --dry-run で「何が消えて、何が残るか」を読んでから外す。これが世代削除で消しすぎないための最も簡単な歯止めです。
9. 整合性check(終了コード0)
# restic check
using temporary cache in /tmp/restic-check-cache-設定項目
create exclusive lock for repository
load indexes
check all packs
check snapshots, trees and blobs
[0:00] 100.00% 2 / 2 snapshots
no errors were found
restic check はリポジトリの構造的な整合性を確認し、no errors were found を返しました。ただしこれは「メタデータと構造に問題がない」ことの確認であり、各データブロックを実際に読み直す検証は別オプションです(後述)。
10. 検証データのクリーンアップ
# rm -rf /tmp/restic-lab
# ls -ld /tmp/restic-lab
ls: cannot access '/tmp/restic-lab': No such file or directory
使い捨てVM内の検証データは削除済みです。
結果のまとめ
- init / backup / restore / check はいずれも終了コード0で成功し、restore後の差分照合も一致しました。
- 誤パスワードと対象パスミスはどちらも終了コード1で停止し、
Fatal:行で原因が読み取れました。 forget --keep-last 1 --prune --dry-runは削除候補を提示するだけで、実際の世代は残りました。
つまり、resticは「失敗したときに何が起きたか」が読みやすく、復元確認と世代整理を安全に試せるツールだと、今回の範囲では確認できました。
失敗・制約・再現条件
- 今回はVM内ローカルパスのリポジトリのみで、リモートリポジトリ(SFTPやオブジェクトストレージ等)の挙動は未検証です。
- retentionポリシー(
--keep-daily/--keep-weeklyなどの組み合わせ設計)は1世代の単純例にとどめており、長期運用向けの設計は別途必要です。 restic checkは実行しましたが、データブロックを読み直すcheck --read-data系の検証は今回行っていません。整合性の確認レベルとしては最小限です。- パスワードを失うと復元不能です(init時の警告どおり)。パスワード管理そのものがバックアップ戦略の一部になります。
- 再現方法: apt導入が可能な使い捨てVM上で、ローカルパスのリポジトリと小さなダミーディレクトリを用意し、本記事のコマンドを同順で実行してください。
結論:採用前に試すべき失敗条件
読者の決定すべきことは「resticを採用する前に、どの失敗まで確認しておくか」でした。今回の検証から言えるのは次のとおりです。
採用に踏み出してよい条件:
- 誤パスワード時に一覧すら取れないこと(
Fatal: wrong password or no key found)を自分の目で確認できた。 restoreしてdiffが無言で返る、つまり一致を確認できた。forget --pruneを--dry-run付きで先に試し、消える候補を読めるようになった。
もう少し様子を見たほうがよい条件:
- パスワードを安全に保管・引き継ぐ方法がまだ決まっていない。
- リモート保存や長期のretention設計が必要なのに、その検証をしていない。
backupが成功したログは、安全の証明にはなりません。復元できない条件を先に試し、削除候補をdry-runで読む――この順序を一度通しておくことが、resticを家庭ラボに迎える前の最低限の準備です。
この検証を回している環境
この検証は、自宅の常設ラボ(使い捨てVM/LXCを回す母艦+GPU+VLAN分離ネットワーク)で動かしています。使っている機材と選定理由、全体構成は1本にまとめています。
ラボ構成のまとめを見る →