Set up file and image uploads to S3

Актуальна ли первая публикация по ссылке выше
https://meta.discourse.org/t/set-up-file-and-image-uploads-to-s3
как руководство, позволяющее администраторам настроить это? Если нет, где можно найти актуальное на 2024 год руководство по настройке S3? Утверждается, что это официальное руководство, поддерживаемое командой Discourse.

Мы реализовали настройку в точности по указанному руководству, но изображения на нашем экземпляре Discourse отображаются некорректно, хотя они успешно загружаются в S3.

Наш процесс

  1. Настройка самого бакета S3 и политики доступа в S3 в соответствии с указанным руководством (все шаги выполнены точно)

  2. Настройка переменных окружения в файле app.yml и в панели администратора (идентично руководству)

  3. Пересборка приложения через launcher

  4. 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 года.

Привет,
мы используем Cloudflare R2 для S3-хранилища (теперь всё работает), и я хотел перенести Discourse на другой сервер.
Однако при восстановлении из резервной копии аватары пользователей отсутствовали, даже при включённой опции «backup uploads».

Поэтому я запустил команду миграции S3 на старом сервере для переноса изображений, которые всё ещё хранятся локально, но она завершается ошибкой с приведённым ниже трассировочным выводом. Причина неясна.

rake uploads:migrate_to_s3 --trace
** Invoke uploads:migrate_to_s3 (first_time)
** Invoke environment (first_time)
** Execute environment
** Execute uploads:migrate_to_s3
Обратите внимание: миграция на S3 в настоящее время необратима! 
[CTRL+c] для отмены, [ENTER] для продолжения

Миграция файлов на S3 для 'default'...
Загрузка файлов на S3...
 - Список локальных файлов
..... => 5123 файла
 - Список файлов на S3
....... => 6871 файл
 - Синхронизация файлов с S3
.......................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................^[[B............................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................
Обновление URL-адресов в базе данных...
Удаление старых оптимизированных изображений...
Пометка всех сообщений, содержащих лайтбоксы, для повторной обработки...
828 сообщений помечены для повторной обработки
rake aborted!
FileStore::ToS3MigrationError: 4898 из 5838 файлов не были перенесены на S3. Миграция на S3 не удалась для БД '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>'

Похоже, что эти изображения по какой-то причине всё ещё хранятся локально, хотя я уже запускал этот скрипт миграции ранее.

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 лайка

Настройте CORS для корзины в сочетании с вышеуказанными параметрами для загрузки в несколько частей.

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

Возможно ли сменить провайдера сервиса S3?

Хотелось бы узнать, возникнут ли какие-либо проблемы, если я попробую сменить провайдера S3, не учитывая вопрос уже загруженных изображений. У меня нет с этим серьезных проблем, так как сайт еще не запущен; я все еще занимаюсь его разработкой.

Возможно ли сохранить изображения локально, а затем снова активировать S3 с новым провайдером?

Вы можете установить siteSettings.include_s3_uploads_in_backups=true в Rails, затем создать резервную копию, изменить настройки S3 и восстановить эту резервную копию.

1 лайк

Ладно, понял. Большое спасибо!

1 лайк

В связанной ветке упоминается PR, удаляющий задачу migrate_from_s3, и у меня нет оснований полагать, что она была добавлена обратно позже, но я хотел уточнить, актуально ли это до сих пор. Я рассматриваю возможность миграции на MinIO и немного беспокоюсь о том, чтобы сделать её зависимостью.

Интересно, может ли это стать обходным решением для упомянутого выше. Включить эту настройку, создать резервную копию, отключить настройки S3 и восстановить резервную копию.

Да. Я бы восстановил её на новом сервере, чтобы в случае чего у вас всё равно был рабочий сервер.

Из этой темы следует, что данный параметр загружает отдельные файлы из S3, но я задаюсь вопросом, не возникнут ли проблемы с постами, которые ссылаются на URL-адреса S3, а не на локальные файлы. Я не уверен, как это обрабатывается в базе данных. Мне было бы интересно узнать, прошла ли ваша миграция на другого провайдера успешно, @Rhod.

1 лайк

Я перешёл плавно. Подчёркиваю, что у меня не возникло серьёзных проблем, так как количество изображений и резервных копий было минимальным. Форум использовался исключительно в тестовых целях, ещё не в «продакшене».

В итоге, после нескольких проб и ошибок, я переустановил форум на новый сервер (Hetzner) и настроил Cloudflare S3 R2 (ранее я использовал Amazon S3) для резервных копий и изображений на сервере, который в конечном счёте меня убедил.

Извините, что не могу быть особо полезен. В будущем попробую протестировать это на другом сервере.

В случае с CF R2 ваши миниатюры чата отображаются корректно?

1 лайк

Я не заметил этой ошибки; на самом деле у меня на сайте чат отключён.

Думаю, я не буду его использовать, но у меня всё ещё та же ошибка, о которой вы упоминали в своём посте.

Однако я буду следить за вашим постом, чтобы увидеть, помогут ли они вам найти решение.

1 лайк

Спасибо, Уолтер! Я пришёл сюда, чтобы написать то же самое, но увидел, что вы уже это сделали.

@Discourse, есть ли шанс, что содержание поста Уолтера будет включено в исходный пост?

Можно ли загружать видео на S3? В данный момент при загрузке видео на S3 сохраняется только обложка видео, а само видео не загружается.