Настройка провайдера объектного хранилища, совместимого с S3, для загрузки файлов

Кажется, у меня нет прав на редактирование вики, но я успешно использовал другого провайдера.

OVHcloud

Название службы: Object Storage

Регионы соответствуют дата-центрам, которые идентифицируются трехбуквенным кодом. Если вы не знаете, где создали свой бакет, проверьте вкладку Object Storage в вашем клиентском портале.

DISCOURSE_USE_S3: true
DISCOURSE_S3_REGION: [код дата-центра]
DISCOURSE_S3_ENDPOINT: https://s3.[код дата-центра].io.cloud.ovh.net/
DISCOURSE_S3_ACCESS_KEY_ID: [ключ]
DISCOURSE_S3_SECRET_ACCESS_KEY: [ключ]
DISCOURSE_S3_BUCKET: [имя бакета]
DISCOURSE_S3_BACKUP_BUCKET: [имя бакета]
DISCOURSE_BACKUP_LOCATION: s3
1 лайк

Вы настроили OVHcloud S3 для загрузки файлов или только для резервного копирования?

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

Она очень совместима с S3, но есть некоторые отсутствующие функции, например, правила жизненного цикла для удаления старых файлов или их перемещения в холодное хранилище, над которыми OVH активно работает. Однако для раздачи файлов она работает отлично.

Поэтому для резервного копирования я просто использовал встроенную опцию Discourse для автоматического удаления старых резервных копий.

1 лайк

Это действительно разочаровывающий и совершенно бесполезный ответ. В чём именно проблема? Ссылка на документацию поддержки, которая постоянно меняется, означает, что никто не может точно сказать, что же именно подразумевается под «ужасной неработоспособностью», упомянутой в этой теме.

Вы упоминаете «метаданные» и то, что CDN «не знает о них». Какие именно метаданные? Было бы полезно узнать, что именно не работает.

Я хотел бы дополнить свой пост инструкцией о том, как использовать E2 от iDrive.

Похоже, что iDrive недавно включил функцию, из-за которой ключи доступа, назначенные только одному бакету, не работают, если не обойти проверку авторизации бакета.

При использовании rclone это можно обойти, добавив no_check_bucket = true в файл rclone.conf, но я не уверен, что для сборки Discourse существует аналогичная настройка окружения.

В результате при работе с iDrive E2 вы сейчас обязаны использовать ключ, имеющий права на запись во все ваши бакеты, а не только в один.

1 лайк

Почему кто-то другой должен знать точную проблему для провайдера, которым он не пользуется?

В любом случае, похоже, что мы почти дошли до Cloudflare R2. Согласно:

Когда я ввёл всю информацию в веб-интерфейсе, новые загрузки корректно отправлялись в хранилище S3, и резервные копии также корректно сохранялись в S3. Текущие загрузки, очевидно, не переместились.
Затем я перешёл в файл app.yml и ввёл следующую информацию:

## Этот набор строк позволяет загружать и скачивать файлы, размещённые на R2 S3..
  DISCOURSE_CDN_URL: https://eufiles.technospider.com
  DISCOURSE_USE_S3: true
  DISCOURSE_S3_ENDPOINT: https://randomnumber.r2.cloudflarestorage.com
  DISCOURSE_S3_CDN_URL: https://eufiles.technospider.com
  DISCOURSE_S3_BACKUP_BUCKET: exotics-unlimited-backups
  DISCOURSE_INCLUDE_S3_UPLOADS_IN_BACKUPS: true
  DISCOURSE_BACKUP_LOCATION: s3
  DISCOURSE_S3_BUCKET: exotics-unlimited
  DISCOURSE_S3_REGION: auto
  DISCOURSE_S3_ACCESS_KEY_ID: randomnumbers
  DISCOURSE_S3_SECRET_ACCESS_KEY: randomnumbers
  DISCOURSE_S3_INSTALL_CORS_RULE: false

## Контейнер Docker не имеет состояния; все данные хранятся в /shared
volumes:
  - volume:
      host: /var/discourse/shared/standalone
      guest: /shared
  - volume:
      host: /var/discourse/shared/standalone/log/var-log
      guest: /var/log

## Плагины размещаются здесь
## подробности см. по ссылке https://meta.discourse.org/t/19157
hooks:
  after_code:
    - exec:
        cd: $home/plugins
        cmd:
          - git clone https://github.com/discourse/docker_manager.git
#         - git clone https://github.com/discourse/discourse-subscriptions.git
          - git clone https://github.com/discourse/discourse-follow.git
          - git clone https://github.com/discourse/discourse-solved.git
          - git clone https://github.com/communiteq/discourse-private-topics.git
#         - git clone https://github.com/discourse/discourse-assign.git
          - git clone https://github.com/tknospdr/discourse-auto-remove-group.git
          - git clone https://github.com/discourse/discourse-topic-voting.git
          - git clone https://github.com/discourse/discourse-livestream.git
#         - git clone https://github.com/discourse/discourse-calendar.git
          - git clone https://github.com/jannolii/discourse-topic-trade-buttons.git
##        - git clone https://github.com/tknospdr/force-tag-group-order.git

## Хуки для S3
  after_assets_precompile:
    - exec:
        cd: $home
        cmd:
          - sudo -E -u discourse bundle exec rake s3:upload_assets
          - sudo -E -u discourse bundle exec rake s3:expire_missing_assets

После пересборки мой сайт перестал работать из-за отсутствия множества файлов, поэтому я попытался перенести их на сервер с помощью rake и получил следующую ошибку для каждого файла:

root@talk-app:/var/www/discourse# rake uploads:migrate_to_s3
Обратите внимание, что миграция на S3 в настоящее время необратима! 
[CTRL+c] для отмены, [ENTER] для продолжения

Миграция загрузок на S3 для 'default'...
Загрузка файлов на S3...
 - Список локальных файлов
 => 31 файл
 - Список файлов S3
. => 4 файла
 - Синхронизация файлов с S3
#<Thread:0x00007ff89dcbcb20 /var/www/discourse/lib/file_store/to_s3_migration.rb:212 run> завершен с ошибкой (report_on_exception установлен в true):
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/aws-sdk-core-3.226.0/lib/seahorse/client/plugins/raise_response_errors.rb:17:in `call': Вы можете указать только одну нестандартную контрольную сумму одновременно. (Aws::S3::Errors::InvalidRequest)
    from /var/www/discourse/vendor/bundle/ruby/3.3.0/gems/aws-sdk-s3-1.182.0/lib/aws-sdk-s3/plugins/sse_cpk.rb:24:in `call'
    from /var/www/discourse/vendor/bundle/ruby/3.3.0/gems/aws-sdk-s3-1.182.0/lib/aws-sdk-s3/plugins/dualstack.rb:21:in `call'
    from /var/www/discourse/vendor/bundle/ruby/3.3.0/gems/aws-sdk-s3-1.182.0/lib/aws-sdk-s3/plugins/accelerate.rb:43:in `call'
    from /var/www/discourse/vendor/bundle/ruby/3.3.0/gems/aws-sdk-core-3.226.0/lib/aws-sdk-core/plugins/checksum_algorithm.rb:169:in `call'
    from /var/www/discourse/vendor/bundle/ruby/3.3.0/gems/aws-sdk-core-3.226.0/lib/aws-sdk-core/plugins/jsonvalue_converter.rb:16:in `call'
    from /var/www/discourse/vendor/bundle/ruby/3.3.0/gems/aws-sdk-core-3.226.0/lib/aws-sdk-core/plugins/invocation_id.rb:16:in `call'
    from /var/www/discourse/vendor/bundle/ruby/3.3.0/gems/aws-sdk-core-3.226.0/lib/aws-sdk-core/plugins/idempotency_token.rb:19:in `call'
    from /var/www/discourse/vendor/bundle/ruby/3.3.0/gems/aws-sdk-core-3.226.0/lib/aws-sdk-core/plugins/param_converter.rb:26:in `call'
    from /var/www/discourse/vendor/bundle/ruby/3.3.0/gems/aws-sdk-core-3.226.0/lib/seahorse/client/plugins/request_callback.rb:89:in `call'
    from /var/www/discourse/vendor/bundle/ruby/3.3.0/gems/aws-sdk-core-3.226.0/lib/aws-sdk-core/plugins/response_paging.rb:12:in `call'
    from /var/www/discourse/vendor/bundle/ruby/3.3.0/gems/aws-sdk-core-3.226.0/lib/seahorse/client/plugins/response_target.rb:24:in `call'
    from /var/www/discourse/vendor/bundle/ruby/3.3.0/gems/aws-sdk-core-3.226.0/lib/aws-sdk-core/plugins/telemetry.rb:39:in `block in call'
    from /var/www/discourse/vendor/bundle/ruby/3.3.0/gems/aws-sdk-core-3.226.0/lib/aws-sdk-core/telemetry/no_op.rb:29:in `in_span'
    from /var/www/discourse/vendor/bundle/ruby/3.3.0/gems/aws-sdk-core-3.226.0/lib/aws-sdk-core/plugins/telemetry.rb:53:in `span_wrapper'
    from /var/www/discourse/vendor/bundle/ruby/3.3.0/gems/aws-sdk-core-3.226.0/lib/aws-sdk-core/plugins/telemetry.rb:39:in `call'
    from /var/www/discourse/vendor/bundle/ruby/3.3.0/gems/aws-sdk-core-3.226.0/lib/seahorse/client/request.rb:72:in `send_request'
    from /var/www/discourse/vendor/bundle/ruby/3.3.0/gems/aws-sdk-s3-1.182.0/lib/aws-sdk-s3/client.rb:17315:in `put_object'
    from /var/www/discourse/lib/file_store/to_s3_migration.rb:215:in `block (2 levels) in migrate_to_s3'

Буду очень признателен за советы, как завершить этот процесс тем или иным способом.

Отсутствующие файлы, скорее всего, являются ресурсами (assets), поэтому вам нужна задача rake для их отправки в S3 (s3:upload_assets — она находится в верхней части списка).

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

Кажется, есть тема о том, как это сделать. Я делал это на одном-двух сайтах, но не уверен, как именно и где это задокументировано.

Я думаю, речь может идти об этой теме:

2 лайка

Мне нужно запускать это, даже если это часть изменений, которые я внес в файл app.yml? Мне казалось, что это нужно для автоматической загрузки файлов при пересборке.

Только что попробовал. Вот вывод:


root@talk-app:/var/www/discourse# rake s3:upload_assets
Установка правил CORS...
пропуск
Пропуск: assets/logo-single-3f9a3693.png
Пропуск: assets/favicon-7e45025e.ico
Пропуск: assets/logo-single-dev-0d38377d.png
Пропуск: assets/push-notifications/posted-e02e1c60.png
Пропуск: assets/push-notifications/watching_first_post-e02e1c60.png
Пропуск: assets/push-notifications/README-d49cc975.md
(длинный список...)
Пропуск: assets/plugins/footnote_extra-95ffab71.gz.js

Вам не следует этого делать, но именно эти действия могут привести к тому, что ваш сайт будет «сломан» (или для вас «сломан» означает «отсутствуют изображения»?). Загрузка изображений с помощью migrate_to_s3 влияет только на изображения.

Мне не совсем понятно, как все ассеты уже были загружены (что было сломано на сайте? Как они могли быть загружены, если ваша настройка S3 неисправна?)

Можете ли вы загружать какие-либо изображения на вашем сайте?

Сейчас я не могу ничего сделать на сайте.
Чувствуйте себя свободно, посмотрите на него и проверьте. https://eu.technospider.com

Поскольку всё, похоже, находится в моём бакете, вероятно, нужно обновить какую-то переменную окружения, чтобы всё работало правильно.
Если нам удастся решить эту проблему, мы сможем сказать, что R2 готова к использованию в production.

Этот (и множество других файлов) отсутствует по адресу https://eufiles.technospider.com/extra-locales/ca382c69f8e6b85162b2ba58f2ce100bfe741966/en/mf.js?__ws=eu.technospider.com

Это ваш CDN или ваше хранилище (bucket)? Существует ли этот файл в вашем хранилище? Возможно, он есть в хранилище, но ваш CDN не работает?

Вот как я когда-то настраивал R2, и, кажется, это сработало.

            - "DISCOURSE_S3_REGION: 'auto'"
            - "DISCOURSE_S3_ENDPOINT: https://some-number.r2.cloudflarestorage.com"
            - "DISCOURSE_S3_ACCESS_KEY_ID: 'keyid'"
            - "DISCOURSE_S3_SECRET_ACCESS_KEY: 'secret'"
            - "DISCOURSE_S3_CDN_URL: 'https://r2.myforum.us/xyz'"
            - "DISCOURSE_CDN_URL: 'https://r2.literatecomputing.com'"
            - "DISCOURSE_S3_BUCKET: 'myforum/xyz'"
            - "DISCOURSE_S3_BACKUP_BUCKET: 'myforum/xyz/backups'"

Значит, это никогда не работало?

1 лайк

Где должен находиться каталог «extra-locales»? Я не вижу его ни в «public», ни в «assets», даже внутри контейнера. Куда мне смотреть?

Извините за глупые вопросы, но это совершенно новое дело для меня.
Что именно является моим CDN или моим хранилищем?

С ведущими тире и всеми одинарными и двойными кавычками? У меня в файле app.yml нет ничего подобного. Мне стоит добавить их и пересобрать для проверки?
Вот точный вид моего файла, каждый элемент отступлен на 2 пробела:

## Этот набор строк позволяет загружать и скачивать файлы, размещенные на R2 S3..
  DISCOURSE_CDN_URL: https://eufiles.technospider.com
  DISCOURSE_USE_S3: true
  DISCOURSE_S3_ENDPOINT: https://randomnumber.r2.cloudflarestorage.com
  DISCOURSE_S3_CDN_URL: https://eufiles.technospider.com
  DISCOURSE_S3_BACKUP_BUCKET: exotics-unlimited-backups
  DISCOURSE_INCLUDE_S3_UPLOADS_IN_BACKUPS: true
  DISCOURSE_BACKUP_LOCATION: s3
  DISCOURSE_S3_BUCKET: exotics-unlimited
  DISCOURSE_S3_REGION: auto
  DISCOURSE_S3_ACCESS_KEY_ID: randomnumbers
  DISCOURSE_S3_SECRET_ACCESS_KEY: randomnumbers
  DISCOURSE_S3_INSTALL_CORS_RULE: false

Это работало, когда я вводил настройки через веб-интерфейс, но когда я перенес всё в файл app.yml, вы увидели то, что увидели, зайдя на сайт.

Вот что я вижу, когда пытаюсь получить доступ к одному из ваших ресурсов:

Этот объект не существует или недоступен по этому URL-адресу. Проверьте URL-адрес объекта, который вы ищете, или свяжитесь с владельцем, чтобы включить публичный доступ.

Вы можете проверить, работает ли https://eufiles.technospider.com/extra-locales/ca382c69f8e6b85162b2ba58f2ce100bfe741966/en/mf.js?__ws=eu.technospider.com, если измените имя хоста на вашу конечную точку Cloudflare.

Вы можете найти этот файл в своём бакете? Вы можете получить к нему доступ?

Не знаю, но это URL-адрес, который я скопировал из инструментов разработчика в браузере.

Сначала найдите этот файл в своём бакете и проверьте, существует ли он вообще, а затем сможете разобраться, почему CDN не может его найти.

Нет. Я использую другой инструмент для конфигурации, но это настройки ENV, которые, насколько я помню, у меня когда-то работали.

Понятно. Это раздражает. Удачи.

У меня выводится:

Этот XML-файл не имеет связанной с ним информации о стилях. Ниже показано дерево документа.
<Error>
<Code>InvalidArgument</Code>
<Message>Authorization</Message>
</Error>

Моя конечная точка:
https://7100e60b936991e069a3230dc05d4976.r2.cloudflarestorage.com/exotics-unlimited/

Я только что изменил

DISCOURSE_S3_CDN_URL: https://eufiles.technospider.com

на

DISCOURSE_S3_CDN_URL: https://eufiles.technospider.com/exotics-unlimited

И теперь у меня бесконечный индикатор загрузки, который не исчезает.
Прогресс? Кто знает. :slight_smile:

Найдите ресурс, к которому можно получить доступ по URL-адресу бакета, а затем узнайте, как получить доступ к тому же ресурсу через CDN.

Прошу прощения за незнание, но в чём разница между bucket и CDN?

Бакет — это та «главная директория», которую вы создали и где находятся все файлы. CDN — это множество серверов по всему миру, которые получают копию этого бакета. Ваш бакет идентифицируется по URL, который вы указали при создании подключения, например cdn.example.com.

Похоже, что в R2 CDN создается автоматически, если вы указываете пользовательский домен для бакета. Это немного запутанно, так как мне не пришлось ничего делать с CDN.

Я посмотрю, что смогу выяснить.

Похоже, что независимо от моих попыток, я не могу получить доступ к объектам по URL-адресу конечной точки R2.

https://7100***********dc05d4976.r2.cloudflarestorage.com/exotics-unlimited/assets/logo-815195ae.png

и

https://exotics-unlimited.7100***********dc05d4976.r2.cloudflarestorage.com/assets/logo-815195ae.png

Выдают ошибку:

Этот XML-файл не имеет связанной с ним информации о стилях. Ниже показано дерево документа.
<Error>
<Code>InvalidArgument</Code>
<Message>Authorization</Message>
</Error>

Но через CDN:

![discourse](upload://4axzzMIqD328iAou0u6qv18Avo8.png)

Показывает:
discourse
Так как ошибка касается авторизации, я немного изучил этот вопрос и наткнулся на следующее замечание:

Примечание

По умолчанию кэшируются только определённые типы файлов. Чтобы кэшировать все файлы в вашем бакете, необходимо установить правило страницы «Cache Everything».

Для получения дополнительной информации о поведении кэша по умолчанию и способах его настройки обратитесь к поведению кэша по умолчанию

С этой страницы:

Я создал правило «кэшировать всё», но изменений не произошло.