Issue with mail-receiver and self-signed certificate?

I’m trying to set up incoming email for a self-hosted discourse instance behind a reverse proxy (http(s), SMTP). Public domain: public.example.com, host behind reverse proxy: internal.example.com. I followed this manual but are stuck potentially due to a certificate error. I’m using self-signed certificates for the internal encryption between reverse proxy and discourse containers. The mail container seems to have an issue with the self signed cert presented by the discourse container although it is a chained cert. What did I do wrong or how to debug the issue further?
The (relevant) log output of the mail-in container (./launcher logs mail-receiver) is:

May 21 15:34:06 internal-mail-receiver postfix/qmgr[101]: BA3E16FDE7: from=<foo@example.com>, size=3836, nrcpt=1 (queue active)
<23>May 21 15:34:06 receive-mail[113]: Recipient: nobody@public.example.com<19>May 21 15:34:06 receive-mail[113]: Failed to POST the e-mail to https://internal.example.com/admin/email/handle_mail: SSL_connect returned=1 errno=0 state=error: certificate verify failed (unable to get local issuer certificate) (OpenSSL::SSL::SSLError)<19>May 21 15:34:06 receive-mail[113]:   /usr/lib/ruby/2.7.0/net/protocol.rb:44:in `connect_nonblock'
  /usr/lib/ruby/2.7.0/net/protocol.rb:44:in `ssl_socket_connect'
  /usr/lib/ruby/2.7.0/net/http.rb:1009:in `connect'
  /usr/lib/ruby/2.7.0/net/http.rb:943:in `do_start'
  /usr/lib/ruby/2.7.0/net/http.rb:932:in `start'
  /usr/lib/ruby/2.7.0/net/http.rb:1483:in `request'
  /usr/local/lib/site_ruby/mail_receiver/internal_mail_receiver.rb:43:in `process'
  /usr/local/bin/receive-mail:13:in `<main>'May 21 15:34:06 internal-mail-receiver postfix/pipe[112]: BA3E16FDE7: to=<nobody@public.example.com>, relay=discourse, delay=0.39, delays=0.19/0.01/0/0.2, dsn=4.3.0, status=deferred (temporary failure)

The (relevant part of the) config file mail-receiver.yml of the mail container is:

env:
  POSTCONF_smtpd_tls_key_file:  /ssl/ssl.key
  POSTCONF_smtpd_tls_cert_file:  /ssl/ssl.crt
  POSTCONF_smtpd_tls_security_level: may

  DISCOURSE_MAIL_ENDPOINT: 'https://internal.example.com/admin/email/handle_mail'

volumes:
  - volume:
      host: /var/discourse/shared/standalone/ssl
      guest: /ssl

The private key ssl.key contains the private key of the (internal) server. The chained cert ssl.crt contains: server-cert + ca-cert (as a new user I’m not allowed to upload a file, thus currently cannot provide the ssl.crt)

The smtpd_tls environment variables relate to the smtpd server, i.e. the part other mail servers will interact with when delivering emails. When it is then trying to deliver the email to the handle_mail endpoint on internal.example.com, whatever Ruby is using doesn’t trust your certificate authority and therefore can’t trust your self-signed certificate.

For this to work, I think you have two options. The first is to modify mail-receiver.yml in order to include your root CA certificate in the container, such that Ruby will trust it. I’m not sure off the top of my head what that would look like, but it would basically be the same as getting Ruby to trust a new CA on any Linux system except via that container yml file.

The other option is just to change DISCOURSE_MAIL_ENDPOINT from using internal. to public., causing it to connect via your proxy which presumably has a certificate it will be able to trust by default.

2 Likes

Thanks for you help, worked that way!
(initially, my naive me assumed, that all communication between the containers would happen directly between the two containers anyway)

2 Likes

Communication does happen directly between the two containers, it’s just that you configured your Discourse container to use HTTPS with a self-signed certificate, which changes the required method of communication.

1 Like

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.