letsencrypt on mail server

Discussion in 'Tips/Tricks/Mods' started by Jesse Norell, Aug 9, 2016.

  1. Jesse Norell

    Jesse Norell ISPConfig Developer Staff Member ISPConfig Developer

    Ispconfig 3.1 supports letsencrypt certificates for client websites out of the box, but using LE certificates for the control panel itself or other services (postfix, dovecot, xmpp, mysql) requires manual setup. This is a short how-to for setting up a letsencrypt certificate on an ispconfig mail server from a multiserver install, and assumes the mail server is already setup in ispconfig and things are running other than the certificates. Maybe some day all the manual pieces can be compiled into a full howto (or one per OS?).

    First install letsencrypt. Refer to the ISPconfig 3.1 Perfect Server guide for your OS, but in general if your OS provides a package, install that (eg. `apt-get install certbot -t jessie-backports`), otherwise:
    Code:
    mkdir /opt/certbot
    cd /opt/certbot
    wget https://dl.eff.org/certbot-auto
    chmod a+x ./certbot-auto
    ./certbot-auto    # (answer "no" to continue)
    
    Next, adjust your firewall. The letsencrypt configuration on a web server (and control panel server) uses the existing apache/nginx web server to intercept requests, but as an email server won't have a web server installed, we'll use letsencrypt's standalone plugin for this. You have likely protected your server with a firewall, so you'll need to allow tcp port 443 requests to your mail server.

    Now determine what hostnames you want to be included in the certificate. There is a limit to the number of names which can be included (100?), so don't plan on including all your customer domains if you have very many domains. We'll include the server's hostname (an CN), and include one "pretty" name (unfortunately it seems you cannot request the bare ip address to be included); a dedicated mail server will need to use --standalone:
    Code:
    certbot auth --text --agree-tos --standalone --email postmaster@`hostname -d` -d `hostname -f` -d mail.`hostname -f`
    If you have a webserver running you will need to use --webroot:
    Code:
    certbot auth --text --agree-tos --webroot --webroot-path /usr/local/ispconfig/interface/acme/ --email postmaster@`hostname -d` -d `hostname -f` -d mail.`hostname -f`
    You should see a Congratulations! message. If not, troubleshoot till you do.

    Now we'll create symlinks for the certificate and key files in the places ispconfig configures by default, which are the same for postfix and dovecot:

    Code:
    # postconf smtpd_tls_cert_file smtpd_tls_key_file
    smtpd_tls_cert_file = /etc/postfix/smtpd.cert
    smtpd_tls_key_file = /etc/postfix/smtpd.key
    # doveconf ssl_key ssl_cert
    ssl_key = </etc/postfix/smtpd.key
    ssl_cert = </etc/postfix/smtpd.cert
    
    # ln -s /etc/letsencrypt/live/`hostname -f`/privkey.pem /etc/postfix/smtpd.key
    # ln -s /etc/letsencrypt/live/`hostname -f`/fullchain.pem /etc/postfix/smtpd.cert
    # ls -l /etc/postfix/smtpd.{key,cert}
    lrwxrwxrwx 1 root root 55 Aug  9 15:34 /etc/postfix/smtpd.cert -> /etc/letsencrypt/live/hostname.domain.com/fullchain.pem
    lrwxrwxrwx 1 root root 53 Aug  9 15:33 /etc/postfix/smtpd.key -> /etc/letsencrypt/live/hostname.domain.com/privkey.pem
    
    # service postfix reload
    # service dovecot reload
    
    At this point both postfix and dovecot answer with the new certificate. The only remaining thing would be to make sure certificate renewals happen and restart postfix/dovecot if so. A quick read of ISPConfig's letsencrypt cronjob looks like it should perform the renewal; as an additional measure, if you installed from an OS package, you might have another cronjob keeping renewals current; eg. the cronjob from jessie-backports runs every 12 days.

    Once the certificate has renewed, postfix and dovecot must restart. You could blindly do this once a week or use a cronjob like this to test the certificate served over the network against the latest letsencrypt files and restart if they differ; save as /usr/local/sbin/letsencrypt-for-mail.sh:
    Code:
    #!/bin/bash
    
    # letsencrypt-for-mail.sh:  compares the ssl certficate served by dovecot
    # and postfix with the current certificate issued by letsencrypt,
    # and restart the mail system if they differ
    
    # this can be run as a cronjob to propogate letsencrypt certificate changes
    # to the running mail services
    
    LE_DIR=/etc/letsencrypt/live/`hostname -f`
    LE_CA=${LE_DIR}/chain.pem
    LE_CERT=${LE_DIR}/cert.pem
    LE_KEY=${LE_DIR}/privkey.pem
    
    OPENSSL=`which openssl 2>/dev/null | head -1`
    
    # Check if letsencrypt has been setup
    if [ ! -f ${LE_CA} -o ! -f ${LE_CERT} -o ! -f ${LE_KEY} ]
    then
        echo "Letsencrypt files not found.  You must setup letsencrypt and issue a certificate first." 1>&2
        exit 0
    fi
    
    # Check openssl binary exists
    if [ ! -f ${OPENSSL} ]
    then
        echo "Cannot find openssl. Exiting." 1>&2
        exit 1
    fi
    
    le_serial=`${OPENSSL} x509 -noout -serial -in ${LE_CERT}`
    smtp_serial=`${OPENSSL} s_client -connect localhost:25 -starttls smtp </dev/null 2>/dev/null | ${OPENSSL} x509 -serial -noout`
    pop3_serial=`${OPENSSL} s_client -connect localhost:110 -starttls pop3 </dev/null 2>/dev/null | ${OPENSSL} x509 -serial -noout`
    imap_serial=`${OPENSSL} s_client -connect localhost:143 -starttls imap </dev/null 2>/dev/null | ${OPENSSL} x509 -serial -noout`
    imaps_serial=`${OPENSSL} s_client -connect localhost:993 </dev/null 2>/dev/null | ${OPENSSL} x509 -serial -noout`
    pop3s_serial=`${OPENSSL} s_client -connect localhost:995 </dev/null 2>/dev/null | ${OPENSSL} x509 -serial -noout`
    
    # if a service is down, this certificate verification will fail;
    # we'll only restart services if they are actually running
    
    function restart_postfix_if_running() {
        /etc/init.d/postfix status 2>/dev/null >/dev/null
        if [ $? -eq 0 ]
        then
            /etc/init.d/postfix restart >/dev/null
        fi
    }
    
    function restart_dovecot_if_running() {
        /etc/init.d/dovecot status 2>/dev/null >/dev/null
        if [ $? -eq 0 ]
        then
            /etc/init.d/dovecot restart >/dev/null
        fi
    }
    
    if [ "${le_serial}" != "${smtp_serial}" ]
    then
        restart_postfix_if_running
    fi
    if [ "${le_serial}" != "${pop3_serial}" -o "${le_serial}" != "${imap_serial}" -o "${le_serial}" != "${imaps_serial}" -o "${le_serial}" != "${pop3s_serial}" ]
    then
        restart_dovecot_if_running
    fi
    exit 0
    
    Make that script executable and set a cronjob to run it:
    Code:
    # cat <<EOF >>/etc/cron.d/letsencrypt-restarts
    15 3 * * *  root  /usr/local/sbin/letsencrypt-for-mail.sh
    EOF
    
    # chmod +x /usr/local/sbin/letsencrypt-for-mail.sh
    
     
    Last edited: Mar 20, 2017
    cjsdfw, ahrasis, liane and 5 others like this.
  2. Hi,
    this sounds great!
    Thanks for this tutorial.
    However I am in fear of breaking my server when doing this as I do not have a separate mail server.
    Will the new features of letsencrypt certificates for basically everything (panel, email) be included soon into ISPconfig?
    Will it take up to 3.2 for that?
     
  3. Jesse Norell

    Jesse Norell ISPConfig Developer Staff Member ISPConfig Developer

    I'd guess 3.2, but too early to say, and the rfe (https://git.ispconfig.org/ispconfig/ispconfig3/issues/3987) is not tagged with a milestone. It's not a tremendous amount of work to get it integrated, but there are still some bugs being found/fixed in 3.1 and of course everyone is anxious for a stable release, so unless it catches a developer's fancy to implement it right away, I'd expect it more in the 3.2 timeframe. It's not difficult to setup manually (if it were part of a Perfect Server guide, you'd never know the difference...), and after 3.1 ispconfig is going to target a stable release every 6 months, so seems reasonable to wait, as it'll get there pretty soon either way.
     
  4. MaxT

    MaxT Member HowtoForge Supporter

    Please, just one question,
    Can I have different Let's Encrypt certificates for several domain names using the same IP?
     
  5. Jesse Norell

    Jesse Norell ISPConfig Developer Staff Member ISPConfig Developer

    No, as postfix does not support SNI, you cannot have multiple certificates. What you can do that might fit your needs is request a single certificates and add additional names to it. That would work if the number of names you want to add isn't too large (the limit is maybe 100, from memory?) and if you don't need to change it too frequently and hence hit the limits for requesting certificates.
     
  6. MaxT

    MaxT Member HowtoForge Supporter

    Do you mean different domain names for one certificate, or many subdomains from an unique domain name?

    thanks for the help!
     
  7. Jesse Norell

    Jesse Norell ISPConfig Developer Staff Member ISPConfig Developer

    Both/either. All the names you provide must resolve in DNS to your server's ip address so letsencrypt can authorize them. The example above shows this being done with:
    Code:
    -d `hostname -f` -d mail.`hostname -f`
    You just add more "-d domain" names to the request.
     
  8. MaxT

    MaxT Member HowtoForge Supporter

    ok...
    Until today I thought that one SSL certificate only can work with an unique domain name, except in the case of the expensive multi-name certificates.

    So, if I understand you, with Let's encrypt I can generate one certificate to work with Aname.com and Bname.com, with both names using the same ip.
    That's correct?

    (I'm sorry for my insistence, I think I was really confused)

    thanks!:)
     
  9. Jesse Norell

    Jesse Norell ISPConfig Developer Staff Member ISPConfig Developer

    Yes, just make sure both Aname.com and Bname.com are setup in DNS to resolve to that same ip.
     
  10. MaxT

    MaxT Member HowtoForge Supporter

    yes, I will do. Thanks for your help! :)
     
  11. kerrsmith

    kerrsmith Member

    Hi Jesse,

    Yesterday I added an SSL certificate to my ISPConfig control panel by linking it in the ispconfig.vhost to the certificates I had created for the domain I also have set up (for example I use mydomain.com to host a site and also mydomain.com:8080 to access the control panel).

    https://www.howtoforge.com/communit...-let-encrypt-control-panel-certificate.74113/

    This works and now I have SSL for both site and control panel.

    Could the same method be used for Postfix and Dovecot if I added a subdomain called mail.mydomain.com (according to the forum ISPConfig already adds subdomains to the SSL certificate automatically when you add them).

    If this works it would mean I do not have to manually generate the certificates for mydomain.com and mail.mydomain.com as they would already be created by ISPConfig and they would automatically update.
     
  12. Jesse Norell

    Jesse Norell ISPConfig Developer Staff Member ISPConfig Developer

    Yes, that should work to get other names added into the certificate.
     
  13. CreeWarrior

    CreeWarrior Member

    Hi
    i have followed the perfect server tutorial for ubuntu 16.04, and the part where you install letsencrypt i decided to use apt-get install letsencrypt which install just fine then proceeded to install ispconfig. everything went fine with the install, however ispconfig would not allow me to use letsencrypt evertime i would check the letsencrypt check box it would never save. I check the log in /var/log/letsencrypt/letsencrypts.log and it would say something about no client permission and invalid response from domain.tld and www.domain.tld. I could manualy create the cert using letsencrypt certonly which seemed to work fine. I created a cert for the control panel and mail server with some help for your other tuts.

    So unistalled letsencrypt and installed certbot as per the perfect server tutorial and now the control panel create ssl certs for any site no prob. Now i try to follow this tut and when i enter the command
    Code:
    certbot auth --text --agree-tos --standalone --email postmaster@`hostname -d` -d `hostname -f` -d mail.`hostname -f`
    i get
    Code:
    certbot: command not found
    Which seems strange, cause ispconfig create certs no problem. I assume the ispconfig must use a command similar if not the same to autmatically create certs within the control panel.
     
  14. Jesse Norell

    Jesse Norell ISPConfig Developer Staff Member ISPConfig Developer

    What packages did you install? It should be 'certbot' and 'python-certbot-apache' I believe, plus their dependencies. But even just the 'certbot' package should give you /usr/bin/certbot: http://packages.ubuntu.com/yakkety/all/certbot/filelist

    (note I don't have a ubuntu 16 server to reference, I'm just searching)
     
  15. CreeWarrior

    CreeWarrior Member

    Hi,
    I had originally installed
    Code:
    apt-get install python-letsencrypt-apache
    This came form the letsencrypt website https://certbot.eff.org/#ubuntuxenial-apache
    Which gave me access to
    Code:
    letsencrypt --apache certonly
    which work fine to manualy create certs like i did for my control panel and mail server. however i would not work in the control panel to create certs for website automatically.
    So i uninstalled it from my system and installed certbot like the way you have it at the begining of this thread using
    Code:
    mkdir /opt/certbot
    cd /opt/certbot
    wget https://dl.eff.org/certbot-auto
    chmod a+x ./certbot-auto
    ./certbot-auto # (answer "no" to continue)
    
    cause that was the same way to do it in the perfect server guide
    I just found out that if i use
    Code:
    ./certbot-auto certonly
    I can create certs manually, how ever i have to be in the directory /opt/certbot for it to work.
     
    Last edited: Oct 5, 2016
  16. kerrsmith

    kerrsmith Member

    Hi Jesse,

    I decided to use your method for creating the certificates as it seemed better than making sub domains. The only issue I had was when I pasted in:

    certbot auth --text --agree-tos --standalone --email postmaster@`hostname -d` -d `hostname -f` -d mail.`hostname -f`

    My server did not like the ` symbols when copied from your example so I manually entered the domains I needed, as mentioned above I also had to navigate to /opt/certbot directory and use ./certbot-auto to run the code (I am using Debian Jessie and certbot was installed as you detailed in the top post).

    ./certbot-auto auth --text --agree-tos --standalone --email [email protected] -d pop3.my.domain -d smtp.my.domain

    On a side note I also used this method to create my pure-ftpd certificate, this appears to use a single reference to a certificate so I had to run the following command when it was created:

    cat privkey.pem fullchain.pem > /etc/ssl/private/pure-ftpd.pem

    (from https://www.howtoforge.com/community/threads/letsencrypt-and-pure-ftpd.72000/)

    This command will need to be added to a cronjob as once the certificate renews it will need to be run again.
     
  17. kerrsmith

    kerrsmith Member

    Just a quick update:

    I decided I should probably have added my root domain name as well as the sub domain names in the certificates. I had a read up on certbot's webpage about the command line options:

    https://certbot.eff.org/docs/using.html#command-line

    I could not find anything directly on the 'auth' part of the certbot-auto command but did see it mentioned as 'aka auth' on the 'certonly' option so decided to use 'certonly' instead so my code followed their examples.

    I was a bit unsure about what would happen if I created a new certificate that included a domain name that was already in another one (my web server one) but on the certbot renewing-certificates page it said using the 'certonly' option would create a new certificate:

    https://certbot.eff.org/docs/using.html#renewing-certificates

    I created the following code:

    ./certbot-auto certonly --text --agree-tos --standalone --email [email protected] -d mydomain.com -d pop3.mydomain.com -d smtp.mydomain.com

    When it ran (after I stopped Apache running) it said I already had a certificate with some of the domain names in it and did I want to just add mydomain.com to this one (it showed the one it was asking about and it was the mail server certificate) - I said yes and it updated the certificate already created the other day.

    This left me with my original web server certificates and an updated set for my mail server (I also did the ftp one again as well using this method.)

    Just thought I would post this update as I could not find much information about creating certificates that included a domain name that featured in a certificate that had already been created.
     
    Last edited: Oct 9, 2016
  18. FirstSoul

    FirstSoul New Member

    Hey Jesse,

    Thanks! And... Did the automatic renew worked? Or must i do something?
     
  19. Jesse Norell

    Jesse Norell ISPConfig Developer Staff Member ISPConfig Developer

    Yes, I'm now on my third renewal (May, July, September). One thought on that is it might not hurt to disable debian's certbot cronjob (/etc/cron.d/certbot), as the ispconfig renewal is smarter - if any certificates are renewed, it will also reload (restart?) the web server. Likely your web server will get restarted within a month's time anyways, but on systems that don't change config much, there's a chance the debian cronjob would renew the certificate, and the webserver would never reload and you'd get expired certificate errors after a month or so.
     
    CreeWarrior likes this.
  20. FirstSoul

    FirstSoul New Member

    Great! thanks! i don't have /etc/cron.d/certbot, because i use ubuntu. i think it will work.
    the only thing i must test, if the FTP Server will restart :) Thanks!
     

Share This Page