В этой теме описывается настройка некоторых распространенных поставщиков объектного хранилища, совместимого с 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 | Да* |
| Self-hosted | 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 для обслуживания файлов, хранящихся в бакете. В своих тестах я использовал StackPath CDN, и, за исключением необходимости установить Dynamic Caching By Header: Accept-Encoding в его конфигурации, он работает нормально.
DISCOURSE_CDN_URL — это CDN, указывающий на ваше доменное имя Discourse и кэширующий запросы. Он будет использоваться в основном для извлекаемых ресурсов: CSS и других ресурсов тем.
DISCOURSE_S3_CDN_URL — это CDN, указывающий на ваш бакет объектного хранилища и кэширующий запросы. Он будет использоваться в основном для загружаемых ресурсов: 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 также очень хорошее, и в большинстве случаев все работает нормально.
Мultipart-загрузки Scaleway поддерживают только максимум 1000 частей. Это не соответствует Amazon S3, который поддерживает максимум 10 000 частей. Для больших экземпляров это приведет к сбоям резервного копирования Discourse, и незавершенную загрузку может потребоваться удалить вручную перед новыми попытками. Для небольших экземпляров это не проблема. Scaleway довольно открыты для обратной связи, поэтому, если вы хотите изменить это ограничение, вам следует связаться с ними.
Обратите внимание, что для параметра DISCOURSE_S3_ENDPOINT Discourse использует конечную точку всего региона: https://s3.{region}.scw.cloud. «Конечная точка бакета», найденная в вашей панели управления Scaleway, имеет вид https://{bucketName}.s3.{region}.scw.cloud. Оmitите поддомен имени бакета, чтобы избежать ошибок подключения.
Пример конфигурации:
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 и имеет установленную «публичную» политику - Ваш URL S3 CDN указывает на правильно настроенный 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, даже если правило не установлено перекомпилятором приложения — по умолчанию, кажется, в MinIO CORS включен для всех HTTP-глаголов, и MinIO не поддерживает BucketCORS (S3 API) в результате.
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 и ключи. - Нажмите Новый виртуальный бакет и создайте виртуальный бакет. Он может иметь то же имя, что и контейнер 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.
- По умолчанию Flexify.IO создает корневой сервис S3 с несколькими бакетами. Discourse требует поддержки поддоменов для бакетов. Перейдите по адресу:
<IP-адрес вашей ВМ Flexify.IO>/flexify-io/manage/admin/engines/configs/1, который откроет скрытую страницу конфигурации! - Укажите базовый домен S3 (допустим, это
s3.mydomain.com) в полеEndpoint hostname, которое по умолчанию должно быть пустым. Нажмите Сохранить, чтобы сохранить настройку. - Перезапустите ВМ Flexify.IO в портале Azure.
- В вашем DNS сопоставьте
s3.mydomain.comи*.s3.mydomain.comс IP-адресом ВМ Flexify.IO. - В 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
Не рекомендуется использовать один и тот же бакет для production и staging. Если вы все же это сделаете, примите меры, чтобы ваш staging-сайт не удалял ваши production-ресурсы (установите s3 disable cleanup как минимум, и следите за тем, чтобы он не удалял резервные копии production).
Wasabi
@pfaffman попробовал wasabi для резервных копий, но, казалось, он периодически и бесшумно не работал, оставляя резервные копии на жестком диске и в конечном итоге заполняя его. Ни wasabi, ни meta не имели никаких подсказок, поэтому я не рекомендую его, хотя ваш опыт может отличаться. @pfaffman теперь довольно уверен, что эта проблема была вызвана тем, что резервное копирование и автоматическая перезагрузка как-то были запланированы одновременно; он использовался только для резервных копий, но, казалось, работал нормально. Если кто-то хочет попробовать и сообщить здесь, это должно работать, по крайней мере, для резервных копий.
Oracle Cloud
Oracle Cloud не поддерживает доступ к бакетам в стиле виртуального хоста и не будет работать
Cloudflare R2
Cloudflare R2 совместим с объектным хранилищем S3 при использовании CDN Cloudflare. Бесплатный план Cloudflare предлагает 10 ГБ хранилища, чего должно быть более чем достаточно для нужд большинства форумов.
Чтобы настроить Cloudflare R2, вам нужно будет настроить соответствующие параметры в панели управления Cloudflare в разделе R2 Object Storage.
В зависимости от ваших потребностей (загрузки или резервные копии или оба), вот соответствующие параметры, которые нужно вставить в ваш файл app.yml или в поиск Admin-All site settings по запросу S3:
DISCOURSE_ENABLE_S3_UPLOADS: true
DISCOURSE_S3_REGION: auto
DISCOURSE_S3_ENDPOINT: https://<your-account-id>.r2.cloudflarestorage.com
DISCOURSE_S3_ACCESS_KEY_ID: "xxx"
DISCOURSE_S3_SECRET_ACCESS_KEY: "xxx"
DISCOURSE_S3_UPLOAD_BUCKET: your-upload-bucket-name
DISCOURSE_S3_CDN_URL: https://uploads.yourdomain.com
# DISCOURSE_S3_USE_CDN_URL_FOR_ALL_UPLOADS: true
DISCOURSE_ENABLE_DIRECT_S3_UPLOADS: true
DISCOURSE_S3_USE_ACLS: false
DISCOURSE_BACKUP_LOCATION: s3
DISCOURSE_S3_BACKUP_BUCKET: your-backup-bucket-name
Если вы не хотите редактировать свой app.yml, вы можете сделать это в интерфейсе администратора:
«Admin → All site settings» (поиск по S3):
- Enable S3 uploads =
true - Enable direct S3 uploads =
true - S3 access key ID =
"xxx" - S3 secret access key =
"xxx" - S3 region =
any - S3 upload bucket =
your upload bucket name - S3 endpoint =
https://<your-account-id>.r2.cloudflarestorage.com - S3 CDN URL =
https://uploads.yourdomain.com - S3 use ACLs =
false(отключите это!) - S3 backup bucket =
your backup bucket name - Backup location =
S3
Важные примечания по настройке Cloudflare R2:
- При настройке вашего
app.ymlилиweb_only.ymlдля Cloudflare R2 только установитеDISCOURSE_S3_CDN_URL. НЕ устанавливайтеDISCOURSE_CDN_URL. Если вы проксируете свой основной домен через Cloudflare, он уже кэширует и обслуживает ресурсы вашего приложения автоматически. Если вы попытаетесь настроить отдельныйDISCOURSE_CDN_URLс использованием DNS Cloudflare, строгая маршрутизация хостов NGINX в Discourse отклонит запросы, что приведет к бесконечным циклам перенаправления 301, блокировкам политики CORS и неработоспособности сайта.
- Оставьте
DISCOURSE_CDN_URLзакомментированным. - Установите
DISCOURSE_S3_CDN_URL: https://your-r2-custom-domain.com
-
Разрешения токена API: Поскольку в Discourse есть только один набор полей учетных данных, токен API, который вы генерируете в Cloudflare, должен иметь разрешение на доступ как к вашему бакету загрузок, так и к вашему бакету резервных копий. При создании токена выберите либо «Применить ко всем бакетам», либо используйте «Применить к определенным бакетам» и убедитесь, что оба отмечены. Также обязательно отметьте
Object Read & Writeпри создании ключа API (по умолчанию толькоObject Read only). -
При копировании URL конечного пункта из Cloudflare он может добавлять имя бакета к URL — вы должны удалить имя бакета из конца строки в вашем файле
.yml(или настройках администратора), если оно будет вставлено. -
Раскомментируйте
# DISCOURSE_S3_USE_CDN_URL_FOR_ALL_UPLOADS: true, если вы хотите использовать свой бакет загрузок R2 для всех загрузок, включая файлыPDFиZIP. (Обратите внимание, что это сделает все загруженные файлы общедоступными по прямой ссылке) -
Если вы включаете
DISCOURSE_ENABLE_DIRECT_S3_UPLOADS(true), то вы должны отключитьDISCOURSE_S3_USE_ACLS(false). Это связано с тем, что Cloudflare R2 использует разрешения на уровне бакета; ваш бакет загрузок должен быть публичным, а бакет резервных копий — частным. Для загрузок Cloudflare R2 вам НЕ нужно настраивать задачи rake правил CORS или писать IAM json, поскольку вы настроите это в панели управления Cloudflare при настройке разрешений вашего бакета. Токен Cloudflare «Object Read & Write» автоматически предоставляет разрешения на multipart-загрузку, и вставка следующего правила CORS непосредственно в настройки бакета загрузок R2 в панели управления Cloudflare в разделеCORS Policyзаменяет необходимость выполнения задачи rake.
[
{
"AllowedOrigins": [
"https://forum.yourdomain.com"
],
"AllowedMethods": [
"GET",
"PUT",
"POST",
"DELETE",
"HEAD"
],
"AllowedHeaders": [
"*"
],
"ExposeHeaders": [
"ETag"
],
"MaxAgeSeconds": 3000
}
]
См. также эту тему для получения дополнительной информации о настройке Cloudflare: Using Discourse with Cloudflare: Best Practices
Contabo
@tuxed пытался заставить Contabo Object Storage работать для загрузок, совместимых с 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)