Takanory Blog

ITだったりそれ以外だったりを気ままに書いていきます

Mastodon の画像などメディアデータをAmazon S3に移行する(非Docker環境)

各所で話題のMastodon。私もAWS上に自分でインスタンスを立てて、おひとり様インスタンスとして運用しています。

デフォルトでは、Mastodonのアカウント画像やTootの画像や動画などメディアデータはフォローしたユーザーが存在するサーバーのローカルに保存されています。しかし、フォロー数が増えてくると、メディアデータの容量もどんどん増えて、サーバーのストレージを圧迫していきます。

Mastodonには、メディアデータをAmazon S3(S3互換のストレージも可)に保存し、参照させる機能があります。容量が増えてしまう前に、ということで、サーバーのローカルストレージからS3に移行しました。

 

 

Amazon S3にメディアデータを置くメリット

S3にデータを置くメリットはこのあたりでしょう。(耐久性に関しては、おひとり様の場合はあまり気にしなくてもいいかもですが)

  • スケーラビリティ:ストレージの圧迫に伴う容量追加が不要
  • 費用:EBSに比べると、S3の方が費用が安い(5分の1近く)
  • 耐久性:EBSよりもSLAが高く、バックアップも手軽に可能

 

移行の流れ

  1. S3バケットの作成
  2. S3バケットの権限設定
  3. MastodonのS3機能設定
  4. データ移行

 

S3バケットの作成

 まずは、データの保存先となるS3バケットを作成します。基本的にマニュアル通りで大丈夫です。

 参考: S3 バケットを作成する方法 - Amazon Simple Storage Service

  

 1. AWSマネジメントコンソールにログインして、S3コンソールにアクセスします。
 2. 「バケットを作成する」ボタンを押して、作成を開始します。
 3. バケット名とリージョンを入力します。

  •  バケット名:他のアカウントも含めてS3全体で一意にする必要があります。あとで変更できないので、注意します。
  • リージョン:適切に設定します。私はサーバーと同じリージョンにしています。

 4. プロパティはそのままでも大丈夫です。*1
 5. アクセス許可の設定もそのままで大丈夫です。外部からアクセスするための設定は後でおこないます。

 6. 設定を確認して、「バケットを作成」を押して作成を実行します。

 

S3バケットの権限設定

 S3バケットの権限設定は大きく2種類。(1)Mastodonからデータを書き込むためのユーザーと権限の作成、(2)データを公開するための権限の設定、です。

 

Mastodonからデータを書き込むためのユーザー作成と権限設定

実はいくつかの方法がありますが、今回はAWS推奨の「IAMグループにS3へのフルアクセス権限を付けて、そのグループにIAMユーザーを登録する」形にします。

 参考: IAM のベストプラクティス - AWS Identity and Access Management

 

 1-1. AWSマネジメントコンソールからIdentity and Access Management (IAM) にアクセスします。

 1-2. 左ペインの「グループ」→「新しいグループの作成」を選択します。

 1-3. グループ名を設定します。今回は「S3FullAccess」としておきます。

f:id:takanory42:20170510000247p:plain

 1-4. 許可設定のポリシーから「AmazonS3FullAccess」を選択します。上のフィルター欄に「s3」などと入力すると探しやすいです。

f:id:takanory42:20170510000356p:plain

 1-5. 確認して、「グループの作成」ボタンを押します。

f:id:takanory42:20170510000459p:plain

 

次に、ユーザーを作成して、グループに所属させます。

 2-1. 左ペインの「ユーザー」→「ユーザーを追加」を選択します。

 2-2. 任意のユーザー名を入力し、「プログラムによるアクセス」を選択します。

f:id:takanory42:20170510000923p:plain

 2-3. アクセス権限の設定では、「ユーザーをグループに追加」を選択し、先ほど作成した「S3FullAccess」グループを選択します。

f:id:takanory42:20170510001120p:plain

 2-4. 確認して、「ユーザーの作成」ボタンをクリックします。

f:id:takanory42:20170510001219p:plain

 2-5. 「アクセスキーID」と「シークレットアクセスキー」が表示されますので、控えておきます。シークレットアクセスキーは再確認することができません。(忘れてしまった場合はリセットする必要があります)

f:id:takanory42:20170511002227p:plain

忘れてしまったら: IAM ユーザーのアクセスキーの管理 - AWS Identity and Access Management

 

データを公開するための権限設定

S3バケット内のデータに外部から読み取りアクセスできるようにバケットポリシーを設定します。ポリシーは決まった形式で記述する必要がありますが、ポリシージェネレーターを使うことで、簡単にポリシーを生成することができます。

 1. S3コンソールから作成したバケットを開き、「アクセス権限」→「バケットポリシー」を選択します。

 2. テキストエリア下の「ポリシージェネレーター」を押します。

f:id:takanory42:20170510003031p:plain

 3. 以下のように設定し、「Add Statement」ボタンを押します。

  • Select Type of Policy: 「S3 Backet Policy」
  • Effect: 「Allow」
  • Principal: 「*」
  • AWS Service: 「Amazon S3
  • Actions: 「GetObject」のみ選択
  • Amazon Resource Name(ARN): 「arn:aws:s3:::バケット名/*」

f:id:takanory42:20170510003457p:plain

 4. 「Generate Policy」ボタンをクリックすると、以下のような生成されたポリシーが表示されます。すべて選択してコピーします。

{
  "Id": "Policy1494344865046",
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "Stmt1494344352632",
      "Action": [
        "s3:GetObject"
      ],
      "Effect": "Allow",
      "Resource": "arn:aws:s3:::backetnamehoge/*",
      "Principal": "*"
    }
  ]
}

 5. バケットポリシーの画面に戻り、コピーしたポリシーを貼り付けて、「保存」ボタンを押します。

これでS3バケット内のコンテンツにhttp/httpsでアクセスできるようになりました。適当なファイルをS3にアップロードして、アクセスできるか確認しておきましょう。

 

MastodonのS3機能設定

 続いて、Mastodonの設定を変更し、S3へのメディアデータの書き込みやリンク先がS3に向くようにします。なお、設定の反映〜データ移行の完了までは、メディアデータが正常に表示されない状態となりますので、自分以外にユーザーのいるインスタンスでは注意が必要です。

 1. 環境設定ファイル .env.production を編集します。

$ sudo su - mastodon
$ vim live/.env.production

 60行目付近のコメントアウトを解除し、以下のように設定します。先ほど控えた「アクセスキーID」と「シークレットアクセスキー」をここで使います。

  • S3_ENABLED: true
  • S3_BUCKET: S3のバケット名
  • AWS_ACCESS_KEY_ID: アクセスキーID
  • AWS_SECRET_ACCESS_KEY: シークレットアクセスキー
  • S3_REGION: S3のリージョン(コードで記述)
  • S3_PROTOCOL: https
  • S3_HOSTNAME: 変更不要(コメント解除も必要なし)

「S3_REGION」はリージョンごとのコードで記述する必要があります。コードの一覧はこちらで確認できます。

 リージョンとアベイラビリティーゾーン - Amazon Elastic Compute Cloud

設定例:

S3_ENABLED=true
S3_BUCKET=backetnamehoge
AWS_ACCESS_KEY_ID=ABCDEFGHIJKLMNOPQRST
AWS_SECRET_ACCESS_KEY=ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890abcd
S3_REGION=ap-northeast-1
S3_PROTOCOL=https
# S3_HOSTNAME=192.168.1.123:9000

 2. ファイルを保存します。

 3. Mastodonのサービスを再起動して、設定を反映させます。*2

$ sudo systemctl restart mastodon-*

 これ以降に投稿や取得されたメディアデータはS3に保存されていきます。また、メディアデータの参照先URLもS3が使用されます。

 

データ移行

 現状のMastodonでは、一度取得したメディアデータが見つからなくても再取得してくれません。ローカルに保存されている取得済みのメディアデータをS3バケットにコピーします。メディアデータは <インストーディレクトリ>/public/system/ 以下に保存されていますので、これをAWS CLIのコマンドを使ってS3バケットにコピーします。

 

AWS CLI のインストー

AWS CLIの動作にはPython 2.6.3 以降が必要です。CentOS 7なら問題ありません。 

 1. pipをインストールするため、EPELレポジトリを追加します。AWS MarketplaceのCentOS公式AMIを使用している場合は最初から入っています。

$ sudo yum install epel-release

 2. python-pipをインストールします。

$ sudo yum install python-pip

3. pipでAWS CLIをインストールします。

$ sudo pip install awscli

4. AWS CLIの初期設定をおこないます。アクセスキーIDはMastodonに設定したものと同じで大丈夫です。

$ aws configure
AWS Access Key ID [None]: ABCDEFGHIJKLMNOPQRST
AWS Secret Access Key [None]: ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890abcd
Default region name [None]: ap-northeast-1
Default output format [None]: json

 

S3バケットにデータをコピー

 1. aws s3 syncコマンドでデータをコピーします。"aws s3 sync <コピー元> s://<バケット名>" で<コピー元>以下のディレクトリ/フォルダを再帰的にS3バケットと同期してくれます。*3 

$ cd ~mastodon/live
$ aws s3 sync public/system/ s3://bucketnamehoge

ちなみに、--dryrunオプションで実際のコピーはせずに、対象の一覧表示だけをおこなえます。

 

これでメディアデータのS3への移行は完了です。

画像付きのTootを投稿するなどして、動作を確認しましょう。画像のリンク先がS3のURLになっていることがわかります。

 

おわりに

MastodonのメディアデータをAmazon S3に移行した記録でした。私の場合は、おひとり様インスタンスで、データも数十MBだったので気軽に、一瞬で移行完了しましたが、公開インスタンスの場合はやはり最初からS3を使っておくべきですね。

 

参考記事(Docker環境の場合):

Mastodon インスタンスの画像や動画の保存先をクラウドストレージ (Amazon S3) に移行した話 | WWW WATCH

*1:私は管理のためにLoggingとTagを使用しています

*2:mastodon-webだけでいいかも?

*3:rsyncで--deleteを指定しない場合と同じような動き