Эта тема описывает настройку некоторых распространённых провайдеров объектного хранилища, совместимых с S3 (аналоги S3). Подробнее о конфигурации Amazon AWS S3, которая официально поддерживается и используется Discourse для наших хостинговых сервисов, см. Set up file and image uploads to S3.
| Провайдер | Название сервиса | Работает с Discourse? |
|---|---|---|
| Amazon AWS | S3 | Да |
| Digital Ocean | Spaces | Да |
| Linode | Object Storage | Да |
| Google Cloud | Storage | Да |
| Scaleway | Object Storage | Да |
| Vultr | Object Storage | Да |
| BackBlaze | Cloud Storage | Да* |
| Самохостинг | MinIO | Да |
| Azure Blob Storage | Flexify.IO | Да |
| Oracle Cloud | Object Storage | Нет [1] |
| Wasabi | Object Storage | Возможно |
| Cloudflare | R2 | Нет |
| Contabo | Object Storage | Нет |
Если вам удалось настроить другой сервис, пожалуйста, добавьте его в эту вики.
Конфигурация
Чтобы хранить статические ресурсы Discourse в вашем объектном хранилище, добавьте следующую конфигурацию в файл app.yml в секцию hooks:
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
При использовании объектного хранилища вам также потребуется CDN для раздачи содержимого бакета. В своих тестах я использовал CDN StackPath; кроме необходимости установить параметр Dynamic Caching By Header: Accept-Encoding в их конфигурации, всё работает нормально.
DISCOURSE_CDN_URL — это CDN, указывающий на ваш хостнейм Discourse и кэширующий запросы. Он будет использоваться в основном для ресурсов, которые можно вытянуть (pullable): CSS и другие ресурсы тем.
DISCOURSE_S3_CDN_URL — это CDN, указывающий на ваш бакет объектного хранилища и кэширующий запросы. Он будет использоваться в основном для ресурсов, которые можно загрузить (pushable): JS, изображения и загрузки пользователей.
Мы рекомендуем, чтобы эти значения отличались, и администраторам следует устанавливать оба параметра.
Отсутствие CDN (или указание URL бакета в качестве URL CDN) скорее всего вызовет проблемы и не поддерживается.
В следующих примерах https://falcoland-files-cdn.falco.dev — это CDN, настроенный для раздачи файлов из бакета. Имя бакета в моих примерах установлено как falcoland-files.
Рекомендуется настраивать эти параметры в переменных окружения в вашем файле app.yml, так как именно так это делает CDCK в своей инфраструктуре, что гарантирует надёжность. Кроме того, задача загрузки ресурсов выполняется после компиляции ресурсов, которая происходит при пересборке. Если вы хотите развернуть Discourse, который корректно работает с объектным хранилищем с самого начала, вам необходимо установить переменные окружения, чтобы ресурсы были загружены до запуска сайта.
Выберите провайдера из списка ниже и добавьте эти настройки в секцию env файла app.yml, соответствующим образом изменив значения:
AWS S3
То, что мы официально поддерживаем и используем внутренне. Их CDN-предложение Cloudfront также подходит для раздачи файлов из бакета. См. Set up file and image uploads to S3 для инструкций по правильной настройке прав доступа.
DISCOURSE_USE_S3: true
DISCOURSE_S3_REGION: us-west-1
DISCOURSE_S3_ACCESS_KEY_ID: myaccesskey
DISCOURSE_S3_SECRET_ACCESS_KEY: mysecretkey
DISCOURSE_S3_CDN_URL: https://falcoland-files-cdn.falco.dev
DISCOURSE_S3_BUCKET: falcoland-files
DISCOURSE_S3_BACKUP_BUCKET: falcoland-files/backups
DISCOURSE_BACKUP_LOCATION: s3
Digital Ocean Spaces
Предложение DO хорошее и работает из коробки. Можно включить ограничение списка файлов. Единственная проблема в том, что их CDN-предложение крайне неработоспособно, поэтому вам нужно использовать другой CDN для файлов. Также не следует устанавливать правило CORS, так как оно переустанавливается при каждой пересборке.
Пример конфигурации:
DISCOURSE_USE_S3: true
DISCOURSE_S3_REGION: whatever
DISCOURSE_S3_ENDPOINT: https://nyc3.digitaloceanspaces.com
DISCOURSE_S3_ACCESS_KEY_ID: myaccesskey
DISCOURSE_S3_SECRET_ACCESS_KEY: mysecretkey
DISCOURSE_S3_CDN_URL: https://falcoland-files-cdn.falco.dev
DISCOURSE_S3_BUCKET: falcoland-files
DISCOURSE_S3_BACKUP_BUCKET: falcoland-files/backups
DISCOURSE_BACKUP_LOCATION: s3
DISCOURSE_S3_INSTALL_CORS_RULE: false
Linode Object Storage
Для Linode требуется дополнительный параметр конфигурации HTTP_CONTINUE_TIMEOUT.
Пример конфигурации:
DISCOURSE_USE_S3: true
DISCOURSE_S3_REGION: us-east-1
DISCOURSE_S3_HTTP_CONTINUE_TIMEOUT: 0
DISCOURSE_S3_ENDPOINT: https://us-east-1.linodeobjects.com
DISCOURSE_S3_ACCESS_KEY_ID: myaccesskey
DISCOURSE_S3_SECRET_ACCESS_KEY: mysecretkey
DISCOURSE_S3_CDN_URL: https://falcoland-files-cdn.falco.dev
DISCOURSE_S3_BUCKET: falcoland-files
DISCOURSE_S3_BACKUP_BUCKET: falcoland-files/backup
DISCOURSE_BACKUP_LOCATION: s3
Google Cloud Platform Storage
Список файлов не работает, поэтому вам нужно добавить дополнительную переменную окружения, чтобы пропустить это, чтобы ресурсы работали. Также пропустите CORS и настройте его вручную.
Поскольку вы не можете перечислять файлы, вы не сможете перечислять резервные копии, и автоматические резервные копии будут завершаться ошибкой, поэтому мы не рекомендуем использовать это для резервного копирования. Однако некоторые пользователи предполагают, что если изменить роль с Storage Legacy Object Owner на Storage Legacy Bucket Owner, резервные копии будут работать корректно. См. эту тему для обсуждения, специфичного для Google Cloud.
Существует сторонний плагин для улучшения интеграции по адресу Discourse GCS Helper.
Пример конфигурации:
DISCOURSE_USE_S3: true
DISCOURSE_S3_REGION: us-east1
DISCOURSE_S3_INSTALL_CORS_RULE: false
FORCE_S3_UPLOADS: 1
DISCOURSE_S3_ENDPOINT: https://storage.googleapis.com
DISCOURSE_S3_ACCESS_KEY_ID: myaccesskey
DISCOURSE_S3_SECRET_ACCESS_KEY: mysecretkey
DISCOURSE_S3_CDN_URL: https://falcoland-files-cdn.falco.dev
DISCOURSE_S3_BUCKET: falcoland-files
#DISCOURSE_S3_BACKUP_BUCKET: falcoland-files/backup
#DISCOURSE_BACKUP_LOCATION: s3
Scaleway Object Storage
Предложение Scaleway также очень хорошее, и в большинстве случаев всё работает без проблем.
Загрузки multipart в Scaleway поддерживают максимум 1000 частей. Это не соответствует Amazon S3, который поддерживает максимум 10 000 частей. Для более крупных экземпляров это приведет к ошибкам резервного копирования Discourse, и незавершенную загрузку может потребоваться удалить вручную перед повторными попытками. Для небольших экземпляров это не проблема. Scaleway, похоже, открыты к обратной связи, поэтому, если вы хотите изменить этот лимит, вам следует связаться с ними.
Обратите внимание, что для параметра DISCOURSE_S3_ENDPOINT Discourse использует конечную точку всего региона: https://s3.{region}.scw.cloud. «Конечная точка бакета», найденная в панели управления Scaleway, имеет вид https://{bucketName}.s3.{region}.scw.cloud. Опустите поддомен имени бакета, чтобы избежать ошибок подключения.
Пример конфигурации:
DISCOURSE_USE_S3: true
DISCOURSE_S3_REGION: fr-par
DISCOURSE_S3_ENDPOINT: https://s3.fr-par.scw.cloud
DISCOURSE_S3_ACCESS_KEY_ID: myaccesskey
DISCOURSE_S3_SECRET_ACCESS_KEY: mysecretkey
DISCOURSE_S3_CDN_URL: https://falcoland-files-cdn.falco.dev
DISCOURSE_S3_BUCKET: falcoland-files
DISCOURSE_S3_BACKUP_BUCKET: falcoland-files/backups
DISCOURSE_BACKUP_LOCATION: s3
Vultr Object Storage
Для Vultr требуется дополнительный параметр конфигурации HTTP_CONTINUE_TIMEOUT.
Пример конфигурации:
DISCOURSE_USE_S3: true
DISCOURSE_S3_REGION: whatever
DISCOURSE_S3_HTTP_CONTINUE_TIMEOUT: 0
DISCOURSE_S3_ENDPOINT: https://ewr1.vultrobjects.com
DISCOURSE_S3_ACCESS_KEY_ID: myaccesskey
DISCOURSE_S3_SECRET_ACCESS_KEY: mysecretkey
DISCOURSE_S3_CDN_URL: https://falcoland-files-cdn.falco.dev
DISCOURSE_S3_BUCKET: falcoland-files
DISCOURSE_S3_BACKUP_BUCKET: falcoland-files/backup
DISCOURSE_BACKUP_LOCATION: s3
Backblaze B2 Cloud Storage
Вам нужно пропустить CORS и настроить его вручную.
Существуют отчеты о том, что «очистка сиротских загрузок» не работает корректно с BackBlaze. Вы должны изменить правила жизненного цикла для вашего бакета, чтобы очистка сиротских файлов работала.
Пример конфигурации:
DISCOURSE_USE_S3: true
DISCOURSE_S3_REGION: "us-west-002"
DISCOURSE_S3_INSTALL_CORS_RULE: false
DISCOURSE_S3_CONFIGURE_TOMBSTONE_POLICY: false
DISCOURSE_S3_ENDPOINT: https://s3.us-west-002.backblazeb2.com
DISCOURSE_S3_ACCESS_KEY_ID: myaccesskey
DISCOURSE_S3_SECRET_ACCESS_KEY: mysecretkey
DISCOURSE_S3_CDN_URL: https://falcoland-files-cdn.falco.dev
DISCOURSE_S3_BUCKET: falcoland-files
DISCOURSE_S3_BACKUP_BUCKET: falcoland-files/backup
DISCOURSE_BACKUP_LOCATION: s3
Примечание: При первоначальной миграции на B2 вы можете столкнуться с лимитом в 2500 бесплатных ежедневных транзакций класса C. Вам потребуется добавить способ оплаты, чтобы снять ограничения.
MinIO Storage Server
Существует несколько предостережений и требований, которые необходимо выполнить перед использованием сервера хранения MinIO в качестве альтернативы S3:
- У вас есть полностью настроенный экземпляр сервера MinIO.
- В конфигурации MinIO включена поддержка доменов для URL-адресов бакетов, управляемых доменом. Это обязательное требование для настройки MinIO и Discourse, так как MinIO всё ещё поддерживает устаревшие «путь»-стили S3, которые больше не поддерживаются в Discourse.
- Конфигурация DNS для MinIO настроена правильно, чтобы поддомены бакетов корректно разрешались на сервер MinIO, и сервер MinIO настроен с базовым доменом (в данном случае
minio.example.com). - Бакет
discourse-dataсуществует на сервере MinIO и имеет установленную политику «public». - Ваш CDN-URL S3 указывает на правильно настроенный CDN, который обслуживает бакет и кэширует запросы, как указано ранее в этом документе.
- Ваши CDN настроены на использование заголовка «Host» основного URL S3 — например,
discourse-data.minio.example.comпри извлечении данных — в противном случае это может вызвать проблемы CORB.
При условии выполнения вышеуказанных предостережений и требований, пример конфигурации может выглядеть так:
DISCOURSE_USE_S3: true
DISCOURSE_S3_REGION: anything
DISCOURSE_S3_ENDPOINT: https://minio.example.com
DISCOURSE_S3_ACCESS_KEY_ID: myaccesskey
DISCOURSE_S3_SECRET_ACCESS_KEY: mysecretkey
DISCOURSE_S3_CDN_URL: https://discourse-data-cdn.example.com
DISCOURSE_S3_BUCKET: discourse-data
DISCOURSE_S3_BACKUP_BUCKET: discourse-backups
DISCOURSE_BACKUP_LOCATION: s3
DISCOURSE_S3_INSTALL_CORS_RULE: false
CORS всё равно будет включен на MinIO, даже если правило не устанавливается пересборщиком приложения — по умолчанию, как кажется, CORS включен для всех HTTP-методов в MinIO, и в результате MinIO не поддерживает BucketCORS (API S3).
Azure Blob Storage с Flexify.IO
Azure Blob Storage не является сервисом, совместимым с S3, поэтому его нельзя использовать с Discourse. Существует плагин, но он неработоспособен.
Самый простой способ предоставить интерфейс, совместимый с S3, для Azure Blob Storage, — это добавить сервер Flexify.IO, который преобразует протокол Azure Storage в S3.
На момент написания этой статьи услуга бесплатна на Azure, и для её запуска требуется только очень базовый (дешёвый) уровень виртуальной машины. Однако это требует некоторой настройки.
- В портале Azure создайте новый ресурс
Flexify.IO - Amazon S3 API for Azure Blob Storage. - Для лёгкого использования минимальная конфигурация ВМ, похоже, работает отлично. Можно принять большинство настроек по умолчанию. Не забудьте сохранить файл ключа PEM при создании ВМ.
- Перейдите по ссылке на ВМ Flexify.IO и войдите в систему. Следуйте инструкциям, настроив поставщика данных Azure Blob Storage и сгенерированную конечную точку S3. Убедитесь, что параметр конфигурации конечной точки
Public read access to all objects in virtual bucketsустановлен в true. Скопируйте URL-адрес конечной точки S3 и ключи. - Нажмите New Virtual Bucket и создайте виртуальный бакет. Он может иметь то же имя, что и контейнер Azure Blob Storage, или другое имя. Свяжите любой(е) контейнер(ы) для объединения в этот виртуальный бакет. Этот виртуальный бакет используется для предоставления общедоступного бакета через S3.
- По умолчанию Flexify.IO устанавливает самоподписанный SSL-сертификат, тогда как конечная точка S3 требует HTTPS. Подключитесь по SSH к ВМ, используя файл ключа (имя пользователя по умолчанию
azureuser), и замените следующие файлы правильными файлами:
/etc/flexify/ssl/cert.pem— замените на файл сертификата (кодировка PEM)/etc/flexify/ssl/key.pem— замените на файл закрытого ключа (кодировка PKCS#8 PEM, это тот, который начинается сBEGIN PRIVATE KEY, а неBEGIN RSA PRIVATE KEY, который является PKCS#1)
Эти файлы принадлежат root, поэтому для их замены потребуется sudo. Лучше всего убедиться, что заменяемые файлы имеют те же владельца и права доступа, что и оригинальные, то есть root:root и права 600.
6. По умолчанию Flexify.IO создаёт корневой уровень сервиса S3 с несколькими бакетами. Discourse требует поддержки поддоменов для бакетов. Перейдите по адресу: <IP-адрес вашей ВМ Flexify.IO>/flexify-io/manage/admin/engines/configs/1, что откроет скрытую страницу конфигурации!
7. Укажите базовый домен S3 (например, s3.mydomain.com) в поле Endpoint hostname, которое по умолчанию должно быть пустым. Нажмите Save, чтобы сохранить настройку.
8. Перезапустите ВМ Flexify.IO в портале Azure.
9. В вашей DNS настройте сопоставление s3.mydomain.com и *.s3.mydomain.com с IP-адресом ВМ Flexify.IO.
10. В Discourse установите следующие параметры на странице администратора (да, нет необходимости помещать настройки в app.yml):
use s3: true
s3 region: anything
s3 endpoint: https://s3.mydomain.com
s3 access key: myaccesskey
s3 secret assess key: mysecret key
s3 cdn url: https://<azure-blob-account>.blob.core.windows.net/<container>
s3 bucket: <virtual bucket>
s3 backup bucket: <backup bucket> (подойдёт любой контейнер, так как он не требует общедоступного чтения, и Flexify.IO автоматически предоставит к нему доступ)
backup location: s3
Использование одного и того же бакета для продакшена и тестовой среды не рекомендуется. Если вы всё же сделаете это, примите меры, чтобы ваша тестовая среда не удаляла ресурсы продакшена (установите s3 disable cleanup как минимум и следите за удалением резервных копий продакшена).
Wasabi
@pfaffman пробовал Wasabi для резервного копирования, но оно, казалось, периодически и незаметно завершалось ошибкой, оставляя резервные копии на жёстком диске и в конечном итоге заполняя диск. Ни Wasabi, ни meta не дали никаких подсказок, поэтому я не рекомендую его, хотя ваш опыт может отличаться. @pfaffman теперь довольно уверен, что эта проблема была вызвана тем, что резервное копирование и автоматические перезагрузки каким-то образом планировались одновременно; он использовался только для резервного копирования, но, похоже, работал нормально. Если кто-то захочет попробовать и сообщить здесь, это должно работать, по крайней мере, для резервного копирования.
Oracle Cloud
Oracle Cloud не поддерживает доступ к бакетам в стиле виртуальных хостов и не будет работать.
Cloudflare
Предложение Cloudflare несовместимо. В ходе тестирования @fearlessfrog подал заявку в Cloudflare, и в декабре 2022 года они ответили:
Contabo
@tuxed пытался заставить объектное хранилище Contabo работать для загрузки, совместимой с S3. Похоже, что при загрузке оно добавляет префикс имени репозитория в URL, и ему не удалось заставить это работать.
Безопасные загрузки
Безопасные загрузки поддерживаются только для AWS S3. Если ваша команда rake uploads:migrate_to_s3 завершается ошибкой, вам следует ввести следующие команды, чтобы сначала подсчитать, а затем пометить как небезопасные те загрузки, которые, как вы знаете, не требуют безопасности. В этом случае вам нужно будет использовать AWS S3.
./launcher enter app
rails c
Upload.where(secure: true).count
Upload.where(secure: true).update_all(secure:false)