Digital Ocean Spaces は CORS ルールに対して AWS S3 API を実装していません

,

Spaces へのアップロードの移動にまだ苦労しています。s3_cdn_url が定義されている場合、Discourse はアセットに対して s3_cdn を参照しますが、そこにアセットが存在しません。rake s3:upload_assets を実行しようとしましたが、以下のようなエラーが発生します。

root@shadrack-rbx:/var/www/discourse# rake s3:upload_assets
installing CORS rule
Uploading: assets/vendor-3037640def3beef9cc83cef108868f2bac887cf141d032c6b7388c7879c19601.js
OPTS: {:cache_control=>"max-age=31556952, public, immutable", :content_type=>"application/ecmascript", :acl=>"public-read", :tagging=>""} # NOTE: Pfaffman added this debug line. . .
rake aborted!
Aws::S3::Errors::InvalidArgument:
/var/www/discourse/vendor/bundle/ruby/2.5.0/gems/aws-sdk-core-3.46.1/lib/seahorse/client/plugins/raise_response_errors.rb:15:in `call'
/var/www/discourse/vendor/bundle/ruby/2.5.0/gems/aws-sdk-s3-1.30.1/lib/aws-sdk-s3/plugins/sse_cpk.rb:22:in `call'
/var/www/discourse/vendor/bundle/ruby/2.5.0/gems/aws-sdk-s3-1.30.1/lib/aws-sdk-s3/plugins/dualstack.rb:26:in `call'
/var/www/discourse/vendor/bundle/ruby/2.5.0/gems/aws-sdk-s3-1.30.1/lib/aws-sdk-s3/plugins/accelerate.rb:35:in `call'
/var/www/discourse/vendor/bundle/ruby/2.5.0/gems/aws-sdk-core-3.46.1/lib/aws-sdk-core/plugins/jsonvalue_converter.rb:20:in `call'
/var/www/discourse/vendor/bundle/ruby/2.5.0/gems/aws-sdk-core-3.46.1/lib/aws-sdk-core/plugins/idempotency_token.rb:17:in `call'
/var/www/discourse/vendor/bundle/ruby/2.5.0/gems/aws-sdk-core-3.46.1/lib/aws-sdk-core/plugins/param_converter.rb:24:in `call'
/var/www/discourse/vendor/bundle/ruby/2.5.0/gems/aws-sdk-core-3.46.1/lib/aws-sdk-core/plugins/response_paging.rb:10:in `call'
/var/www/discourse/vendor/bundle/ruby/2.5.0/gems/aws-sdk-core-3.46.1/lib/seahorse/client/plugins/response_target.rb:23:in `call'
/var/www/discourse/vendor/bundle/ruby/2.5.0/gems/aws-sdk-core-3.46.1/lib/seahorse/client/request.rb:70:in `send_request'
/var/www/discourse/vendor/bundle/ruby/2.5.0/gems/aws-sdk-s3-1.30.1/lib/aws-sdk-s3/client.rb:5856:in `put_object'
/var/www/discourse/vendor/bundle/ruby/2.5.0/gems/aws-sdk-s3-1.30.1/lib/aws-sdk-s3/object.rb:928:in `put'
/var/www/discourse/lib/s3_helper.rb:44:in `upload'
/var/www/discourse/lib/tasks/s3.rake:38:in `block in upload'
/var/www/discourse/lib/tasks/s3.rake:37:in `open'
/var/www/discourse/lib/tasks/s3.rake:37:in `upload'
/var/www/discourse/lib/tasks/s3.rake:148:in `block (2 levels) in <top (required)>'
/var/www/discourse/lib/tasks/s3.rake:147:in `each'
/var/www/discourse/lib/tasks/s3.rake:147:in `block in <top (required)>'
/usr/local/bin/bundle:23:in `load'
/usr/local/bin/bundle:23:in `<main>'
Tasks: TOP => s3:upload_assets
(See full trace by running task with --trace)
root@shadrack-rbx:/var/www/discourse# vi config/discourse.
discourse.conf           discourse.config.sample  discourse.pill.sample
root@shadrack-rbx:/var/www/discourse# vi config/discourse.conf
root@shadrack-rbx:/var/www/discourse# rails c

参考までに、この設定では S3 への画像アップロードは正常に動作します。

また、これが動作した場合、アセットはブートストラップ時に S3 にプッシュされるのでしょうか?このサイトを S3(73GB の画像)に移行し、サーバー構成を変更したいと考えています。Spaces は紹介クレジットと無料の CDN が利用できるため魅力的ですが、もしかすると諦めて AWS S3 に移行した方が良いでしょうか?

Why do you need to push assets to S3? Can’t they be served from a push CDN like normal? Uploads assets means JS files not uploads.

That’s what I thought, but what’s happening is that all the assets are linked to the S3 CDN url and they aren’t there. I’d assumed that they’d either be served by the CDN like normal (I have one site configured with regular CDN and it points to S3 cdn when that’s configured) or from local storage (I have another site configured with no regular CDN and when I have s3_cdn_url in global settings, all the assets are linked to the s3 CDN.

So, I either need to push assets to S3 or have Discourse not point to assets in S3. I don’t really care, but they need to be somewhere that they can be found, as without assets the whole site is hosed and I have to make changes in console.

Making sure you saw this @pfaffman because this topic makes very little sense the way it is phrased now.

Do you mean “uploads” as in “uploaded files”?

No, I really mean assets (uploads seem fine). It seems that when GlobalSettings.s3_cdn_url is defined, discourse expects assets (i.e., the javascript stuff) to be in the S3 CDN, so the site is broken because none of the assets are available.

It makes zero sense to me either. :frowning_face:

I just set SiteSettings.s3_cdn_url (not in GlobalSettings) and assets seem to still be coming from the server, not the CDN. So maybe it’s a bug with GlobalSettings.s3_cdn_url?

Yup. Re-setting the value in discourse.conf does this:

All those red things link to the CDN for the assets.

I turned it back on/off and defining it as a global makes assets link to the s3_cdn_url.

So I guess the thing to do is configure those values in a plugin and hide them from the UX that way.

Looks like spaces don’t implement the AWS S3 API for the CORS rule. That is a must have since assets can contain fonts, and those really need CORS.

Maybe work on a way to disable the rules insertion and took care of that manually?

@rishabh did this already with the tombstone rule to allow our S3 compatibility with more providers, so makes sense to expand on that.

So if I want to move this site to S3 maybe I should just give in and stick this on AWS S3 and then stick CloudFlare or KeyCDN in front of it?

No.

That means that if you want to use the GlobalSettings for S3 in the current state you will need to deal with the missing feature in the S3-like service in Digital Ocean, patching around it somehow.

You already have a workaround (use a normal site setting), and we know that we need a setting to disable the CORS rule (pr-welcome for that).

Sorry I’m dense. I’ve been working on this off and on for months.

Ah, so as long as I don’t use GlobalSettings it’ll work just fine? (Because GlobalSettings also wants assets to be in S3?)

この問題がまだ続いているか、以下の対応で解決するかはわかりませんが、自分自身のトラブルシューティング中にこの情報に出会ったので共有させていただきます:

  • S3 ストレージに Digital Ocean Spaces を使用している場合、
  • WOFF などのアップロードされたフォントを含むテーマがあり、それらが S3 ストレージにコピーされている場合、
  • Discourse サイトでフォントを読み込む際に CORS エラーが発生している場合、

Digital Ocean Spaces では、S3 ストレージに使用しているエンドポイントに CORS 設定が追加されています。Origin には Discourse サイトの URL を、許可されるメソッドには GET を、有効期限には 86400 などの適切な値を設定してください。

つまり、このトピック全体の結論は誤解だったということです。

私は DO の提供サービスとの Discourse の互換性をテストするのに丸一日費やし、ここでの CORS の問題は赤いニシン(見分けを難しくするための誤情報)であることがわかりました。

問題は、DO Spaces が S3 クローンで tagging ヘッダーを実装していないことです。

upload_assets タスクの修正は非常にシンプルで、ブランチにあります。

問題は、実際には別の rake タスクで tagging を本当に使用しているため、DO Spaces を使用している場合、s3:expire_missing_assets タスクを全く使用できないことです。これはある程度は「許容できる」トレードオフとなる場合があります。

来週、これについて更新を行い、いくつかの新しいガイドを作成する予定です。

うっ、これを DO に報告して、彼らの Clone を修正してもらえないでしょうか?

Discourse(Redis、PostgreSQL、オブジェクトストレージ、CDNなどのサービス)を使用した大規模な実験について、DO サービスを活用してまとめているため、これを簡潔なドキュメントとして共有できます。すでに深刻な問題が見つかりました。彼らの S3 クローン CDN がファイルの Content-Encoding ヘッダーを削除してしまうため、GZip や Brotli で圧縮された JavaScript を提供できず、結果としてすべてが機能しなくなります。

長期的には、すべての AWS S3 のクローンが正確になることが、全員にとって最良の結果です。したがって、プロバイダーにフォローアップし、クローンの品質向上を促すことが、より優れた道です。

確かに。

それは素晴らしいことですが、私は期待していません。

一方、彼らは自分が壊れていると知らなければ直すことはできません。これが彼らに必要な後押しになるかもしれません。

Digital Ocean に連絡したところ、裏側で MinIO を運用していることがわかりました。MinIO は先月からタグ付け機能をサポートしており、彼らがこの新バージョンをロールアウトすれば、すぐにサポートされる予定です。

これで動作します。

アップロード用のオブジェクトストレージの利用(S3 のクローン)の手順に従ってください。