DavidO
(David)
1
我的 Digital Ocean Droplet 空间快用完了,所以我想把上传的文件移到 Digital Ocean Space。
这是我的设置……
-
s3 访问密钥 ID - 从 DO CP > API > Applications & API 复制
-
s3 密钥访问密钥 - 从 DO CP > API > Applications & API 复制
-
s3 区域 - 不确定它是否对 DO Spaces 重要,但我将其保留为默认值 - US East (N. Virginia)
-
s3 上传存储桶 - 我不清楚是否应该在 Space 中创建一个文件夹。我两者都试过了……
- uploads - 在 Space 中没有创建文件夹
- files - 已经在 Space 中创建了文件夹
-
s3 端点 - 我认为我在这里出错了。我尝试了以下…的 https:// 版本
我看到了这个…
…还有这个…
但我的设置显示在管理界面中,所以我认为这可能不是过时的,只是需要正确配置我的设置。
我看到了这个…
…但管理区域不允许我将“s3 upload bucket”留空,所以我不知道这是否相关。那似乎也只适用于使用 AWS S3 的情况。我尝试在我的 DO Space 中创建一个文件夹并使用该文件夹名。我尝试使用一个不存在的文件夹名称,以防它需要自己创建。这些都不起作用。
我看到了这个…
…但我远非专家,所以我回避了它。
现在我已无计可施,不确定我是否接近成功,只需要正确的设置配置,或者我是否完全遗漏了什么,根本没有接近。
任何帮助将不胜感激。谢谢。
DavidO
(David)
2
另外,我也尝试过使用 DO API 凭证,例如……
不确定它应该匹配什么,所以我在这方面也有些困惑。
Falco
(Falco)
3
不,它们没有。虽然您可以在 UI 中配置 S3 端点,但我们在配置 app.yml 文件时仅测试和验证了使用 S3 克隆(如 Digital Ocean 提供)的情况。
配置兼容 S3 的对象存储提供商以上传文件 wiki 凝聚了许多人的心血,所以我建议您遵循它。
4 个赞
pfaffman
(Jay Pfaffman)
4
好吧,Falco 比我快一步,但这是我刚才说的……
不。你需要按照 Configure an S3 compatible object storage provider for uploads 的说明,将设置放入你的 app.yml 文件中。
你需要一个真正的 CDN,比如 bunny.net。我不认为 Cloudflare 可以。
1 个赞
DavidO
(David)
5
谢谢。
我在 app.yml 中没有看到 DISCOURSE_S3 设置部分。我只需要为每个设置添加一行吗?还是 sudo 命令就是做这个的?
我不太清楚在哪里运行或放置这些 sudo 命令。不清楚这是否是一个一次性的命令行项目来添加它,还是必须将其放入 app.yml 中以便始终考虑到它。
sudo 命令是放在 app.yml 区域还是只放 DISCOURSE_S3 设置行?
使用 DO Spaces 时,我是否只需将 DISCOURSE_S3_REGION 留空?
我必须使用 CDN 吗?我们的流量非常低。用户群体很小。我真的想尽可能地减少需要处理的环节。
DavidO
(David)
6
这个…
…放在…的**# plugins to here**下面…
hooks:
…区域,在…
after_code: 部分之后?
1 个赞
DavidO
(David)
7
好的。我已添加 after_assets_precompile…
我已重新构建,但仍然看不到 S3 部分。
我需要自己创建一个吗?
设置放在哪里是否重要?
Falco
(Falco)
8
如指南中所述,它们必须放在 env: 部分下,与其他 DISCOURSE_ 设置一起:
2 个赞
the220hq
(Quynh H Nguyen)
9
这个问题有解决方案吗?我在尝试使用 Oracle Cloud Storage 时遇到了同样的错误。
我遵循了 wiki 中的说明,在 app.yml 中进行了设置。我尝试使用 s3cmd 手动进行正确的连接。但是,在上传图片时,我收到了相同的错误消息。
消息(报告了 4 个副本)
作业异常:SSL_connect 返回=1 errno=0 peeraddr=134.70.128.1:443 状态=错误:证书验证失败(主机名不匹配)
回溯
/usr/local/lib/ruby/3.2.0/net/protocol.rb:46:in `connect_nonblock'
/usr/local/lib/ruby/3.2.0/net/protocol.rb:46:in `ssl_socket_connect'
/usr/local/lib/ruby/3.2.0/net/http.rb:1342:in `connect'
/usr/local/lib/ruby/3.2.0/net/http.rb:1248:in `do_start'
/usr/local/lib/ruby/3.2.0/net/http.rb:1243:in `start'
/usr/local/lib/ruby/3.2.0/delegate.rb:87:in `method_missing'
aws-sdk-core-3.130.2/lib/seahorse/client/net_http/connection_pool.rb:307:in `start_session'
aws-sdk-core-3.130.2/lib/seahorse/client/net_http/connection_pool.rb:100:in `session_for'
aws-sdk-core-3.130.2/lib/seahorse/client/net_http/handler.rb:128:in `session'
aws-sdk-core-3.130.2/lib/seahorse/client/net_http/handler.rb:76:in `transmit'
aws-sdk-core-3.130.2/lib/seahorse/client/net_http/handler.rb:50:in `call'
aws-sdk-core-3.130.2/lib/seahorse/client/plugins/content_length.rb:24:in `call'
aws-sdk-core-3.130.2/lib/seahorse/client/plugins/request_callback.rb:85:in `call'
aws-sdk-s3-1.114.0/lib/aws-sdk-s3/plugins/s3_signer.rb:132:in `call'
aws-sdk-s3-1.114.0/lib/aws-sdk-s3/plugins/s3_signer.rb:63:in `call'
aws-sdk-s3-1.114.0/lib/aws-sdk-s3/plugins/s3_host_id.rb:17:in `call'
aws-sdk-core-3.130.2/lib/aws-sdk-core/xml/error_handler.rb:10:in `call'
aws-sdk-core-3.130.2/lib/aws-sdk-core/plugins/transfer_encoding.rb:26:in `call'
aws-sdk-core-3.130.2/lib/aws-sdk-core/plugins/helpful_socket_errors.rb:12:in `call'
aws-sdk-s3-1.114.0/lib/aws-sdk-s3/plugins/s3_signer.rb:110:in `call'
aws-sdk-s3-1.114.0/lib/aws-sdk-s3/plugins/redirects.rb:20:in `call'
aws-sdk-core-3.130.2/lib/aws-sdk-core/plugins/retry_errors.rb:360:in `call'
aws-sdk-core-3.130.2/lib/aws-sdk-core/plugins/retry_errors.rb:394:in `retry_request'
aws-sdk-core-3.130.2/lib/aws-sdk-core/plugins/retry_errors.rb:382:in `retry_if_possible'
aws-sdk-core-3.130.2/lib/aws-sdk-core/plugins/retry_errors.rb:371:in `call'
aws-sdk-core-3.130.2/lib/aws-sdk-core/plugins/retry_errors.rb:394:in `retry_request'
aws-sdk-core-3.130.2/lib/aws-sdk-core/plugins/retry_errors.rb:382:in `retry_if_possible'
aws-sdk-core-3.130.2/lib/aws-sdk-core/plugins/retry_errors.rb:371:in `call'
aws-sdk-core-3.130.2/lib/aws-sdk-core/plugins/retry_errors.rb:394:in `retry_request'
aws-sdk-core-3.130.2/lib/aws-sdk-core/plugins/retry_errors.rb:382:in `retry_if_possible'
aws-sdk-core-3.130.2/lib/aws-sdk-core/plugins/retry_errors.rb:371:in `call'
aws-sdk-core-3.130.2/lib/aws-sdk-core/plugins/http_checksum.rb:19:in `call'
aws-sdk-core-3.130.2/lib/aws-sdk-core/plugins/endpoint_pattern.rb:30:in `call'
aws-sdk-s3-1.114.0/lib/aws-sdk-s3/plugins/accelerate.rb:67:in `call'
aws-sdk-core-3.130.2/lib/aws-sdk-core/plugins/checksum_algorithm.rb:136:in `call'
aws-sdk-s3-1.114.0/lib/aws-sdk-s3/plugins/bucket_dns.rb:35:in `call'
aws-sdk-s3-1.114.0/lib/aws-sdk-s3/plugins/dualstack.rb:41:in `call'
aws-sdk-s3-1.114.0/lib/aws-sdk-s3/plugins/expect_100_continue.rb:22:in `call'
aws-sdk-s3-1.114.0/lib/aws-sdk-s3/plugins/bucket_name_restrictions.rb:26:in `call'
aws-sdk-s3-1.114.0/lib/aws-sdk-s3/plugins/arn.rb:62:in `call'
aws-sdk-core-3.130.2/lib/aws-sdk-core/rest/handler.rb:10:in `call'
aws-sdk-core-3.130.2/lib/aws-sdk-core/plugins/recursion_detection.rb:18:in `call'
aws-sdk-core-3.130.2/lib/aws-sdk-core/plugins/user_agent.rb:13:in `call'
aws-sdk-core-3.130.2/lib/seahorse/client/plugins/endpoint.rb:47:in `call'
aws-sdk-core-3.130.2/lib/aws-sdk-core/plugins/param_validator.rb:26:in `call'
aws-sdk-s3-1.114.0/lib/aws-sdk-s3/plugins/arn.rb:88:in `call'
aws-sdk-core-3.130.2/lib/seahorse/client/plugins/raise_response_errors.rb:16:in `call'
aws-sdk-s3-1.114.0/lib/aws-sdk-s3/plugins/sse_cpk.rb:24:in `call'
aws-sdk-s3-1.114.0/lib/aws-sdk-s3/plugins/dualstack.rb:27:in `call'
aws-sdk-s3-1.114.0/lib/aws-sdk-s3/plugins/accelerate.rb:56:in `call'
aws-sdk-core-3.130.2/lib/aws-sdk-core/plugins/checksum_algorithm.rb:111:in `call'
aws-sdk-core-3.130.2/lib/aws-sdk-core/plugins/jsonvalue_converter.rb:22:in `call'
aws-sdk-core-3.130.2/lib/aws-sdk-core/plugins/idempotency_token.rb:19:in `call'
aws-sdk-core-3.130.2/lib/aws-sdk-core/plugins/param_converter.rb:26:in `call'
aws-sdk-core-3.130.2/lib/seahorse/client/plugins/request_callback.rb:71:in `call'
aws-sdk-core-3.130.2/lib/aws-sdk-core/plugins/response_paging.rb:12:in `call'
aws-sdk-core-3.130.2/lib/seahorse/client/plugins/response_target.rb:24:in `call'
aws-sdk-core-3.130.2/lib/seahorse/client/request.rb:72:in `send_request'
aws-sdk-s3-1.114.0/lib/aws-sdk-s3/client.rb:10921:in `put_bucket_policy'
/var/www/discourse/lib/s3_inventory.rb:183:in `update_bucket_policy'
/var/www/discourse/app/jobs/regular/update_s3_inventory.rb:16:in `block in execute'
/var/www/discourse/app/jobs/regular/update_s3_inventory.rb:14:in `each'
/var/www/discourse/app/jobs/regular/update_s3_inventory.rb:14:in `execute'
/var/www/discourse/app/jobs/base.rb:292:in `block (2 levels) in perform'
rails_multisite-5.0.0/lib/rails_multisite/connection_management.rb:82:in `with_connection'
/var/www/discourse/app/jobs/base.rb:279:in `block in perform'
/var/www/discourse/app/jobs/base.rb:275:in `each'
/var/www/discourse/app/jobs/base.rb:275:in `perform'
sidekiq-6.5.12/lib/sidekiq/processor.rb:202:in `execute_job'
sidekiq-6.5.12/lib/sidekiq/processor.rb:170:in `block (2 levels) in process'
sidekiq-6.5.12/lib/sidekiq/middleware/chain.rb:177:in `block in invoke'
/var/www/discourse/lib/sidekiq/pausable.rb:134:in `call'
sidekiq-6.5.12/lib/sidekiq/middleware/chain.rb:179:in `block in invoke'
sidekiq-6.5.12/lib/sidekiq/middleware/chain.rb:182:in `invoke'
sidekiq-6.5.12/lib/sidekiq/processor.rb:169:in `block in process'
sidekiq-6.5.12/lib/sidekiq/processor.rb:136:in `block (6 levels) in dispatch'
sidekiq-6.5.12/lib/sidekiq/job_retry.rb:113:in `local'
sidekiq-6.5.12/lib/sidekiq/processor.rb:135:in `block (5 levels) in dispatch'
sidekiq-6.5.12/lib/sidekiq.rb:44:in `block in <module:Sidekiq>'
sidekiq-6.5.12/lib/sidekiq/processor.rb:131:in `block (4 levels) in dispatch'
sidekiq-6.5.12/lib/sidekiq/processor.rb:263:in `stats'
sidekiq-6.5.12/lib/sidekiq/processor.rb:126:in `block (3 levels) in dispatch'
sidekiq-6.5.12/lib/sidekiq/job_logger.rb:13:in `call'
sidekiq-6.5.12/lib/sidekiq/processor.rb:125:in `block (2 levels) in dispatch'
sidekiq-6.5.12/lib/sidekiq/job_retry.rb:80:in `global'
sidekiq-6.5.12/lib/sidekiq/processor.rb:124:in `block in dispatch'
sidekiq-6.5.12/lib/sidekiq/job_logger.rb:39:in `prepare'
sidekiq-6.5.12/lib/sidekiq/processor.rb:123:in `dispatch'
sidekiq-6.5.12/lib/sidekiq/processor.rb:168:in `process'
sidekiq-6.5.12/lib/sidekiq/processor.rb:78:in `process_one'
sidekiq-6.5.12/lib/sidekiq/processor.rb:68:in `run'
sidekiq-6.5.12/lib/sidekiq/component.rb:8:in `watchdog'
sidekiq-6.5.12/lib/sidekiq/component.rb:17:in `block in safe_thread'
提前感谢!
附注:不仅是 Oracle Cloud Service,还有另一个国内服务提供商。
the220hq
(Quynh H Nguyen)
11
如上所述:我正在尝试使用 Oracle Cloud Storage。并且我已通过 s3cmd 工具使用同一帐户进行了手动检查。
而且不可能弄错名称,因为我只是复制粘贴。
我检查了 S3 端点的 DNS:
dig axhjdarc4cuy.compat.objectstorage.ap-singapore-1.oraclecloud.com
;; <<>> DiG 9.18.18-0ubuntu0.22.04.1-Ubuntu <<>> axhjdarc4cuy.compat.objectstorage.ap-singapore-1.oraclecloud.com
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 63008
;; flags: qr rd ra; QUERY: 1, ANSWER: 3, AUTHORITY: 1, ADDITIONAL: 1
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 65494
;; QUESTION SECTION:
;axhjdarc4cuy.compat.objectstorage.ap-singapore-1.oraclecloud.com. IN A
;; ANSWER SECTION:
axhjdarc4cuy.compat.objectstorage.ap-singapore-1.oraclecloud.com. 258 IN CNAME compat.objectstorage.ap-singapore-1.oci.oraclecloud.com.
compat.objectstorage.ap-singapore-1.oci.oraclecloud.com. 258 IN CNAME objectstorage.ap-singapore-1.oci.oraclecloud.com.
objectstorage.ap-singapore-1.oci.oraclecloud.com. 174 IN A 134.70.128.1
;; AUTHORITY SECTION:
ap-singapore-1.oci.oraclecloud.com. 258 IN SOA ns1.p200.dns.oraclecloud.net. hostmaster.ap-singapore-1.oci.oraclecloud.com. 682052 3600 900 31536000 1800
;; Query time: 0 msec
;; SERVER: 127.0.0.53#53(127.0.0.53) (UDP)
;; WHEN: Sat Nov 04 18:58:03 +07 2023
;; MSG SIZE rcvd: 252
并使用目标地址:objectstorage.ap-singapore-1.oci.oraclecloud.com 而不是原始名称:axhjdarc4cuy.compat.objectstorage.ap-singapore-1.oraclecloud.com
然后我在 s3cmd 工具中得到了与 Discourse 显示完全相同的错误消息:
请稍候,正在尝试列出所有存储桶...
错误:测试失败:[SSL: CERTIFICATE_VERIFY_FAILED] 证书验证失败:主机名不匹配,证书对 'objectstorage.ap-singapore-1.oci.oraclecloud.com' 无效。(_ssl.c:1007)
我对此问题没有任何经验。 
the220hq
(Quynh H Nguyen)
14
经过多次尝试,我仍然收到相同的错误消息。我手动检查了证书和主机名,并使用了正确的格式来仔细查看正确的证书,但都没有成功。
我的端点: <namespace>.<region>.compat.objectstorage.oraclecloud.com
证书的通用名称 (CN): *.compat.objectstorage.<region>.oraclecloud.com
我可以使用 s3cmd 工具连接。但无法使用相同的配置为 discourse 设置 S3 上传。
错误消息: SSL_connect returned=1 errno=0 peeraddr=134.70.128.1:443 state=error: certificate verify failed (Hostname mismatch)
我想尝试另一种方法,通过在 Ruby 环境中设置(到处搜索后):
OpenSSL::SSL::VERIFY_PEER = OpenSSL::SSL::VERIFY_NONE
但如何在 discourse 中设置这个?拜托!
这是一个坏主意,因为它会破坏 X509 证书提供的许多保护。
你能展示一下你这里非秘密的设置吗?请注意 Oracle Cloud 不受支持,但我们仍然会快速查看是否有明显错误。
the220hq
(Quynh H Nguyen)
16
是的,您在关闭它时是对的。我想找到原因,以便在 ruby 库出错时提交一个 PR。
我的设置非常简单,只是尝试将图像上传到 S3 兼容存储。
DISCOURSE_USE_S3: true
DISCOURSE_S3_REGION: <region>
DISCOURSE_S3_ENDPOINT: https://<namespace>.compat.objectstorage.<region>.oraclecloud.com
DISCOURSE_S3_ACCESS_KEY_ID: <access_key_id>
DISCOURSE_S3_SECRET_ACCESS_KEY: <access_key>
DISCOURSE_S3_BUCKET: <bucket_name>
Oracle Cloud Storage 对端点地址有一些格式要求。但无论我尝试哪种格式,都会出现我上面显示的相同错误消息。
SSL_connect returned=1 errno=0 peeraddr=134.70.128.1:443 state=error: certificate verify failed (Hostname mismatch)
我上面使用的格式,我已经检查了证书,在我看来是正确的:
正如我之前所说,我使用此设置通过 s3cmd 工具正常连接。非常感谢!
好的,我在 ssl_socket_connect 的开头添加了一个 binding.pry,当我尝试使用这些设置时,我看到:
→ DISCOURSE_USE_S3=true DISCOURSE_S3_REGION=ap-singapore-1 DISCOURSE_S3_ENDPOINT=https://axhjdarc4cuy.compat.objectstorage.ap-singapore-1.oraclecloud.com DISCOURSE_S3_ACCESS_KEY_ID=foo DISCOURSE_S3_SECRET_ACCESS_KEY=bar DISCOURSE_S3_BUCKET=bucketname bin/rails c
Loading development environment (Rails 7.0.7)
[1] pry(main)> s3 = S3Helper.build_from_config; s3.list
From: /home/michael/.rvm/gems/ruby-3.2.2@discourse/gems/net-protocol-0.2.2/lib/net/protocol.rb:42 Net::Protocol#ssl_socket_connect:
40: def ssl_socket_connect(s, timeout)
41: binding.pry
=> 42: if timeout
43: while true
44: raise Net::OpenTimeout if timeout <= 0
45: start = Process.clock_gettime Process::CLOCK_MONOTONIC
46: # to_io is required because SSLSocket doesn't have wait_readable yet
47: case s.connect_nonblock(exception: false)
48: when :wait_readable; s.to_io.wait_readable(timeout)
49: when :wait_writable; s.to_io.wait_writable(timeout)
50: else; break
51: end
52: timeout -= Process.clock_gettime(Process::CLOCK_MONOTONIC) - start
53: end
54: else
55: s.connect
56: end
57: end
[1] pry(#<Net::HTTP>)> s.hostname
=> "bucketname.axhjdarc4cuy.compat.objectstorage.ap-singapore-1.oraclecloud.com"
所以实际连接的主机名是 bucketname.axhjdarc4cuy.compat.objectstorage.ap-singapore-1.oraclecloud.com,这与 *.compat.objectstorage.ap-singapore-1.oraclecloud.com 不匹配,所以错误是正确的。
不幸的是,OCI 不支持 这种风格的访问:
在您的应用程序中使用基于路径的访问。不支持虚拟主机风格的访问(将存储桶访问为 {bucketnamespace}.compat.objectstorage.{region}.oraclecloud.com [sic])。
相反,Discourse 只支持虚拟主机风格的访问({bucketname}.{namespace}.compat.objectstorage.{region}.oraclecloud.com.)。
我们几年前移除了 可能使其生效的设置,因为它支持不佳(参见提交消息)。
要使其正常工作并不简单,需要复杂的开发和测试来添加此支持。
这里有危险。
(参考:S3 Path Style Access)
4 个赞
DavidO
(David)
19
不过,我从未弄明白。
找到了他所指的内容,但当我复制粘贴文本时,它会反转大小写。我放弃了,没有再继续。明年可能会再试一次。
我希望在此期间有人能弄明白,并根据我的计划更好地记录设置。
总之,谢谢。
what
(blox)
20
我遇到了这个问题并已修复,我的解决方案是,在我设置时,我的邮件服务器未经过 SSL 验证,但我的域名提供商确实为我提供了一个经过 SSL 验证的邮件服务器,所以我更换了它们。