tmytのらくがき

個人の日記レベルです

今話題のMastodonインスタンスを建ててS3の代わりにAzure Blob Storageを使う

Pixivとかドワンゴインスタンスを建てて話題沸騰のMastodonですけど、僕もAzure IaaS上にインスタンスを建ててみてました。 Docker Composeでさくっと作っただけだったのを、画像アップロード先をAzure Blobにするとかしてちょっとカスタムしたりもしたのでそのお話です。

Azure Blobにする

Mastodonは標準でAmazon S3に対応してるので、S3使う人はそのまま使えばなんとなくうまくいきます。でもAzure IaaSに建てたしせっかくなのでBlob使います。

Azure BlobをS3のAPIでアクセスするには s3proxy っての使えばどうにかなります。Java製。

github.com

docker-compose.ymlにs3proxy追加しました。

diff --git a/docker-compose.yml b/docker-compose.yml
index 81c6fe9..d953d44 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -15,6 +15,11 @@ services:
 #    volumes:
 #      - ./redis:/data

+  s3proxy:
+    restart: always
+    image: andrewgaul/s3proxy
+    env_file: .env.production
+
   web:
     restart: always
     build: .
@@ -26,6 +31,7 @@ services:
     depends_on:
       - db
       - redis
+      - s3proxy
     volumes:
       - ./public/assets:/mastodon/public/assets
       - ./public/system:/mastodon/public/system

そして、.env.productionにS3といいつつAzure Blobにアクセスするように設定します。します。

 # S3 (optional)
-# S3_ENABLED=true
-# S3_BUCKET=
-# AWS_ACCESS_KEY_ID=
-# AWS_SECRET_ACCESS_KEY=
-# S3_REGION=
-# S3_PROTOCOL=http
-# S3_HOSTNAME=192.168.1.123:9000
+S3_ENABLED=true
+S3_BUCKET=uploads
+AWS_ACCESS_KEY_ID=local-identity
+AWS_SECRET_ACCESS_KEY=local-credential
+S3_PROTOCOL=https
+S3_HOSTNAME=***.blob.core.windows.net
+S3_ENDPOINT=http://s3proxy/
+S3_PERMISSION=private

それに加えて、s3proxyの設定も書きます。。

+S3PROXY_AUTHORIZATION=none
+S3PROXY_CORS_ALLOW_ALL=true
+JCLOUDS_PROVIDER=azureblob
+JCLOUDS_ENDPOINT=https://***.blob.core.windows.net/
+JCLOUDS_IDENTITY=***
+JCLOUDS_CREDENTIAL=****************************************

だいたいこれでいいはずなんですけど、このまま動かすとs3proxyから501 Not Implementedエラーが帰ってくるのです。なんか、調べたところによると、X-Amz-Aclヘッダにpublic-readが指定されてるとなんかよくわかんないけどAzure Blob宛てだと501 Not Implementedになるみたいです。

で、このパラメータなんですけど、config/initializers/paperclip.rbpublic-readに決め打ちされてて非常に困るので適当にパッチします。

diff --git a/config/initializers/paperclip.rb b/config/initializers/paperclip.rb
index 77bc13b..6fab071 100644
--- a/config/initializers/paperclip.rb
+++ b/config/initializers/paperclip.rb
@@ -16,7 +16,7 @@ if ENV['S3_ENABLED'] == 'true'
   Paperclip::Attachment.default_options[:s3_host_name]   = ENV.fetch('S3_HOSTNAME') { "s3-#{ENV.fetch('S3_REGION')}.amazonaws.com" }
   Paperclip::Attachment.default_options[:path]           = '/:class/:attachment/:id_partition/:style/:filename'
   Paperclip::Attachment.default_options[:s3_headers]     = { 'Cache-Control' => 'max-age=315576000' }
-  Paperclip::Attachment.default_options[:s3_permissions] = 'public-read'
+  Paperclip::Attachment.default_options[:s3_permissions] = ENV.fetch('S3_PERMISSION') { 'public-read' }
   Paperclip::Attachment.default_options[:s3_region]      = ENV.fetch('S3_REGION') { 'us-east-1' }

これでdocker-compose buildしてdocker-compose up -d するといい感じになりました。