本主题涵盖如何配置一些常见的 S3 兼容对象存储提供商(S3 克隆版)。有关 Amazon AWS S3 配置的更多详细信息,请参阅 https://meta.discourse.org/t/setting-up-file-and-image-uploads-to-s3/7229,这是官方支持并由 Discourse 内部用于其托管服务的配置。
| 提供商 | 服务名称 | 是否适用于 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
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 的具体讨论,请参阅 此主题。
有一个第三方插件可以改善集成,详见 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 存储服务器
在使用 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 上启用——默认情况下,似乎,CORS 在 MinIO 的所有 HTTP 动词上均已启用,因此 MinIO 不支持 BucketCORS(S3 API)。
使用 Flexify.IO 的 Azure Blob Storage
Azure Blob Storage 不是 S3 兼容服务,因此无法与 Discourse 一起使用。有一个插件,但它已损坏。
为 Azure Blob Storage 提供 S3 兼容接口的最简单方法是添加一个 Flexify.IO 服务器,该服务器将 Azure Storage 协议 转换 为 S3。
截至撰写本文时,该服务在 Azure 上是免费的,您只需要一个非常基本(便宜)的 VM 层级即可开始运行。不过,它需要一些设置。
- 在 Azure 门户中,创建一个名为
Flexify.IO - Amazon S3 API for Azure Blob Storage的新资源。 - 对于轻量级使用,最小 VM 配置似乎可以正常工作。您可以接受大多数默认配置。请记住在创建 VM 时保存 PEM 密钥文件。
- 浏览到 Flexify.IO VM 链接并进入系统。按照说明设置 Azure Blob Storage 数据提供程序和生成的 S3 端点。确保端点配置设置
Public read access to all objects in virtual buckets为 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
不建议在生产环境和 staging 环境中使用同一个桶。如果您仍然这样做,请采取措施确保您的 staging 站点不会删除您的生产资源(至少设置 s3 disable cleanup,并注意它是否会删除生产的备份)。
Wasabi
@pfaffman 尝试使用 Wasabi 进行备份,但它似乎间歇性地静默失败,导致备份留在硬盘上并最终填满磁盘。Wasabi 和 meta 都没有任何线索,因此我不推荐它,尽管您的体验可能有所不同。 @pfaffman 现在相当确定这个问题是由于备份和自动重启被安排在同一时间导致的;它仅用于备份,但似乎运行正常。如果有人想尝试并在此报告,它应该可以工作,至少对于备份而言。
Oracle Cloud
Oracle Cloud 不支持虚拟主机风格的桶访问 并且 无法工作
Cloudflare R2
要配置 Cloudflare R2,您需要在 Cloudflare 仪表板下的 R2 对象存储中配置相关设置。
根据您的需求(上传、备份或两者兼有),以下是需要插入到 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,可以在管理 UI 中执行此操作:
“Admin → All site settings”(搜索 S3):
- 启用 S3 上传 =
true - 启用直接 S3 上传 =
true - S3 访问密钥 ID =
"xxx" - S3 秘密访问密钥 =
"xxx" - S3 区域 =
any - S3 上传桶 =
your upload bucket name - S3 端点 =
https://<your-account-id>.r2.cloudflarestorage.com - S3 CDN URL =
https://uploads.yourdomain.com - S3 使用 ACLs =
false(禁用此项!) - S3 备份桶 =
your backup bucket name - 备份位置 =
S3
注意事项:
-
API 令牌权限:由于 Discourse 只有一组凭据字段,您在 Cloudflare 中生成的 API 令牌必须具有访问上传桶和备份桶的权限。创建令牌时,请选择“应用于所有桶”或使用“应用于特定桶”并确保两者都被选中。此外,在创建 API 密钥时,请确保勾选
Object Read & Write(默认为仅Object Read only)。 -
从 Cloudflare 复制端点 URL 时,它可能会在 URL 末尾附加桶名称——如果您的
.yml文件中粘贴了该名称,请将其删除。 -
如果您希望使用 R2 上传桶进行所有上传(包括
PDF和ZIP文件),请取消注释# DISCOURSE_S3_USE_CDN_URL_FOR_ALL_UPLOADS: true。(请注意,这将使所有上传的文件通过直接链接公开可用) -
如果启用
DISCOURSE_ENABLE_DIRECT_S3_UPLOADS(true),则应禁用DISCOURSE_S3_USE_ACLS(false)。这是因为 Cloudflare R2 使用桶级权限;您的上传桶应为公开,备份桶应为私有。对于 Cloudflare R2 上传,您 不需要 配置 CORS 规则 rake 任务或编写 IAM json,因为您可以在设置桶权限时在 Cloudflare 仪表板中进行配置。Cloudflare 的“Object Read & Write”令牌会自动授予多部分上传权限,将以下 CORS 规则直接粘贴到 Cloudflare 仪表板的 R2 上传桶设置下的CORS Policy中,即可替代 rake 任务。
[
{
"AllowedOrigins": [
"https://forum.yourdomain.com"
],
"AllowedMethods": [
"GET",
"PUT",
"POST",
"DELETE",
"HEAD"
],
"AllowedHeaders": [
"*"
],
"ExposeHeaders": [
"ETag"
],
"MaxAgeSeconds": 3000
}
]
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 不支持虚拟主机风格的桶访问,并且 无法工作 ↩︎

