Open6

MastodonのメディアをCloudflare R2に移行する

rkunkunrrkunkunr

手順をまとめる

  1. tootctl media removeを走らせる
  2. R2に既存のファイル達(~/live/public/system)をアップロードする
  3. メンテとしてMastodonを落とす
  4. nginx設定を入れる
  5. .env.productionの設定と、もう一度R2にファイルを手動アップロードする
  6. いろいろ確認して、問題なければ終了
rkunkunrrkunkunr
[75dbe464-24a3-4b99-97cd-045efae0cd83]   TRANSACTION (0.3ms)  BEGIN
[75dbe464-24a3-4b99-97cd-045efae0cd83]   MediaAttachment Create (3.0ms)  INSERT INTO "media_attachments" ("file_file_name", "file_content_type", "file_file_size", "file_updated_at", "created_at", "updated_at", "file_meta", "account_id", "blurhash", "processing", "file_storage_schema_version") VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11) RETURNING "id"  [["file_file_name", "9ec56930055ec
bdb.png"], ["file_content_type", "image/png"], ["file_file_size", 499846], ["file_updated_at", "2022-11-16 11:37:45.615981"], ["created_at", "2022-11-16 11:37:46.816710"], ["updated_at", "2022-11-16 11:37:46.816710"], ["file_meta", "{\"original\":{\"width\":1200,\"height\":1200,\"size\":\"1200x1200\",\"aspect\":1.0},\"small\":{\"width\":480,\"height\":480,\"size\":\"480x480\",\"aspect\":1.0}}"],
 ["account_id", 107343998598766453], ["blurhash", "UTOD^EJ;~V=^Tf0L%0?Frp%0t7R-v{$yXTXU"], ["processing", 2], ["file_storage_schema_version", 1]]
[75dbe464-24a3-4b99-97cd-045efae0cd83] [paperclip] saving media_attachments/files/109/353/282/228/610/586/original/9ec56930055ecbdb.png
[75dbe464-24a3-4b99-97cd-045efae0cd83] [httplog] PUT http://~~~ACCOUNT_ID~~~.r2.cloudflarestorage.com:443/~~~BUCKET_NAME~~~/media_attachments/files/109/353/282/228/610/586/original/9ec56930055ecbdb.png completed with status code 501 in 0.032587 seconds
[75dbe464-24a3-4b99-97cd-045efae0cd83]   TRANSACTION (0.9ms)  ROLLBACK
[75dbe464-24a3-4b99-97cd-045efae0cd83] method=POST path=/api/v2/media format=html controller=Api::V2::MediaController action=create status=500 error='Aws::S3::Errors::NotImplemented: Header 'x-amz-acl' with value 'public-read' not implemented' duration=1329.86 view=0.00 db=7.64
[75dbe464-24a3-4b99-97cd-045efae0cd83]
[75dbe464-24a3-4b99-97cd-045efae0cd83] Aws::S3::Errors::NotImplemented (Header 'x-amz-acl' with value 'public-read' not implemented):
[75dbe464-24a3-4b99-97cd-045efae0cd83]
[75dbe464-24a3-4b99-97cd-045efae0cd83] lib/paperclip/attachment_extensions.rb:87:in `block in save'
[75dbe464-24a3-4b99-97cd-045efae0cd83] lib/paperclip/attachment_extensions.rb:93:in `save'
[75dbe464-24a3-4b99-97cd-045efae0cd83] app/controllers/api/v2/media_controller.rb:5:in `create'
[75dbe464-24a3-4b99-97cd-045efae0cd83] app/controllers/concerns/localized.rb:11:in `set_locale'
[75dbe464-24a3-4b99-97cd-045efae0cd83] lib/mastodon/rack_middleware.rb:9:in `call'

というふうに怒られてしまった...
[75dbe464-24a3-4b99-97cd-045efae0cd83] Aws::S3::Errors::NotImplemented (Header 'x-amz-acl' with value 'public-read' not implemented):
と書いてある。

rkunkunrrkunkunr

https://developers.cloudflare.com/r2/data-access/s3-api/api/#implemented-object-level-operations

このページの下部、Implemented object-level operations内PutObjectの中で、ACLのAPIは対応していない、との記述が。。。

アップロード時に権限を設定するAPIっぽいが、これに対応していない事によってMastodonでCloudflare R2を使うのはムリみたいだ...

PaperClipの設定をこねれば出来ないことも無いのでは?と思ったので、後で見てみる。

rkunkunrrkunkunr

やり方がわかりました!
エラー的に、x-amz-aclヘッダーに何も指定しなければ問題なく使えそうだなと思い、mastodonの実装を漁ってきました。

https://github.com/mastodon/mastodon/blob/main/config/initializers/paperclip.rb#L71-L73
Mastodonがメディアファイルの保存に利用しているPaperClipの設定を見ていますと、S3_PERMISSIONに何も指定していない場合にx-amz-acl: public-readヘッダがつくようです。
ということは、S3_PERMISSIONに空文字を指定すればヘッダを消すことができる!ということで、実際に試してみました。

https://mstdn.rkunkunr.com/@rkun/109353794795158039

出来た!!

rkunkunrrkunkunr

最終的に利用した.env.production(抜粋)の設定を上げておきます。

# For Cloudflare R2

S3_ENABLED=true
S3_BUCKET=$BUCKET_NAME
AWS_ACCESS_KEY_ID=$AWS_ACCESS_KEY_ID
AWS_SECRET_ACCESS_KEY=$AWS_SECRET_ACCESS_KEY
S3_REGION=auto
S3_PROTOCOL=https
S3_HOSTNAME=$CLOUDFLARE_ACCOUNT_ID.r2.cloudflarestorage.com
S3_ENDPOINT=https://$CLOUDFLARE_ACCOUNT_ID.r2.cloudflarestorage.com
S3_PERMISSION=
S3_ALIAS_HOST=${ALIAS_HOST}