この話の要点
下記の設定で、ローカルにファイルを保存しながら、オブジェクトストレージと同じURL設計にできる
.env.production
にPAPERCLIP_ROOT_URL=https://media.example.com
を指定- nginxで
root /home/mastodon/live/public/system;
にしてservername media.example.com;
を公開する。
Mastodonのメディアファイルの保存場所
標準
Mastodonでは、標準ではメディアをインストールしたディレクトリのpublic/system/
以下に保存します。
accounts/
アカウント関連のメディアavatars
アバター(アイコン)headers
ヘッダー
media_attachments/files
投稿の添付ファイルcustom_emojis/images
カスタム絵文字preview_cards/images
プレビューカード(URL参照先のサムネイル)
また、リモートサーバーのユーザーについては、同様のファイルをpublic/system/cache/
以下に保存します。
標準のnginx用の設定ファイルでは、root /home/mastodon/live/public;
に設定されているので、たとえばexample.com
というドメインでサーバ設置した場合、URLはこうなります。
https://example.com/about
概要ページhttps://example.com/@admin
アカウントページhttps://example.com/system/accounts/avatars/000/000/001/original/7d4fbbe3107f536a95a30334bf91137c.png
アバター画像のURL
オブジェクトストレージ
一方、メディアをオブジェクトストレージに保存する設定にすることもできます。
.env.production
の設定がこんな感じになっているとして、
S3_BUCKET=media.example.com S3_REGION=ap-northeast-1 S3_HOSTNAME=s3.ap-northeast-1.wasabisys.com S3_ENDPOINT=https://s3.ap-northeast-1.wasabisys.com AWS_ACCESS_KEY_ID=xxxxxxxx AWS_SECRET_ACCESS_KEY=xxxxxxxx S3_ALIAS_HOST=media.example.com
この場合、URLはこうなります。
https://example.com/about
概要ページhttps://example.com/@admin
アカウントページhttps://media.example.com/accounts/avatars/000/000/001/original/7d4fbbe3107f536a95a30334bf91137c.png
アバター画像のURL
連合先に伝えたURLは変更できない
サーバを設置する際、ローカルストレージにメディアを保存する決定をすると、あとからオブジェクトストレージに移行しようとした時に、リモートに既に伝えたURLが無効になってしまう問題が発生します。逆の場合も同様です。アカウントのアバターやヘッダーについては強制更新をかけて置き換えることも可能ですが、カスタム絵文字は難しいし、投稿の添付ファイルは絶望的です。
あらかじめ、オブジェクトストレージを採用する場合と同じURLでアクセスするよう設定し、いつ切り替えても問題が起きないようにしておくことをオススメします。
ローカルストレージをオブジェクトストレージと同じURLにする
.env.production
に、メディアにアクセスする際に使う、本体とは異なるサーバURLを指定する- メディアサーバのドメインをDNSに登録する
- nginxの設定に、ローカルストレージの内容を返す、メディアサーバとして機能する設定を追加する
ここでは、example.com
ドメインで運用するサーバのメディアを、media.example.com
で提供することにします。まずここを決めます。
.env.production
に以下の環境変数を指定します。
PAPERCLIP_ROOT_URL=https://media.example.com
DNSサーバにmediaの名称とIPアドレスを指定します。
nginxに、例えば下記のような設定を追加します。
server { listen 80; listen [::]:80; server_name media.example.com; location / { return 301 https://$host$request_uri; } } server { listen 443 ssl http2; listen [::]:443 ssl http2; server_name media.example.com; ssl_session_cache shared:ssl_session_cache:10m; ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem; ssl_protocols TLSv1 TLSv1.2; ssl_ciphers ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA:ECDHE-RSA-AES128-SHA:AES128-SHA; ssl_prefer_server_ciphers on; access_log /var/log/nginx/media_access.log; error_log /var/log/nginx/media_error.log; root /home/mastodon/live/public/system; location / { add_header Cache-Control "public, max-age=31536000, immutable"; add_header Strict-Transport-Security "max-age=31536000" always; access_log /var/log/nginx/media.access.log; error_log /var/log/nginx/media.error.log; } }