【実録】Raspberry PiでTime Machineサーバー構築に挑み、LUKS暗号化NASに行き着いた深夜の死闘

【実録】Raspberry PiでTime Machineサーバー構築に挑み、LUKS暗号化NASに行き着いた深夜の死闘

深夜1時に目が覚めて、なんとなく一時間で終わるだろうと思って、Raspberry Piと8TBのHDDを引っ張り出してネットワークTime Machineサーバーの構築を始めた。
しかし、待っていたのはAppleの理不尽な仕様と、Linuxのシビアな洗礼だった。

第一章:SambaとApple拡張(fruit)の厳しすぎる壁

最初は定石通り、Samba(smbd)を立てて設定ファイルにいそいそと vfs objects = fruit を追記した。
しかし、MacのTime Machine設定画面から「バックアップディスク」として一向に認識されない。

原因を探るべく、testparm -s で構文チェックを行って重複を潰し、Avahi(Bonjour)の設定を調整。
Mac側のターミナルからパケットレベルで広報が届いているか確認する。

dns-sd -B _adisk._tcp

結果は完璧。backup という名前のTime Machineサーバーとして、ネットワーク上で見事に検出できていた。

よし寝よう!

と思ったのも束の間、いざバックアップを開始すると、仮想ディスク(Sparsebundle)の作成フェーズでMacがSambaを拒絶する。

マジかと、Macのローカルで hdiutil を使って手動で器(Sparsebundle)を作成し、ラズパイに送り込むという荒業を試みたが、そのファイルを華麗に回避。

第二章:ブラックボックスを捨て、透明性を取る

時刻は午前3時。ここで天才エンジニアとしての無慈悲な判断を下す。

「そもそも、中身がブラックボックスで、一度壊れると復旧不可能な Sparsebundle に大切なデータを預けて良いのか?」

代わりに、何が起きているかすべて可視化でき、LinuxやAndroidなど他の端末からも直接ファイルを引っこ抜ける ファイルベースのバックアップ(rsync / restic 等)にすることにした。

ただし、NASとしてネットワークに晒す以上、物理的なセキュリティは担保したい。
そこで、8TBのHDDを LUKS(Linux Unified Key Setup) で丸ごと暗号化することにした。
これなら物理的にHDDを引っこ抜かれても安全。

第三章:LUKS暗号化と、恐怖の「Unknown host」

Sambaを止め、先ほどまでのTime Machineの残骸ごとHDDをフォーマットする。

sudo cryptsetup luksFormat /dev/sda1
sudo cryptsetup open /dev/sda1 backup_crypt
sudo mkfs.ext4 /dev/mapper/backup_crypt

再起動のたびにパスワードを手入力するのはサーバーとして致命的なので、/root/keys/backup.key を作成し、自動マウントの設定を仕込んだ。
ラズパイとセットで盗まれてラズパイにコンソールから接続したら中身は見えるけど、どんだけ盗まれとるんやっていう話なんで、そこはさすがにいいかなと思って。

/etc/crypttab にUUIDと鍵を登録し、/etc/fstab にマウントポイントを追記。

/dev/mapper/backup_crypt /mnt/backup ext4 defaults,noatime 0 2

よし、これで再起動だ……あ、あれ……。
Macから ping backup.local を打つと、目を疑うエラーが返ってきた。

ping: cannot resolve backup.local: Unknown host

第四章:Emergency Modeからの生還

終わったンゴ。
Linuxは、/etc/fstab に書かれたディスクのマウントに失敗すると、ネットワークすら立ち上がらない Emergency Mode で停止してしまう。
SSHでの遠隔操作も不可能になった。ラズパイがただの光る箱になった瞬間ンゴ。

俺はスーパーミニマリストなので、外付けキーボードもマウスも持っているけど、そんなものは最終手段として倉庫の奥底に眠らせているのだ。
こんな寒い早朝に取りに行きたくない。

幸い、手元には別の自宅データ監視用のモンスターラズパイ(正常系)があった。
起動しなくなったSDカードを抜き、USBリーダーでもう一台のラズパイに接続して、直接ファイルを書き換える。
こういう時SDカードが簡単に抜けるのはいいことよね。
ちなみに正常系ラズパイはSSDに換装しているので、こんな気軽にはできない。

sudo mount /dev/sda2 /mnt/rescue
sudo vi /mnt/rescue/etc/fstab

sda2になってるのは、正常系ラズパイがSSD換装してるから。
マウントポイントを作らずに mount しようとしてコケるという深夜特有のミスを挟みつつも、fstab に問題の行をコメントアウトして救出成功。

修正後は以下のように nofail を付けておいた。

/dev/mapper/backup_crypt /mnt/backup ext4 defaults,noatime,nofail 0 2

これをつけておけば、万が一HDDの解錠に失敗したりUSBの接触不良が起きても、システムは止まらずに起動する。
SSHでログインして落ち着いて原因究明ができるのだ。

結末:朝焼けと暗号化要塞

再度SDカードを戻して起動。
今度は無事にSSHが繋がり、lsblk コマンドが美しい階層構造を映し出した。

sda
`-sda1
  `-backup_crypt (crypt) /mnt/backup

物理層、暗号化層、マウント層が完璧に連携している。
最後にダミーファイルを作成し、アンマウントしてファイルが消えること(=確実に物理HDDに書き込まれていること)を証明して、すべての作業が完了した。

TimeMachine使うつもりだったけど、結局rsyncになってしまった。
rsyncは便利だけどcronを自分で設定して、失敗と成功の管理が必要なのでOSレベルで動いてくれるTimeMachineに乗っかりたかったんだけどね。

まあ先日のGoogle Takeoutのバックアップ先サーバーとしては活躍してもらうので良いと思う。
常時起動していることに意味があるかはわからないけど、少なくとも毎度付け外したりするより自動マウントされているNASのほうがバックアップの精神的ハードル下がりますしね。

TimeMachineが疲れうと思って、試行錯誤した結果朝の6時になってしまったw