GitLab.comでバックアップが機能してなかった事件の話を見て、まあよくある話だよね、と思ったんだ。実際に私の人生においても、周囲にいるベテランのエンジニアが機能しないバックアップによってデータロストをする、という経験が複数回あるんだよね。自分はさすがにそういうポカはやってなくて、それはそもそもバックアップしてなかったからだ、という…基本、手で作ったファイルは全部リポジトリかクラウドサービスに入れるようにしてるからね。
そんな私が、その「リポジトリに入れる」ために自宅内gitサーバとしてgogsをRaspberryPiで動かしているんだけど、gogsはgogs backupというコマンド一発でバックアップすることができる。しかし当然のようにgogs restoreコマンドはない。まあその辺はいざとなったら自分で何とかできるだろう。いつの間にかgogs importコマンドができていた。これでいけるのかな? 試してないけど。
で、リポジトリを作るたびにwebhookを設定して、pushされた時にバックアップが走るように設定してあるわけだけど、そうやって取ったバックアップはgpg -c(共有鍵)で暗号化してS3に送っているんです。共有鍵はパスワード管理ソフトとかに入れてある長いやつ。これだけ見ると玄人でしょ。
しかし、落とし穴はあった。
何かっていうと、webhookを実行しているデーモンとgogsのデーモンは別のユーザで動いていて、gogs dumpはカレントディレクトリにバックアップファイルを作るので、
cd /tmp sudo sudo -u gogsuser /path/to/gogs dump -c /path/to/gogs/custom/conf/app.ini
みたいな感じのコマンドになっているわけだ。そして、gogsは/path/to/gogsディレクトリをカレントディレクトリにして動いているので、app.iniのDB(sqlite)の設定は相対パスになっている。
[database] PATH = data/gogs.db
これで何が起きるかっていうと、gogs dumpのcwdは/tmpで動いているわけだから、/tmp/data/gogs.dbをダンプしようとして失敗し、DBのダンプが取れていないという…実際に見てみると、最初のコメントの60バイトくらいしかgogs-db.sqlファイルができていなかった。ていうかそういう時はgogs dumpが失敗して欲しいんだけどな…
結局、app.iniのdatabase.PATHをフルパスで書くようにして解決した。衝撃に弱いのにケースを買わずに裸のまま運用されているRaspberryPi…ちっぽけなSDカードに託してしまっていたデータ…まあリポジトリは救えるんだろうけど、DB部分は全部飛んでてもおかしくなかったな。
このエントリを読んだエンジニアがバックアップからのリストアに成功しますように。私には今回のGitLab.comの事件によるアラートは、自分のバックアップを確認するきっかけになってくれて、ありがたかったです。
まあでも、まだリストアのやり方は試せていないんですけどねw