noellabo's tech blog

@noellaboの技術ブログ

Pixelfedのオブジェクトストレージ対応

オブジェクトストレージの有効化

Pixelfedは主に写真を投稿するサービスであるが、まだオブジェクトストレージに保存する機能は完成していない。しかし、ほとんどできあがっていて、動くことは動く。

.envへの記述

.envに次のように記述する

PF_ENABLE_CLOUD=true

AWS_ACCESS_KEY_ID="XXXXXXXXXXXXXXXXXXXX"
AWS_SECRET_ACCESS_KEY="XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
AWS_DEFAULT_REGION="us-east-2"
AWS_BUCKET="media.example.com"
AWS_URL=https://media.example.com
AWS_ENDPOINT=https://s3.us-east-2.wasabisys.com

最初のPF_ENABLE_CLOUDが重要。その他は、wasabiのus-east-2を利用する例である。

オブジェクトを参照するためのURLは、オブジェクトストレージのURLそのままだとあとで大変苦労するので、専用のサブドメインを割り当てることが望ましい。DNSのCNAMEで参照先を振り替えたり、nginxなどリバースプロキシを立てて中継すると良い。nginxはキャッシュサーバとしてもしっかり働いてくれる。Cloudflareを通すのであれば、CNAMEを指定すると同時にキャッシュさせることができる。

CNAMEの場合

DNSで、example.comのゾーンに下記の設定を行う

CNAME media  media.example.com.s3.us-east-2.wasabisys.com

nginxの場合

一例

proxy_cache_path /var/cache/pixelfed levels=1:2 keys_zone=PIXELFEDCACHE:10m inactive=7d max_size=2g;

server {
  listen 80;
  listen [::]:80;
  server_name media.example.com;

  root /home/pixelfed/pixelfed/public;
  location / { return 301 https://$host$request_uri; }
}

server {
  listen 443 ssl http2;
  listen [::]:443 ssl http2;
  server_name media.example.com;

  ssl_protocols TLSv1.2 TLSv1.3;
  ssl_ciphers HIGH:!MEDIUM:!LOW:!aNULL:!NULL:!SHA;
  ssl_prefer_server_ciphers on;
  ssl_session_cache shared:SSL:10m;

  ssl_certificate           /etc/letsencrypt/live/example.com/fullchain.pem;
  ssl_certificate_key       /etc/letsencrypt/live/example.com/privkey.pem;

  root /home/pixelfed/pixelfed/public;

  location = /favicon.ico { access_log off; log_not_found off; }
  location = /robots.txt  { access_log off; log_not_found off; }

  location / {
    add_header Cache-Control "public, max-age=31536000, immutable";
    add_header Strict-Transport-Security "max-age=31536000";
    add_header X-Cached $upstream_cache_status;

    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto https;
    proxy_set_header Proxy "";
    proxy_pass_header Server;
    proxy_cache PIXELFEDCACHE;
    proxy_buffering on;
    proxy_redirect off;
    proxy_http_version 1.1;

    proxy_pass https://media.example.com.s3.us-east-2.wasabisys.com/;
  }
}

Pixelfedにおけるオブジェクトストレージの使い方

Pixelfedでは、まずローカルのファイルシステムにファイルを保存する。

オブジェクトストレージへの保存が有効になっている場合、前述のようにまずローカルに保存したあと、オブジェクトストレージにファイル保存を試み、成功した場合、データベース上に保存したオブジェクトストレージを参照するURLを記録する。

オブジェクトストレージは、しばしば障害によりダウンしていることがあるが、Pixelfedでは何事も無かったかのようにローカルにファイル保存して参照URLを記録し、オブジェクトストレージの方はあっさりあきらめる。

最初に保存したローカルのファイルは、そのままでは削除されずに残る。オブジェクトストレージと重複するファイルについては、バックグラウンドで掃除するタスクを別途走らせる予定であるという。

ローカルにだけ保存されたファイルは、オブジェクトストレージのようにメディア用のサブドメインではなく、Pixelfed本体と同じドメインのローカルパスで参照される。これについては、オブジェクトストレージと同じURLで参照すると、ローカルに保存されたファイルがある場合はそちらを、ない場合はオブジェクトストレージを参照するなど、ユーザーからは見分けがつかないように振る舞うべきであると思う。