本主题介绍如何配置一些常见的 S3 兼容对象存储提供商(S3 克隆版)。有关 Amazon AWS S3 配置的更多详细信息(该配置是官方支持的,并且 Discourse 内部用于我们的托管服务),请参阅 https://meta.discourse.org/t/setting-up-file-and-image-uploads-to-s3/7229。
| 提供商 | 服务名称 | 是否适用于 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 来提供存储在桶中的内容。我在测试中使用了 StackPath CDN,除了需要在他们的配置中设置Dynamic Caching By Header: Accept-Encoding外,其他方面运行正常。
DISCOURSE_CDN_URL 是一个指向您 Discourse 主机名并缓存请求的 CDN。它主要用于可拉取的资源:CSS 和其他主题资源。
DISCOURSE_S3_CDN_URL 是一个指向您对象存储桶并缓存请求的 CDN。它主要用于可推送的资源:JS、图片和用户上传。
我们建议这两个地址不同,并且管理员应同时设置两者。
不使用 CDN(或将桶 URL 作为 CDN URL 输入)可能会导致问题,且不受支持。
在以下示例中,https://falcoland-files-cdn.falco.dev 是一个配置为提供桶下文件的 CDN。在我的示例中,桶名称设置为 falcoland-files。
建议在您的 app.yml 中通过环境变量配置这些设置,因为这是 CDCK 在其基础设施中采用的方式,因此经过充分测试。此外,上传资源的任务发生在资源编译之后,而资源编译发生在重建过程中。如果您希望从一开始就运行一个能正常与对象存储配合工作的 Discourse,则需要设置环境变量,以便在站点启动前上传资源。
从下面的列表中选择您的提供商,并将这些设置添加到 app.yml 文件的 env 部分,相应地调整值:
AWS S3
这是我们官方支持并在内部使用的服务。他们的 CDN 产品 Cloudfront 也可以用于提供桶文件。有关如何正确配置权限,请参阅 https://meta.discourse.org/t/setting-up-file-and-image-uploads-to-s3/7229。
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
Digital Ocean 的产品表现良好,开箱即用。启用“限制文件列表”功能是可以的。唯一的问题是他们的 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 的特定讨论,请参阅 此主题。
有一个第三方插件可以更好地集成,详见 https://meta.discourse.org/t/discourse-gcs-helper/247705。
示例配置:
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 的产品也非常好,大部分功能都能正常工作。
Scaleway 的多部分上传仅支持 最多 1,000 个部分。这与 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 并手动配置它。
有 报告 指出 clean up orphan uploads(清理孤儿上传)无法在 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 仍支持不再受 Discourse 支持的旧版 S3“路径”样式。
- 您已为 MinIO 正确设置了 DNS 配置,以便桶子域名能正确解析到 MinIO 服务器,并且 MinIO 服务器已配置了基础域(在此例中为
minio.example.com) - 桶
discourse-data存在于 MinIO 服务器上,并且已对其设置了“公开”策略 - 您的 S3 CDN URL 指向一个正确配置的 CDN,该 CDN 指向桶并缓存请求,如本文档前面所述。
- 您的 CDN 配置为在实际获取数据时使用核心 S3 URL 的“Host”标头——例如
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 在所有 HTTP 动词上启用了 CORS,因此 MinIO 不支持 BucketCORS(S3 API)。
Azure Blob Storage with Flexify.IO
Azure Blob Storage 不是 S3 兼容服务,因此无法与 Discourse 一起使用。有一个插件,但它已损坏。
为 Azure Blob Storage 提供 S3 兼容接口的最简单方法是添加一个 Flexify.IO 服务器,该服务器将 Azure 存储协议 翻译 为 S3。
截至撰写本文时,该服务在 Azure 上是免费的,您只需要一个非常基本(便宜)的 VM 层级即可开始运行。不过,它确实需要一些设置。
- 在 Azure 门户中,创建一个名为
Flexify.IO - Amazon S3 API for Azure Blob Storage的新资源。 - 对于轻度使用,最低 VM 配置似乎就足够了。您可以接受大多数默认配置。创建 VM 时,请务必保存 PEM 密钥文件。
- 浏览到 Flexify.IO VM 链接并进入系统。按照说明设置 Azure Blob Storage 数据提供程序和生成的 S3 端点。确保端点配置设置
虚拟桶中所有对象的公共读取访问为 true。复制 S3 端点 URL 和密钥。 - 按下 New Virtual Bucket 并创建一个虚拟桶。它可以与您的 Azure Blob Storage 容器同名,也可以是不同的名称。链接任何容器以合并到此虚拟桶中。此虚拟桶用于通过 S3 暴露一个公开可读的桶。
- 默认情况下,Flexify.IO 安装自签名 SSL 证书,而 S3 端点需要 HTTPS。使用密钥文件 SSH 到 VM(默认用户名为
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 需要桶的 子域名 支持。转到:
<your Flexify.IO VM IP>/flexify-io/manage/admin/engines/configs/1,这将打开一个 隐藏 配置页面! - 在
Endpoint hostname字段中指定 S3 基础域(例如s3.mydomain.com),该字段默认应为空白。按下 Save 保存设置。 - 在 Azure 门户中重启 Flexify.IO VM。
- 在您的 DNS 中,将
s3.mydomain.com和*.s3.mydomain.com映射到 Flexify.IO VM IP。 - 在 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 年 12 月他们回复说:
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)
Oracle Cloud 不支持虚拟主机风格的桶访问,并且 无法正常工作 ↩︎

