Mastodon の画像などメディアデータをAmazon S3に移行する(非Docker環境)
各所で話題のMastodon。私もAWS上に自分でインスタンスを立てて、おひとり様インスタンスとして運用しています。
デフォルトでは、Mastodonのアカウント画像やTootの画像や動画などメディアデータはフォローしたユーザーが存在するサーバーのローカルに保存されています。しかし、フォロー数が増えてくると、メディアデータの容量もどんどん増えて、サーバーのストレージを圧迫していきます。
Mastodonには、メディアデータをAmazon S3(S3互換のストレージも可)に保存し、参照させる機能があります。容量が増えてしまう前に、ということで、サーバーのローカルストレージからS3に移行しました。
Amazon S3にメディアデータを置くメリット
S3にデータを置くメリットはこのあたりでしょう。(耐久性に関しては、おひとり様の場合はあまり気にしなくてもいいかもですが)
- スケーラビリティ:ストレージの圧迫に伴う容量追加が不要
- 費用:EBSに比べると、S3の方が費用が安い(5分の1近く)
- 耐久性:EBSよりもSLAが高く、バックアップも手軽に可能
移行の流れ
- S3バケットの作成
- S3バケットの権限設定
- MastodonのS3機能設定
- データ移行
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」としておきます。
1-4. 許可設定のポリシーから「AmazonS3FullAccess」を選択します。上のフィルター欄に「s3」などと入力すると探しやすいです。
1-5. 確認して、「グループの作成」ボタンを押します。
次に、ユーザーを作成して、グループに所属させます。
2-1. 左ペインの「ユーザー」→「ユーザーを追加」を選択します。
2-2. 任意のユーザー名を入力し、「プログラムによるアクセス」を選択します。
2-3. アクセス権限の設定では、「ユーザーをグループに追加」を選択し、先ほど作成した「S3FullAccess」グループを選択します。
2-4. 確認して、「ユーザーの作成」ボタンをクリックします。
2-5. 「アクセスキーID」と「シークレットアクセスキー」が表示されますので、控えておきます。シークレットアクセスキーは再確認することができません。(忘れてしまった場合はリセットする必要があります)
忘れてしまったら: IAM ユーザーのアクセスキーの管理 - AWS Identity and Access Management
データを公開するための権限設定
S3バケット内のデータに外部から読み取りアクセスできるようにバケットポリシーを設定します。ポリシーは決まった形式で記述する必要がありますが、ポリシージェネレーターを使うことで、簡単にポリシーを生成することができます。
1. S3コンソールから作成したバケットを開き、「アクセス権限」→「バケットポリシー」を選択します。
2. テキストエリア下の「ポリシージェネレーター」を押します。
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:::バケット名/*」
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
$ sudo yum install python-pip
$ 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