本主题介绍如何配置一些常见的 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 | 对象存储 | 是 |
| Google Cloud | 存储 | 是 |
| Scaleway | 对象存储 | 是 |
| Vultr | 对象存储 | 是 |
| BackBlaze | 云存储 | 是* |
| 自托管 | MinIO | 是 |
| Azure Blob Storage | Flexify.IO | 是 |
| Oracle Cloud | 对象存储 | 否 [1] |
| Wasabi | 对象存储 | 可能 |
| Cloudflare | R2 | 是 |
| Contabo | 对象存储 | 否 |
如果您有其他服务可以正常工作,请将其添加到本 wiki 中。
配置
为了将 Discourse 静态资源存储在对象存储中,请在 hooks 部分下的 app.yml 中添加以下配置:
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 也可以用于前置桶文件。请参阅 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 对象存储
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 存储
文件列表功能有问题,因此您需要额外的环境变量来跳过该功能,以便资源可以正常工作。同时跳过 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 对象存储
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 对象存储
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 云存储
您需要跳过 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)。
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 端点。确保端点配置设置
Public read access to all objects in virtual buckets为 true。复制 S3 端点 URL 和密钥。 - 按 新建虚拟桶 并创建虚拟桶。它可以与您的 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 需要 子域名 支持桶。转到:
<您的 Flexify.IO VM IP>/flexify-io/manage/admin/engines/configs/1,这将打开一个 隐藏 配置页面! - 在
Endpoint hostname字段中指定 S3 基本域名(假设是s3.mydomain.com),该字段默认应为空白。按 保存 以保存设置。 - 在 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 R2
Cloudflare R2 在使用 Cloudflare CDN 时与 S3 对象存储兼容。Cloudflare 的 免费计划提供 10GB 存储,这对于大多数论坛的需求来说应该绰绰有余。
要配置 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 使用 ACL =
false(禁用此选项!) - S3 备份桶 =
your backup bucket name - 备份位置 =
S3
配置 Cloudflare R2 的重要注意事项:
- 在为 Cloudflare R2 配置
app.yml或web_only.yml时,仅设置DISCOURSE_S3_CDN_URL。不要设置DISCOURSE_CDN_URL。 如果您通过 Cloudflare 代理主域名,它已经在自动缓存和提供您的应用资源。如果您尝试使用 Cloudflare DNS 配置单独的DISCOURSE_CDN_URL,Discourse 的严格 NGINX 主机路由将拒绝请求,导致无限 301 重定向循环、CORS 策略阻止和站点损坏。
- 将
DISCOURSE_CDN_URL注释掉。 - 设置
DISCOURSE_S3_CDN_URL: https://your-r2-custom-domain.com
-
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”令牌自动授予 multipart 上传权限,并将以下 CORS 规则直接粘贴到 Cloudflare 仪表板 R2 上传桶设置下的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 对象存储适用于 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 不支持虚拟主机样式的桶访问 且 无法工作 ↩︎

