Misskeyのfilesフォルダーをオブジェクトストレージに移行した話 From Misskey (2) Advent Calendar 2023

この記事はMisskey (2) Advent Calender 2023の掲載記事です。

始めに

おはこんばんにちは、「Misskey.art」を運営しているc30です。
今回は「Misskeyのfilesフォルダーをオブジェクトストレージに移行した」という話題で記事を書いていこうと思います。

※例として、ここではCloudflare R2を使用します。
※オブジェクトストレージを勧める前提で記事を書いています。
Misskey v2023.11.1を使用しているため情報が不十分な場合があります。

どうしてこの記事を作ろうと思ったのか

Misskey.artのファイルをオブジェクトストレージに移行してるときに思いついたからです。

本題

Misskeyのサーバーを運営している人なら一度は経験をしているのではないでしようか、サーバーを建てたときにオプジェクトストレージの存在を知らすに建ててしまったこと。

...え、無い?
私はありますよ、えぇ、オプジェクトストレージの存在知らなかったんですもの
容量がカツカツになり始めたときに存在を知ったので...

必要な物

  • オブジェクトストレージ(サービスはS3が対応していれば多分なんでも良いです)
  • rclone - 元々のファイルをオブジェクトストレージに移動するときに使います
  • 事前にオブジェクトストレージに変更したMisskeyサーバー

Cloudflare R2の準備

これは、常に使用している人はスキップしても大丈夫です。

バケツを用意する

  1. Cloudflareにアクセスし、R2をクリックします。
  2. 初めて使用する場合、クレジットカードまたはPayPalの登録が必要になります。
    支払い情報を入力してAdd R2 subscription to my accountをクリックします。

  3. Create Bucketをクリックします。
  4. Bucket nameに任意の名前を入力し、Create Bucketをクリックします。
  5. バケツが鉄8個で作れました。

バケツを自分のドメインに紐付ける

  1. Settingsに移動します。
  2. Connect Domainをクリックします。
  3. Domainfiles.<ドメイン>を入力し、Continueをクリックします。(CloudflareにDNSを設定していないと、ドメインは使用できません。)
  4. Connect domainをクリックします。

オブジェクトストレージのAccess Key IDとSecret Access Keyを取得する

  1. Cloudflareにアクセスし、R2をクリックします。
  2. Manage R2 API Tokensをクリックします。
  3. Create API tokenをクリックします。
  4. Token nameに任意の名前を入力します。
  5. PermissionsObject Read & Write: Allows the ability to read, write, and list objects in specific buckets.を選択します。
  6. Specify bucket(s)は、Apply to specific buckets onlyに選択し、対象のMisskeyのbucketを選択します。
  7. Create API tokenをクリックします。
  8. R2 Token was successfully createdと出たら、Use the following credentials for S3 clients:Access Key IDSecret Access Keyをコピーし、メモしておきます。
  9. Finishをクリックし、作業は完了です。

Misskeyにバケツを設定する

これも、常に設定している人はスキップしても大丈夫です。

  1. 運営しているMisskeyのサーバーにアクセスし、コントロールパネルをクリックします。
  2. オブジェクトストレージをクリックします。
  3. オブジェクトストレージを使用するをオンにします。
    Base URLに設定したドメイン + /filesを書きます。
    Bucketに設定したバケットの名前を設定します。
    Prefixfilesを入力します。
    Endpoint<R2ページのAccount ID>.r2.cloudflarestorage.comを入力します。
    Regionus-east-1を入力します。
    Access keyオブジェクトストレージのAccess Key IDとSecret Access Keyを取得するで取得したAccess Key IDをペーストします。
    Secret keyオブジェクトストレージのAccess Key IDとSecret Access Keyを取得するで取得したSecret Access Keyをペーストします。
    下にあるスイッチをすべてオンにします。
  4. 保存を押し、画像をアップロードして出来たら完了です。

rcloneでファイルをオブジェクトストレージにアップロードする

オブジェクトストレージにファイルをアップロードするためにrcloneのセットアップをします。
実際に設定する際は使用する各サービスの画面と見比べていい感じに読み替えてください。おそらくどのサービスも基本は似たようなことが書いてあると思います。

rcloneのインストール

Linuxの場合、こちらのコマンドでインストールが可能です。
sudo -v ; curl https://rclone.org/install.sh | sudo bash

rcloneを設定する

インストールが出来たら、rclone configで設定をします。

  1. 新しく追加するため、nを選択します。
  2. name> にリモートにつけたい名前を書きます。
  3. Storage> 5と入力します。
  4. provider> 6と入力します。
  5. env_auth> 1と入力します。
  6. access_key_id> オブジェクトストレージのAccess Key IDとSecret Access Keyを取得するで取得したAccess Key IDをペーストします。
  7. secret_access_key> オブジェクトストレージのAccess Key IDとSecret Access Keyを取得するで取得したSecret Access Keyをペーストします。
  8. region> 1と入力します。
  9. endpoint> <R2ページのAccount ID>.r2.cloudflarestorage.comを入力します。
  10. Edit advanced config?と聞かれるのでnを入力します。
  11. Keep this "remote" remote?と聞かれるので、設定を間違えてないか確認し、yを入力します。
  12. qを入力し、rclone configから抜けます。

rcloneでオブジェクトストレージにファイルをアップロードする

sudo su - misskey;
cd misskey;
rclone copy --metadata --progress files/ <rcloneを設定するで決めた名前>:<bucketの名前>/files; # /filesをつけてるのは、移行する際に分かりやすくするためです。

次の作業に移る前に、データベースのバックアップを忘れずに

sudo su - postgres;
pg_dumpall -f backup.sql; # バックアップ用コマンド
psql -f backup.sql; # バックアップ復旧用コマンド

頭を脳筋にしてsql文をpostgresqlに叩きまくる

これはデータベースをまさぐって使用したコードです。

update emoji             set "originalUrl"  = replace("originalUrl",  '<変更前のURL>', '<変更後のURL>');
update emoji             set "publicUrl"    = replace("publicUrl",    '<変更前のURL>', '<変更後のURL>');
update drive_file        set "thumbnailUrl" = replace("thumbnailUrl", '<変更前のURL>', '<変更後のURL>'); 
update drive_file        set url            = replace(url,            '<変更前のURL>', '<変更後のURL>'); 
update "user"            set "avatarUrl"    = replace("avatarUrl",    '<変更前のURL>', '<変更後のURL>'); --ここはURLの変換が違うので注意
update "user"            set "bannerUrl"    = replace("bannerUrl",    '<変更前のURL>', '<変更後のURL>'); 
update role              set "iconUrl"      = replace("iconUrl",      '<変更前のURL>', '<変更後のURL>'); 
update announcement      set "imageUrl"     = replace("imageUrl",     '<変更前のURL>', '<変更後のURL>'); 
update avatar_decoration set url            = replace(url,            '<変更前のURL>', '<変更後のURL>');

解説

<変更前のURL>https://<サーバーのURL>/files/になります。
<変更後のURL>https://files.<サーバーのURL>/files/になります。

ここで注意なのが、avatarUrlだけURLエンコードされたものになっています。
<変更前のURL>https%3A%2F%2F<サーバーのURL>%2Ffiles%2Fになります。
<変更後のURL>https%3A%2F%2Ffiles.<サーバーのURL>%2Ffiles%2Fになります。

置き換えた後に、データベースの変更作業に移ります。

sudo su - postgres;
psql;
\c misskey;
# <URL置き換え後のsql文を書いていく>
\q

これでMisskeyのサーバーを再起動、キャッシュのクリアなどをしてちゃんとファイルが表示されたら完了です。

最後に

初めてこういう記事を書いたので、読みづらいところがあったりすると思います。
この記事を読んで誰かの助けになれたら良いな、と思っています。
読んでくださりありがとうございました。