Multiple domains & webroot paths using webroot plugin

Hi all, I have a few questions specifically regarding the use of the “webroot” plugin under a Debian-based Linux distribution (Ubuntu).

I understand that letsencrypt issues SAN certificates valid for 90 days. This means that the certificate can be used for multiple (sub)domains, but must be renewed at least once every 90 days.

The intent: secure multiple subdomains served over multiple webroot paths (virtual hosts). e.g.

webroot path: /var/www/

webroot path: var/www/

webroot path: var/www/

I presume we could do this in shell:

./letsencrypt-auto certonly --webroot -w /var/www/ -d -d -w /var/www/ -d -w /var/www/ -d -d -d


  1. If my understanding is correct, I believe only 1 certificate will be created. Is the resultant certificate stored in /etc/letsencrypt/live/ or /etc/letsencrypt/live/ or some other location?

  2. Let’s say authentication fails for one of the subdomains - say, Will a certificate still be issued for the rest of the domains that pass authentication?

  3. The docs say that /etc/letsencrypt/cli.ini is searched for configuration by default. Does this mean cli.ini is always applied for every execution of ./letsencrypt-auto? If the cli.ini specifies a different webroot path, does it overwrite the command line arguments?

  4. Is there a way to do the above using a config file? i.e. executing ./letsencrypt-auto --config /etc/letsencrypt/myconfig.ini will create the necessary certificate(s) for all the above domains across multiple webroot paths. I have read through a ton of resources in the forum but cannot seem to find any examples of multiple webroot paths in a config file.

Thanks for reading. :slightly_smiling:

Finally, a big thank you to letsencrypt for this awesome tool. :evergreen_tree:

2: If one of the domains fails, the whole certificate will fail.

Anyway, the other questions I don’t have a quick answer to.

Why don’t you find out? You can test all your questions by adding --test-cert to the options. This way, the Let’s Encrypt client will perform all the steps on the “staging” server in stead of the “live” server. You’ll end up with a worthless certificate, issued by some sort of “happy hacker” issuer, but other than that, the steps are the same.

And when you’re satisfied, you can remove the --test-cert switch ofcourse, so you’ll end up with a real certificate :wink:

Yes, only one certificate will be created with each domain being in the SAN field. It will be (usually) stored in a directory named after the first domain on the command line.

I believe it will fail completely, as you're asking for a certificate with all those names (and created a CSR with that information).

Switches should override the default ini file. I'm not sure about the order if you specify an ini file using the command.

As far as I am aware, you cannot use multiple webroot paths in the command.

As @Osiris noted, you should use the test server to see what happens. This reduces the load on the production servers and avoids you hitting the rate limits that can prevent you getting a real cert when you're ready.

Yes, you can: one webroot-path per (set of) domain(s). The presumption @godchuanz posted above is correct.

You can add up to 100 different (sub)domains in one certificate. It would be exceptional if all those domains would fall under one webroot :wink:

@Osiris Yups, thanks for the tip on --test-cert switch. Sorry I completely missed that in the documentation. I just started exploring letsencrypt yesterday, and was mostly reading up on the letsencrypt-auto client under --help all, which doesn’t seem to mention it.

I have done some tests and I’m happy to confirm that:

  1. Just as @motoko said, only ONE certificate will be generated in a directory named after the FIRST domain supplied.
  2. As expected, it is ALL OR NOTHING.
  3. If there are conflicting flags, letsencrypt complains with an error and fails. Too many flags setting...
  4. There doesn’t seem to be a way to specify multiple webroot paths in a config file. At this point, my impression is that the command line can pretty much do everything that it needs, so the use of a config file is not really necessary. In fact, it appears to be less powerful than the command line. Even for the sake of automation, I think setting up a shell script with all the correct variables seem to be the simplest solution.

For the benefit of anyone trying to set up multiple sub-domains, this is the way I’m doing it for multiple virtual hosts in Apache HTTPD.

The config file is not necessary, as these can be easily enumerated as flags in the command line. But just for the sake of demonstration:

* cli.ini *
rsa-key-size = 4096
server =
email =
text = True
agree-tos = True
renew-by-default = True
authenticator = webroot

I created a shell script to do the entire authentication command for all webroot paths and domains at one go.

* /usr/bin/ *

# Settings
TIMESTAMP=$(date +"%F %T")

# Execute
/etc/letsencrypt/letsencrypt-auto certonly -t --renew-by-default --test-cert \
-w /var/www/www.$DOMAIN/ -d $DOMAIN -d www.$DOMAIN \
-w /var/www/admin.$DOMAIN/ -d admin.$DOMAIN -d adm.$DOMAIN \
-w /var/www/api.$DOMAIN/ -d api.$DOMAIN

# Log and restart web server
if [ $? -ne 0 ]
      echo "["$TIMESTAMP"] Cert for "$DOMAIN" could NOT be renewed!" >> /var/log/letsencrypt/sh-renewals.log
      echo "["$TIMESTAMP"] Cert for "$DOMAIN" renewed!" >> /var/log/letsencrypt/sh-renewals.log
      service apache2 reload

exit 0

I could also have set it up to mail the output to me, but I’m leaving it out of the script for simplicity.

As shown, I test run it with the --test-cert flag just to ensure that the rest of the infrastrcuture is in place (DNS, firewall, webserver’s virtualhost config etc.). If we successfully get the CONGRATULATIONS message from executing


then I know we’re good to go.

I proceed to remove the --test-cert flag from the script and run it again to generate the real certificate.

I then set up a cron job via crontab -e so that the script runs every month:

# add this line to end of file to renew on the 1st of every month, 02:30AM.
30 02 1 * * /usr/bin/

Hopefully, this guarantees that all my sub-domains across various vhosts are always happily TLS-encrypted for free.

Experts, please do enlighten if I missed out anything important, or if I’m doing something wrong or stupid. Thank you!