SSL_connect returned=1 errno=0 peeraddr= state=error: certificate verify failed (Hostname mismatch)

I’ve started running out of space in my Digital Ocean Droplet so I wanted to move the uploaded files over to a Digital Ocean Space.

This is what I have setup…

I saw this…

…and this…

But my settings do show up in the admin interface, so I think this may not we outdated and it’s just a matter of getting my setting mix correct.

I saw this…

…but the admin area does not allow me to leave “s3 upload bucket” empty, so I wasn’t sure if that was related. That also seemed to be only if you’re using AWS S3 also. I tried creating a folder in my DO Space and using that folder name. I tried using a different name of a folder that wasn’t there, in case it needs to create its own. None of that worked.

I saw this…

…but I’m far from an expert, so I shied away from that.

At this point I’m just out of ideas to try and I’m not sure if I’m close and just need the right setting configuration or if I’m wholly missing something and not even close.

Any help would be much appreciated. Thank you.

Also, I’ve tried DO API credentials as…

Not sure what it’s supposed to match, so I’m a little thrown off there also.

No they aren’t. While you can configure the S3 endpoints in the UI, we only tested and validated using the S3 clones, like Digital Ocean offering, when configuring it on the app.yml file.

The Configure an S3 compatible object storage provider for uploads wiki took much work from many people, so I recommend sticking to it.


Well, Falco beat me to it, but here’s what I was saying…

No. You need to follow Configure an S3 compatible object storage provider for uploads and put the settings in your app.yml.

You need a real cdn like I don’t think that cloudflare will do it.

1 Like

Thank you.

I don’t see a section in app.yml for DISCOURSE_S3 settings. Do I just create a line for each? Or is that what the sudo commands do?

I’m not entirely clear on where I run or put those sudo commands. Not clear if it’s a one-time command line item to add it or if it’s something that has to go into app.yml so that it’s always accounted for.

Do the sudo commands go in the app.yml area or just the DISCOURSE_S3 setting lines?

Do I just leave this blank with DO Spaces? DISCOURSE_S3_REGION:

Do I have to have a CDN? We have very low traffic. Small group. I’m really trying to limit the moving parts if possible.


…goes below # plugins to here in the…


…area, after the…

after_code: section?

1 Like

OK. I got the after_assets_precompile added…


I rebuilt it and I still don’t see a section of S3.

Do I just make one?
Does it matter where I put the settings?

As said in the guide they must go under the env: section, together with other DISCOURSE_ like settings:


Is there any solution for this issue? I got the same error when trying to use Oracle Cloud Storage.

I followed the wiki by setting in app.yml. I tried to use s3cmd manual for sure correct connection. But when upload an image in post, I got the same error message.

Message (4 copies reported)
Job exception: SSL_connect returned=1 errno=0 peeraddr= state=error: certificate verify failed (Hostname mismatch)
/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' 

Thanks in advanced!

PS. Not only Oracle Cloud Service, but also another domestic service provider.

So maybe you’re accessing the bucket with the wrong name?

What bucket provider are you using?

As I talk above: I’m trying with Oracle Cloud Storage. And I checked by manual with s3cmd tool with the same account.

And no way to get wrong name, because just copy & paste.

I check DNS of S3 Endpoint:


; <<>> DiG 9.18.18-0ubuntu0.22.04.1-Ubuntu <<>>
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 63008
;; flags: qr rd ra; QUERY: 1, ANSWER: 3, AUTHORITY: 1, ADDITIONAL: 1

; EDNS: version: 0, flags:; udp: 65494
; IN A


;; AUTHORITY SECTION: 258	IN SOA 682052 3600 900 31536000 1800

;; Query time: 0 msec
;; WHEN: Sat Nov 04 18:58:03 +07 2023
;; MSG SIZE  rcvd: 252

And using the target address: instead of the original name:

Then I got the exactly error message in s3cmd tool like Discourse show:

Please wait, attempting to list all buckets...
ERROR: Test failed: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: Hostname mismatch, certificate is not valid for ''. (_ssl.c:1007)

I don’t have any experience about this issue. :frowning:

So the issue maybe from this:

Is there anyway to fix this issue? Thank you!

Use a name that matches the certificate.

After many tries, I still get the same error message. I checked manual the certificate and the hostname, used the right format to get the right certificate by eyes, but not luck.

My endpoint:
The certificate’s CN: *

I could connect by s3cmd tool. But could not setting S3 upload for discourse with the same configuration.

The error message: SSL_connect returned=1 errno=0 peeraddr= state=error: certificate verify failed (Hostname mismatch)

I want to try another way by setting in ruby environment (by searching everywhere):


But how can I set this in discourse? Please!

This is a bad idea as it will undermine many protections that X509 certificates provide.

Can you show what your non-secret settings are here? Please note Oracle Cloud is not supported, but we’ll still take a quick look to see if anything is obviously wrong.

Yes, you are right when turn it off. I just want to find the reason to make a PR if this is error in ruby library.

My settings are very simple, just try to upload images to S3 compatible storage.

  DISCOURSE_S3_ENDPOINT: https://<namespace>.compat.objectstorage.<region>
  DISCOURSE_S3_ACCESS_KEY_ID: <access_key_id>
  DISCOURSE_S3_BUCKET: <bucket_name>

Oracle Cloud Storage has some format for endpoint address. But whatever the format I tried, the same error massage that I show above.

SSL_connect returned=1 errno=0 peeraddr= state=error: certificate verify failed (Hostname mismatch)

The format above, I had checked the certificate and it is right in my eyes:

As I talked before, I used this setting to connect by s3cmd tool normally. Thanks so much!

OK I added a binding.pry to the start of ssl_socket_connect and what I see when trying to use these settings is:

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
=> ""

so the actual hostname being connected to is, which does not match * so the error is correct.

Unfortunately OCI does not support this style access:

Use path-based access in your application. Virtual host-style access (accessing a bucket as {bucketnamespace}.compat.objectstorage.{region} [sic]) is not supported.

Conversely Discourse only supports virtual host-style access ({bucketname}.{namespace}.compat.objectstorage.{region}

We removed the setting that might have made it work a while back as it wasn’t well supported (see the commit message).

Getting this working is not going to be simple and will require complex development and testing to add this support.

Here be dragons.

(xref: S3 Path Style Access)


Very clearly explains. Thank you very much!

1 Like

Thanks, but I never got it figured out.

Found what he was referring to, but then when I copy and paste text in it’s inverting the case. I give up and didn’t return to it. May try again next year.

I was hoping that someone would figure it out in the meantime and better document the setup to match my plans.

Thanks anyway.

I was having this issue and fixed this, My solution was that when I set it up my mail server was not SSL verified, but my domain provider did give me a SSL verified mail server so I replaced them.