深夜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