Set up file and image uploads to S3

上記の最初の投稿は、管理者がS3へのファイルと画像のアップロードを設定できる有効なガイドですか?もしそうでない場合、2024年の正しいS3ガイドはどこにありますか?これは公式であり、Discourseチームによってサポートされているとのことです。

上記のように実装しましたが、画像はS3にアップロードされているにもかかわらず、Discourseインスタンスで壊れています。

私たちのフロー

  1. 上記の通り、S3バケット自体とS3のポリシーを設定しました(すべての手順を正確に実行しました)。

  2. 上記の通り、app.ymlと管理画面で環境設定を行いました(同一です)。

  3. launcher rebuild app

  4. CDNは一切使用していません。CDNはオプションであり、CDNなしでも動作するはずだと理解しています。

結果:

  1. 画像はDiscourseによってバケットにアップロードされています。
  2. 投稿内のリンクは、Discourseによって正しくAmazonリンクに置き換えられています。
    xxx-bucket.s3.dualstack.us-east-1.amazonaws.com/original/1X/a1b21eb5de071799d4b5e5215619d11d28602dfe.jpeg
  3. リンクはアクセスできません(公式ガイドのS3ポリシーによるものと推定されます)。

公式ガイドのS3ポリシーの変更が推定されます。Principal: このポリシーはPrincipalを指定していないため、適切な権限を持つ認証されたすべてのユーザーに適用されます。匿名(公開)アクセスを許可するには、\"Principal\": \"*\"を指定する必要があります。これもバケットを公開するため、良い解決策ではないかもしれません。
これはあくまで推測です。2024年にガイドが正しく更新されることを願っています。

Hey,
.we are using Cloudflare R2 for s3 storage(it works now) and i wanted to move discourse to another server.
However profile pictures were missing when restoring from a backup even when checking the “backup uploads” option.

so i ran the s3 migrate command on the old server to migrate images that are still local, and it’s failing with this trace, it’s not clear what’s the reason.

rake uploads:migrate_to_s3 --trace
** Invoke uploads:migrate_to_s3 (first_time)
** Invoke environment (first_time)
** Execute environment
** Execute uploads:migrate_to_s3
Please note that migrating to S3 is currently not reversible! 
[CTRL+c] to cancel, [ENTER] to continue

Migrating uploads to S3 for 'default'...
Uploading files to S3...
 - Listing local files
..... => 5123 files
 - Listing S3 files
....... => 6871 files
 - Syncing files to S3
.......................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................^[[B............................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................
Updating the URLs in the database...
Removing old optimized images...
Flagging all posts containing lightboxes for rebake...
828 posts were flagged for a rebake
rake aborted!
FileStore::ToS3MigrationError: 4898 of 5838 uploads are not migrated to S3. S3 migration failed for db 'default'. (FileStore::ToS3MigrationError)
/var/www/discourse/lib/file_store/to_s3_migration.rb:132:in `raise_or_log'
/var/www/discourse/lib/file_store/to_s3_migration.rb:73:in `migration_successful?'
/var/www/discourse/lib/file_store/to_s3_migration.rb:383:in `migrate_to_s3'
/var/www/discourse/lib/file_store/to_s3_migration.rb:59:in `migrate'
/var/www/discourse/lib/tasks/uploads.rake:126:in `migrate_to_s3'
/var/www/discourse/lib/tasks/uploads.rake:106:in `block in migrate_to_s3_all_sites'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/rails_multisite-6.1.0/lib/rails_multisite/connection_management/null_instance.rb:49:in `with_connection'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/rails_multisite-6.1.0/lib/rails_multisite/connection_management/null_instance.rb:36:in `each_connection'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/rails_multisite-6.1.0/lib/rails_multisite/connection_management.rb:21:in `each_connection'
/var/www/discourse/lib/tasks/uploads.rake:104:in `migrate_to_s3_all_sites'
/var/www/discourse/lib/tasks/uploads.rake:100:in `block in <main>'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/rake-13.2.1/lib/rake/task.rb:281:in `block in execute'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/rake-13.2.1/lib/rake/task.rb:281:in `each'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/rake-13.2.1/lib/rake/task.rb:281:in `execute'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/rake-13.2.1/lib/rake/task.rb:219:in `block in invoke_with_call_chain'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/rake-13.2.1/lib/rake/task.rb:199:in `synchronize'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/rake-13.2.1/lib/rake/task.rb:199:in `invoke_with_call_chain'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/rake-13.2.1/lib/rake/task.rb:188:in `invoke'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/rake-13.2.1/lib/rake/application.rb:188:in `invoke_task'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/rake-13.2.1/lib/rake/application.rb:138:in `block (2 levels) in top_level'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/rake-13.2.1/lib/rake/application.rb:138:in `each'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/rake-13.2.1/lib/rake/application.rb:138:in `block in top_level'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/rake-13.2.1/lib/rake/application.rb:147:in `run_with_threads'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/rake-13.2.1/lib/rake/application.rb:132:in `top_level'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/rake-13.2.1/lib/rake/application.rb:83:in `block in run'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/rake-13.2.1/lib/rake/application.rb:214:in `standard_exception_handling'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/rake-13.2.1/lib/rake/application.rb:80:in `run'
bin/rake:13:in `<top (required)>'
/usr/local/lib/ruby/gems/3.3.0/gems/bundler-2.5.18/lib/bundler/cli/exec.rb:58:in `load'
/usr/local/lib/ruby/gems/3.3.0/gems/bundler-2.5.18/lib/bundler/cli/exec.rb:58:in `kernel_load'
/usr/local/lib/ruby/gems/3.3.0/gems/bundler-2.5.18/lib/bundler/cli/exec.rb:23:in `run'
/usr/local/lib/ruby/gems/3.3.0/gems/bundler-2.5.18/lib/bundler/cli.rb:455:in `exec'
/usr/local/lib/ruby/gems/3.3.0/gems/bundler-2.5.18/lib/bundler/vendor/thor/lib/thor/command.rb:28:in `run'
/usr/local/lib/ruby/gems/3.3.0/gems/bundler-2.5.18/lib/bundler/vendor/thor/lib/thor/invocation.rb:127:in `invoke_command'
/usr/local/lib/ruby/gems/3.3.0/gems/bundler-2.5.18/lib/bundler/vendor/thor/lib/thor.rb:527:in `dispatch'
/usr/local/lib/ruby/gems/3.3.0/gems/bundler-2.5.18/lib/bundler/cli.rb:35:in `dispatch'
/usr/local/lib/ruby/gems/3.3.0/gems/bundler-2.5.18/lib/bundler/vendor/thor/lib/thor/base.rb:584:in `start'
/usr/local/lib/ruby/gems/3.3.0/gems/bundler-2.5.18/lib/bundler/cli.rb:29:in `start'
/usr/local/lib/ruby/gems/3.3.0/gems/bundler-2.5.18/exe/bundle:28:in `block in <top (required)>'
/usr/local/lib/ruby/gems/3.3.0/gems/bundler-2.5.18/lib/bundler/friendly_errors.rb:117:in `with_friendly_errors'
/usr/local/lib/ruby/gems/3.3.0/gems/bundler-2.5.18/exe/bundle:20:in `<top (required)>'
/usr/local/bin/bundle:25:in `load'
/usr/local/bin/bundle:25:in `<main>'

it seems these pictures are still stored locally for some reason, even though i ran this migration script before.

「いいね!」 1

新しい画像とは異なるバケットまたはパスに画像が存在する、s3の設定を変更したことが原因だと推測されます。

Upload.pluck(:url) を確認して、何が間違っているのか確認してください。

「いいね!」 1

この問題は私も最近経験し、解決することができました。このロールを使用してIAM権限を更新することで解決しました。

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
               "s3:List*",
               "s3:Get*",
               "s3:AbortMultipartUpload",
               "s3:DeleteObject",
               "s3:PutObject",
               "s3:PutObjectAcl",
               "s3:PutObjectVersionAcl",
               "s3:PutLifecycleConfiguration",
               "s3:CreateBucket",
               "s3:PutBucketCORS"
      ],
      "Resource": [
        "arn:aws:s3:::my-bucket",
        "arn:aws:s3:::my-bucket/*"
      ]
    },
    {
       "Effect": "Allow",
       "Action": [
           "s3:ListAllMyBuckets",
           "s3:ListBucket"
       ],
       "Resource": "*"
    }
  ]
}

また、ACLオブジェクト所有権を有効にする必要がありました。

S3を検索した際の完全な設定は以下の通りです。

「いいね!」 4

マルチパートアップロードのために、上記の СORS 設定をバケットに追加してください。

[
    {
        "AllowedHeaders": [
            "content-type",
            "x-amz-acl",
            "x-amz-meta-sha1-checksum"
        ],
        "AllowedMethods": [
            "GET",
            "HEAD",
            "PUT"
        ],
        "AllowedOrigins": [
            "*"
        ],
        "ExposeHeaders": [],
        "MaxAgeSeconds": 3000
    }
]

S3サービスプロバイダーを変更することは可能ですか?

既にアップロードされた画像の問題は無視して、S3サービスプロバイダーを変更しようとした場合に何か問題が発生するかどうか知りたいです。サイトがまだ稼働しておらず、開発中であるため、この点については特に大きな問題はありません。

画像をローカルに保存し、新しいサービスプロバイダーでS3を再度有効にすることは可能ですか?

Railsで siteSettings.include_s3_uploads_in_backups=true を設定し、その後バックアップを作成して、S3の設定を変更し、バックアップを復元することができます。

「いいね!」 1

わかりました。どうもありがとうございます。

「いいね!」 1

リンクされたスレッドでは、migrate_from_s3 タスクを削除する PR について言及されており、後でそれが追加されたという証拠は見ていませんが、まだそうなのか確認したかったのです。MinIO への移行を検討しており、依存関係になることを少し心配しています。

これが上記で述べたことの回避策になるのではないかと思います。その設定を含め、バックアップを作成し、S3 設定を無効にし、バックアップを復元します。

はい。万が一何か問題が発生した場合でも、動作するサーバーが残るように、新しいサーバーに復元します。

このスレッドによると、この設定はS3から個々のファイルをダウンロードするようですが、投稿がローカルファイルではなくS3 URLを参照している場合に問題が発生するのではないかと疑問に思っています。データベースでどのように処理されるのかよくわかりません。プロバイダーの移行が成功したかどうか、@Rhodさん、知りたいです。

「いいね!」 1

スムーズに移行できました。画像やバックアップの数が最小限だったため、大きな問題はなかったことを強調しておきます。フォーラムは完全にテスト目的であり、「本番稼働」ではありませんでした。最終的に、数回の試行錯誤を経て、新しいサーバー(Hetzner)にフォーラムを再インストールし、バックアップと画像のためにS3(Cloudflare R2)を、最終的に私を納得させたサーバーで設定しました。

お役に立てず申し訳ありません。将来的に別のサーバーでテストできるか確認してみます。

CF R2 で、チャットのサムネイルは正常に機能しますか?

「いいね!」 1

そのエラーには気づきませんでした。実は、私のサイトではチャットを無効にしています。

使用しないと思いますが、あなたの投稿で言及されているのと同じエラーがまだ発生しています。

しかし、解決策が見つかるのを手伝ってくれるかどうか、あなたの投稿を注視しておきます。

「いいね!」 1

ウォルターさん、ありがとうございます!私も同じことを投稿しようとしたのですが、すでに投稿されていました。

@Discourse ウォルターさんの投稿内容を最初の投稿に統合していただけますか?

S3に動画をアップロードできますか?現在、動画をアップロードすると、動画のサムネイルのみがS3にアップロードされ、動画自体はアップロードされません。