nixcloud/nixcloud-webservices

nixcloud.email example results in system using self signed TLS certificate "Warwickshire"

erictapen opened this issue · 10 comments

I tried nixcloud.email another time, this time on a "vanilla" NixOS host. This is my host config:

{ config, pkgs, ... }:
{

  nixcloud.email= {
    enable = true;
    domains = [ "erictapen.de" ];
    ipAddress = "REDACTED";
    ip6Address = "REDACTED";
    hostname = "mail.erictapen.de";
    enableSpamassassin = false;

    users = [
      { name = "mail"; domain = "erictapen.de"; password = "{PLAIN}passpass"; }
    ];
  };

}

I'm on nixos-18.03 and nixcloud-webservices 8c9a230.

Everything seems to work, but when I try to fetch my Mails with offlineimap, I get

OfflineIMAP 7.1.5
  Licensed under the GNU GPL v2 or any later version (with an OpenSSL exception)
imaplib2 v2.57 (bundled), Python v2.7.14, OpenSSL 1.0.2o  27 Mar 2018
Account sync erictapen:
 *** Processing account erictapen
 Establishing connection to mail.erictapen.de:993 (erictapen-Remote)
 ERROR: Unknown SSL protocol connecting to host 'mail.erictapen.de' for repository 'erictapen-Remote'. OpenSSL responded:
[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed (_ssl.c:661)
 *** Finished account 'erictapen' in 0:00
ERROR: Exceptions occurred during the run!
ERROR: Unknown SSL protocol connecting to host 'mail.erictapen.de' for repository 'erictapen-Remote'. OpenSSL responded:
[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed (_ssl.c:661)

Traceback:
  File "/nix/store/abz63s1hsf38m9b9k1yvigxcs4l535pg-offlineimap-7.1.5/lib/python2.7/site-packages/offlineimap/accounts.py", line 283, in syncrunner
    self.__sync()
  File "/nix/store/abz63s1hsf38m9b9k1yvigxcs4l535pg-offlineimap-7.1.5/lib/python2.7/site-packages/offlineimap/accounts.py", line 359, in __sync
    remoterepos.getfolders()
  File "/nix/store/abz63s1hsf38m9b9k1yvigxcs4l535pg-offlineimap-7.1.5/lib/python2.7/site-packages/offlineimap/repository/IMAP.py", line 452, in getfolders
    imapobj = self.imapserver.acquireconnection()
  File "/nix/store/abz63s1hsf38m9b9k1yvigxcs4l535pg-offlineimap-7.1.5/lib/python2.7/site-packages/offlineimap/imapserver.py", line 630, in acquireconnection
    exc_info()[2])
  File "/nix/store/abz63s1hsf38m9b9k1yvigxcs4l535pg-offlineimap-7.1.5/lib/python2.7/site-packages/offlineimap/imapserver.py", line 544, in acquireconnection
    af=self.af,
  File "/nix/store/abz63s1hsf38m9b9k1yvigxcs4l535pg-offlineimap-7.1.5/lib/python2.7/site-packages/offlineimap/imaplibutil.py", line 194, in __init__
    super(WrappedIMAP4_SSL, self).__init__(*args, **kwargs)
  File "/nix/store/abz63s1hsf38m9b9k1yvigxcs4l535pg-offlineimap-7.1.5/lib/python2.7/site-packages/offlineimap/bundled_imaplib2.py", line 2183, in __init__
    IMAP4.__init__(self, host, port, debug, debug_file, identifier, timeout, debug_buf_lvl)
  File "/nix/store/abz63s1hsf38m9b9k1yvigxcs4l535pg-offlineimap-7.1.5/lib/python2.7/site-packages/offlineimap/bundled_imaplib2.py", line 361, in __init__
    self.open(host, port)
  File "/nix/store/abz63s1hsf38m9b9k1yvigxcs4l535pg-offlineimap-7.1.5/lib/python2.7/site-packages/offlineimap/imaplibutil.py", line 202, in open
    super(WrappedIMAP4_SSL, self).open(host, port)
  File "/nix/store/abz63s1hsf38m9b9k1yvigxcs4l535pg-offlineimap-7.1.5/lib/python2.7/site-packages/offlineimap/bundled_imaplib2.py", line 2196, in open
    self.ssl_wrap_socket()
  File "/nix/store/abz63s1hsf38m9b9k1yvigxcs4l535pg-offlineimap-7.1.5/lib/python2.7/site-packages/offlineimap/bundled_imaplib2.py", line 548, in ssl_wrap_socket
    self.sock = ssl.wrap_socket(self.sock, self.keyfile, self.certfile, ca_certs=self.ca_certs, cert_reqs=cert_reqs, ssl_version=ssl_version)
  File "/nix/store/nx3jw576gqw01iiijgsav39w2qa4cni2-python-2.7.14/lib/python2.7/ssl.py", line 943, in wrap_socket
    ciphers=ciphers)
  File "/nix/store/nx3jw576gqw01iiijgsav39w2qa4cni2-python-2.7.14/lib/python2.7/ssl.py", line 611, in __init__
    self.do_handshake()
  File "/nix/store/nx3jw576gqw01iiijgsav39w2qa4cni2-python-2.7.14/lib/python2.7/ssl.py", line 840, in do_handshake
    self._sslobj.do_handshake()

A run of openssl reveals:

$ openssl s_client -connect mail.erictapen.de:993 -crlf
CONNECTED(00000003)
depth=1 C = UK, ST = Warwickshire, L = Leamington, O = OrgName, OU = Security Department, CN = example.com
verify error:num=19:self signed certificate in certificate chain
---
Certificate chain
 0 s:/C=UK/ST=Warwickshire/L=Leamington/O=OrgName/OU=IT Department/CN=example.com
   i:/C=UK/ST=Warwickshire/L=Leamington/O=OrgName/OU=Security Department/CN=example.com
 1 s:/C=UK/ST=Warwickshire/L=Leamington/O=OrgName/OU=Security Department/CN=example.com
   i:/C=UK/ST=Warwickshire/L=Leamington/O=OrgName/OU=Security Department/CN=example.com
...

I would expect, that the example config contains not a self signed certificate but one from Let's encrypt? Also after a quick glance at the source, I wonder wether this Warwickshire cert should be used for anything other than nginx config file validation?

are you still using services.nginx because that won't work with nixcloud.TLS and therefore ACME will only create self-signed certifictes.

you need to enable nixcloud.reverse-proxy on port 80 in combination to this setup so that you actually can query valid let's encrypt certifictes.

we've just released hack-your-service

this is pretty much like services.apache or services.nginx. try it!

hack ahead: if you still want to use services.nginx or services.apache you can define a webpage running on the 'domain' in question so that security.acme is able to query the certificate when needed. but then you have to reload the postfix.service and dovecot2.service manually from time to time since they don't know about updated certificates.

are you still using services.nginx because that won't work with nixcloud.TLS and therefore ACME will only create self-signed certifictes.

As I said, I setup a new NixOS host with a sole purpose to not have any other service like Nginx running, which could interfer with the setup. Also I just did

cd /var/lib
rm -rf acme/ dovecot/ virtualMail/

to get sure, that all the certs I have come from Nixcloud. After rebuilding the system, the problem persists.

I don't want to run any other web service, just email. There is really nothing else configured on the server, besides of a tinc VPN for maintenance. The text on the email documentation suggests, that I get a Let's encrypt certificate by default, not a self signed one:

When using nixcloud.email.enableTLS = true;, which is a default we automatically acquires a let's encrypt TLS certificate for your mail server.

Also the "basic example" section gives me the impression, that it results in a mail server, where my users don't have to accept a self signed certificate from "Warwickshire".

The overall presentation of the email module gave me the impression, that it provides me a abstraction for a mail server, that "works out of the box" but still gives me the possibilty to manipulate the service on the deeper level. At the moment I have no time for hacking. Is this a use case of nixcloud.email?

@erictapen i've been looking into your issue and the problem is that:

the problem

  1. acme-mail.someserver.com.service was able to get a certificate after a while
  2. but https://github.com/NixOS/nixpkgs/blob/release-18.03/nixos/modules/security/acme.nix#L296 uses a privateTmp
  3. but https://github.com/NixOS/nixpkgs/blob/release-18.03/nixos/modules/security/acme.nix#L239 seems not to be able to read it and thus is not executed

and what i've seen on your system is that there were let's encrypt certificates but the services weren't restarted after those had been retrieved successfully. at the moment i think this is an issue of security.acme and that it is related to the condition to run the postRun hook (which, as i said, was never run and can't be run manually either...)

will look into this either later today or tomorrow.

the hack solution

  • you need to reboot the machine (easy)
  • you need to restart all jobs mentioned in the postRun hook, see systemctl cat acme-mail.someserver.com.service's ExecStopPost script
  • or restart all manually like: systemctl restart dovecot2 and systemctl restart postfix

the solution

we need to figure why the postRun in security.acme is actually existent and not just a part of the ExecStart. at the moment i can't think of any good reason ...

now i'd like to move away from security.acme, see this NixOS/nixpkgs#34941

@erictapen i think we'll move away from security.acme in the long run (next few weeks) and until then you should not get any certificate issues for the server in question. for all the new installation simply restart the server (easiest) or reload the services in question manually (more work).

@erictapen i'll leave this issue open until we fixed it. thanks for your help!

Works like a charm now, many thanks!

By the way: Today I learned about nixos/tests/common/letsencrypt.nix. This looks like a module which emulates the Let's Encrypt API, so one can test for issues like this automatically.