Let's Encrypt for mail.domain.com

I have been using this script below to create the certificates for the domain to also include mail.domain.com, however since mail.domain.com does not have a webroot the method that is utilized is to point to /var/www or the directory that is the default webroot for the server.

Script for a single domain cron job:

cd /root/letsencrypt/ && mkdir -p /home/domain/ssl_certificates && ./letsencrypt-auto certonly --email info@domain.com --agree-tos --webroot --renew-by-default -w /home/domain/public_html/ -d www.domain.com -d domain.com -w /var/www -d mail.domain.com && cp -f /etc/letsencrypt/live/www.domain.com/cert.pem /home/domain/ssl_certificates/cert.pem && cp -f /etc/letsencrypt/live/www.domain.com/chain.pem /home/domain/ssl_certificates/chain.pem && cp -f /etc/letsencrypt/live/www.domain.com/fullchain.pem /home/domain/ssl_certificates/fullchain.pem && cp -f /etc/letsencrypt/live/www.domain.com/privkey.pem /home/domain/ssl_certificates/privkey.pem

To follow the existing virtualmin convention SSL files should be in the /home/user/ root but while this script in still in 'beta' the /ssl_certificate/ folder is used for time being to avoid any conflict if a paid certificate is to be used in case anything were to block the usage of letsencrypt certs.

Status: 
Active

Comments

The following is untested pseudo code for the feature request.

https://github.com/webmin/webmin/blob/c7d2d2a78a7ddd0a04399fedef06d5f1c9...

####
# Untested pseudo code...
# Replaces line 34 in letsencrypt-lib.pl
# https://github.com/webmin/webmin/blob/c7d2d2a78a7ddd0a04399fedef06d5f1c9...
###

# Replace the www. prefix if it was specified. For purposes of mail host www. alias not used.
my $mail_domain = $dom;
$mail_domain =~ s/^www./''/g;

#webroot-path for mail.domain.suffix is specified here as /var/www, but should be the default Apache/nginx root as mail.domain.com does not have its own mail root.

my $out = &backquote_command("cd $dir && (echo A | $letsencrypt_cmd certonly -a webroot ".join(" ", map { "-d ".quotemeta($_) } @doms)." --webroot-path ".quotemeta($webroot)." -d mail.".$mail_domain." --webroot-path /var/www --duplicate --config $temp 2>&1)");

FYI, the next Virtualmin release will let you enter whatever hostnames you like for inclusion in the Let's Encrypt cert request.

Ok, I'm not sure I've made this issue entirely clear. Since the DNS entry for mail.domain.com actually points to the shared IP or dedicated IP it does not have its own webroot within the /home/user/public_html/. This is problematic for ACME whereby it cannot validate the ownership of mail.domain.com request by placing a nonce in the .well-known folder for that host.

So this code 'fakes' or directs the webroot validation to /www/var so that the webroot validation of the ACME client is able to authenticate the host mail.domain.com and add mail.domain.com certificate to the SSL keychain.

I still don't think this is clear enough, but heck, if don't try you can't succeed.

Hi Jamie and Team,

After much trial and error I'm happy to contribute this code which will create certs for mail.domain.com, www.domain.com and domain.com from the Let's Encrypt Tab.

Two issue

  • Only supports apache web server
  • Values for DocumentRoot for Apache only support Debian/Ubuntu, and should detect Flavor and path of actual root
  • This code goes into /usr/share/webmin/webmin/letsencrypt-lib.pl

    # Build command for mail.domain.com webroot
    my $mail_domain = $doms[0];
    # Strip any www. prefix from mail server purposes
    $mail_domain =~ s/^www.//g;

    # Prototype Method for Debian/Ubuntu only
    # get DocumentRoot
    $cmd  = "grep -i DocumentRoot /etc/apache2/sites-available/default";
    my $mail_root = `$cmd`;
    $mail_root =~ s/^DocumentRoot //g;
    my $mail_cert_cmd = "-w ".quotemeta($mail_root). " -d mail.".$mail_domain;


    my $out = &backquote_command("cd $dir && (echo A | $letsencrypt_cmd certonly --webroot ".$mail_cert_cmd." -w ".quotemeta($webroot)." ".join(" ", map { "-d ".quotemeta($_) } @doms)." --duplicate --config $temp 2>&1)");

    Below is what the entire sub request_letsencrypt_cert looks like with modifications. It will likely need some refactoring. The idea was simply to get a working prototype.

    sub request_letsencrypt_cert
    {
    my ($dom, $webroot, $email) = @_;
    my @doms = ref($dom) ? @$dom : ($dom);
    $email ||= "root\@$dom";
    my $temp = &transname();
    &open_tempfile(TEMP, ">$temp");
    &print_tempfile(TEMP, "email = $email\n");
    &print_tempfile(TEMP, "text = True\n");
    &close_tempfile(TEMP);
    my $dir = $letsencrypt_cmd;
    $dir =~ s/\/[^\/]+$//;

    # Build command for mail.domain.com webroot

    my $mail_domain = $doms[0];
    # Strip any www. prefix from mail server purposes
    $mail_domain =~ s/^www.//g;

    # Prototype Method for Debian/Ubuntu only
    # get DocumentRoot
    $cmd  = "grep -i DocumentRoot /etc/apache2/sites-available/default";
    my $mail_root = `$cmd`;
    $mail_root =~ s/^DocumentRoot //g;
    my $mail_cert_cmd = "-w ".quotemeta($mail_root). " -d mail.".$mail_domain;

    my $out = &backquote_command("cd $dir && (echo A | $letsencrypt_cmd certonly --webroot ".$mail_cert_cmd." -w ".quotemeta($webroot)." ".join(" ", map { "-d ".quotemeta($_) } @doms)." --duplicate --config $temp 2>&1)");
    if ($?) {
    return (0, $out);
    }
    my ($full, $cert, $key, $chain);
    if ($out =~ /(\/.*\.pem)/) {
    # Output contained the full path
    $full = $1;
    }
    else {

    Hi I've tried adding this code in Virtualmin GPL 5.07 but now when I click Let's Encrypt to get the certs I get this error:

    Error - Perl execution failed

    Undefined subroutine &webmin::request_letsencrypt_cert called at /usr/share/webmin/virtual-server/feature-ssl.pl line 2154.

    soydemadrid - are you running Webmin 1.830 there?

    hi thanks for the reply. I'm running Webmin 1.831

    Hi there,

    I think this topic should definitely be prioritized by the Virtualmin developers. Using the integrated Let's Encrypt script in Virtualmin does still not work for generating a certificate for mail.ANYdomain.tld .

    I am running on the latest Webmin 1.850 with Virtualmin 5.99 .

    The perl script for lets encrypt did change a bit, didn't it? Can somebody tell me how I should update the perl script so it works for mail.ANYdomain.tld ?

    I am not a pro in Virtualmin nor in perl and I really do not want to mess my Virtualmin configuration.

    The real problem here is that Apache isn't configured to accept requests for mail.domain.com, and so the usual method of generating Let's Encrypt certs doesn't work. The work-around is to either configure Apache manually to add mail.domain.com as one of the ServerAlias entries for domain.com, or add a Virtualmin alias domain for mail.domain.com.

    By default, Apache will accept requests for domain.com and www.domain.com - hence those domains get included in the SSL certificate request. Our recommendation, and what's included in the mail client autoconfig setup in the latest release, is for mail clients to just use domain.com for SMTP and IMAP connections over SSL.

    IMAP and POP3 are similar -- if you wish to use POP3 rather than IMAP, Jamie's suggestion still applies... using "domain.com" is a simpler option for that too.

    And you can use SSL over POP3 or IMAP.

    Probably Virtualmin should include mail.domain.com in the list of Apache aliases, so that an SSL cert can be requested for it as well - I will look into this.

    Any news on this? I'm having the same issue. : )

    Workaround also is to create alias virtualserver for mail.domain.tld

    Then put the mail. in the ssl LE CERT list at maindomain, and let the CERT path pointing to the maindomain cert where then the alias mail.domain.tld is also on the cert.

    IN short. ;)

    Otherwise read above for other workarrounds.

    Right now by default Virtualmin doesn't setup Apache to accept requests for mail.domain.com, but you can set this up for new domains at System Settings -> Server Templates -> Default Settings -> Apache website.

    Someone would have to try the approach of adding "ServerAlias mail.${DOM}." and report back their findings. Even though it is an alias for that host would it be sufficient for a cert be issued and renewed... that is the question.

    Would be cool if anyone could try that on their test setup, I don't have a test setup, and a bit scared to brick my up and running one :p

    Submitted by JamieCameron on Tue, 07/18/2017 - 00:25 Comment #13

    By default, Apache will accept requests for domain.com and www.domain.com - hence those domains get included in the SSL certificate request. Our recommendation, and what's included in the mail client autoconfig setup in the latest release, is for mail clients to just use domain.com for SMTP and IMAP connections over SSL.

    So the above makes dovecot happy since it can have multiple certificates using the local domain name, but if I am trying to use STARTTLS or TLS for smtp outbound, Postfix can only use one certificate (unless you have an IP for every domain).

    So the only way to make that happen is a certificate with each domain name (mail.xxxx.com) in the certificate. And.... every time I create a new domain and letsencrypt creates the certs for domain and www.domain, I have to get a new cert for postfix is all the existing mail.xxxx.com and now add the new one.

    Yes, adding the ServerAlias line is the right thing to do.

    As for that flush_files_lines error, can you try adding the line error_stack=1 to /etc/webmin/config , re-trying setting up SSL, and post the full error message here?

    //EDIT// Rebooted server, all working fine now ; ).

    Just weird that 'admin and webmail' are also mentionned as ServerAlias but he doens't generate certificates for that.

    Best regards

    Just add

    ServerAlias mail.${DOM}

    to Directives and settings for new websites

    under

    Virtualmin / System Settings / Server Templates / select default / in drop down menu select apache website.

    You will then have the server alias in all apache files for all domains created using virtualmin and it will show up in the list for inclusion on letsencrypt certs. Its a very easy and simple thing to do.

    If you want to add other aliases instead of mail just add

    ServerAlias whateveraliasyouwantl.${DOM}

    Hope that helps everyone