Webroot and https-only server impossible

I’ve read the documentation of certbot and the only way for me to get certificates without having certbot changing my web server config files or restarting my web server is to use the webroot plugin.
But this plugin only uses http-01 for authentication, which means I cannot have a https-only setup on my server.

Is there a reason for this? I might understand that http-01 is necessary for the first certificate (unless you already have a valid ssl cert), but it makes no sense to keep a non-ssl config and server setup forever just to renew my certs.

Are there any certbot developers here who can shed some light on this?

2 Likes

Hi @tessus,

The way that the TLS-SNI-01 authentication method works is by reconfiguring your web server to serve a custom certificate. This, in turn, can only be done by editing its configuration files and reloading the server.

HTTP-01 is defined by the ACME standard to require HTTP on port 80 (never HTTPS on port 443) for reasons that have to do with the defaults in some shared hosting environments, where the previously-proposed HTTPS-01 authentication method would have allowed some shared hosting users to obtain certificates for other users’ domains. The people defining the standard considered this an unacceptable risk and removed HTTPS-01 from the specification; HTTP-01 isn’t believed to have this particular problem.

You might also want to look at the DNS-01 method, which is not as well supported by Certbot, but doesn’t require the certificate authority to connect to your server at all. This method is well-supported by some of the alternative clients, especially those written in bash.

Thank you very much for the explanation.

I was actually thinking about DNS-01. Unfortunately I don’t run my own DNS server, but use off-site ones. One is configured via the registrar and the other one is a high performance / fault tolerant DNS provider. This makes automation a bit problematic. I would have to manually update the DNS entries every time I renew a certificate. This might be doable, if the certs were valid for 2 or 3 years, but I won’t do this every 30-60 days. But even then, it would be a pain in the neck, since I use quite a few sub domains and also use a wildcard DNS entry for one domain.

I hoped I could turn off port 80 completely on my server, but it seems I am out of luck. I’m not comfortable with other software modifying my Apache configuration or restarting it. This is a fantastic solution for web hosters or people who have one simple domain on one server, but it doesn’t fit my needs. I wish it would though.

If I were able to use my own virtual host templates which certbot modified, it would be a lot more convenient. Although restaring the server every time a renewal is in place (just for verifcation) seems a bit heavy. Would be ok for reverse proxies though.
This fully automated system is something I have to get used to first.

Anyway, I think the idea of certbot and ACME is quite ingenious.

Maybe I have to look into the usage of hooks. I’m too busy to write my own ACME client.

Generally it would be considered inadvisable to completely disable port 80, as it can host a 301 redirect in order to upgrade requests to HTTPS, at least until a request for HSTS preloading propagates to all major browser vendors.

I had same issue, Lets’ encrypt does the challenge on port 80. Easy to solve though. Your port 80 site must have 2 location directives, one for the challenge, and another for the redirect to https

server {
	# SSL configuration
	#
	listen *:443 ssl http2;
        listen [::]:443 ssl http2;
        .........
    }
    server {
	listen *:80;
        listen [::]:80;    
  	server_name mywebsite.com www/mywebsite.com;
	# ACME Challenge Rule
        location /.well-known {
    	        alias /var/www/mywebsite.com/.well-known;
  		allow all;
    	        default_type "text/plain";
    	        autoindex    on;
                }
        location / {
  		return 301 https://mywebsite.com$request_uri;
                }
	access_log /var/log/nginx/mywebsite.com-access.log;
	error_log /var/log/nginx/mywebsite.com-error.log;
}

and I must give credit, I found the solution here - Cannot renew certs when redirecting http to https and all my renewals now work flawlessly using webroot

Many of the DNS providers have APIs which can be used for this purpose. I think acme.sh's support might be the most extensive:

You are right @BFeely, this is the only reason why I still run http. However, right now I use one directive in the virtual host stanza for http and now I will have to use at least 10 (Document root, rewrite engine and rules, …).

1 Like

@MitchellK thanks, my current config looks similar, but with Apache.

1 Like

I don’t think all of this is necessary. The HTTP-01 validator is willing to follow redirects, including redirects to HTTPS. I think a number of people have continued to use webroot successfully on servers that perform a blanket redirect from the HTTP site to the HTTPS site.

2 Likes

@schoen yea, I’ve checked a while back and an API is only available for the DNS provider. And they changed owners, so a lot of things were “in transition”. Anyway, maybe I should look into this again.

@schoen this sounds promising. thank you. just another quick question:

certbot certonly --webroot -w /var/www/example/ -d www.example.com -d example.com -w /var/www/other -d other.example.net

Will this command create 2 different temporary files in /var/www/example/ and 1 temporary file in /var/www/other, or will it create the same file in all locations?

One file per subject name, so two in /var/www/example and one in /var/www/other.

@schoen thanks a bunch for all your answers. Have a great weekend.

I certainly have. On Apache, I initially set up on port 80 for the initial cert, and then change port 80 to redirect to https after getting the cert set up. It renews quite nicely, going through the redirect when authenticating.

Here are a my settings for dovecot and sendmail as a reference. I read up on that topic and all of the answers and blog posts are actually wrong or miss the background.

dovecot (dovecot.conf):

ssl_cert = </etc/letsencrypt/live/CERTNAME/fullchain.pem
ssl_key = </etc/letsencrypt/live/CERTNAME/privkey.pem

sendmail (sendmail.mc):

define(`CERT_DIR', `/etc/letsencrypt/live/CERTNAME')
define(`confCACERT_PATH', `CERT_DIR')
define(`confCACERT', `CERT_DIR/fullchain.pem')
define(`confSERVER_CERT', `CERT_DIR/cert.pem')
define(`confSERVER_KEY', `CERT_DIR/privkey.pem')
define(`confCLIENT_CERT', `CERT_DIR/cert.pem')
define(`confCLIENT_KEY', `CERT_DIR/privkey.pem')

define(`confDONT_BLAME_SENDMAIL',`groupreadablekeyfile')dnl

sendmail does not like the key with permission 644, thus it starts up, but it does not accept TLS connections.
To solve this problem, one has to set the permission of the private key as follows:

chmod 640 /etc/letsencrypt/live/CERTNAME/privkey.pem

As for confCACERT: this parameter is supposed to hold the CA bundle, but most systems do not have a recent version that does include the CA and intermediary certs of Letsencrypt. There are several option to solve this problem:

  • download a newer ca-bundle (curl has usually very recent ones, mozilla is also a good source)
  • add the letsencrypt root and intermediate certs to your bundle manually
  • use a workaround (other would call it a hack) and use the fullchain.pem, since it includes all necessary certs

The confCLIENT_* parameters are not really needed but don’t hurt either. Letsencrypt does not provide client certs so setting up a “local” CA that allows people to use client certs to authenticate against sendmail is pretty much useless.

Sendmail also likes to complain about certs that are group readable. Either change the permission of the certifcates to 600, or use the confDONT_BLAME_SENDMAIL directive.

In any case, the renewal of certs will change the permission back to 644 and sendmail will stop working again. Two options are available:

  • ask EFF to change the certbot script to set the correct permission for the private key
  • use a --renew-hook to do the work

Here’s my renew hook script:

#!/bin/bash

set -e

RESTART=0
LOG="/var/log/letsencrypt/renewal.log"

if [ -e $LOG ]; then
	mv $LOG $LOG.save
fi

for domain in $RENEWED_DOMAINS; do
	case $domain in
		CERTNAME_THAT_YOU_USE_FOR_DOVECOT_AND_SENDMAIL)
			RESTART=1
			DT=`date +"%Y-%M-%d %H:%M:%S %z"`
			echo "$DT   [ Certificate ]   $domain" >>$LOG
			DT=`date +"%Y-%M-%d %H:%M:%S %z"`
			echo "$DT   [   Restart   ]   dovecot, sendmail" >>$LOG
			# it's the main cert -> set correct permissions, restart dovecot and sendmail
			chmod 640 "$RENEWED_LINEAGE/privkey.pem"
			systemctl restart dovecot
			systemctl restart sendmail
			;;
		*)
			RESTART=1
			DT=`date +"%Y-%M-%d %H:%M:%S %z"`
			echo "$DT   [ Certificate ]   $domain" >>$LOG
			;;
	esac
done

if [ "$RESTART" == "1" ]; then
	DT=`date +"%Y-%M-%d %H:%M:%S %z"`
	echo "$DT   [   Restart   ]   httpd" >>$LOG
	/usr/local/apache/bin/apachectl -k graceful
fi

Ok, I think that’s it. Cheers. Have fun!!!

I also want to make my solution for ACME challenge available to others. With the following one can use one challenge directory for all virtual hosts and/or subdomains. Add this to your virtual host configs for port 80:

Alias "/.well-known/acme-challenge/" "/data/projects/acme-challenge/.well-known/acme-challenge/"
<Directory "/data/projects/acme-challenge/">
    Require all granted
</Directory>

RewriteEngine On
RewriteCond %{REQUEST_URI} !^/\.well-known/acme-challenge/.*
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [QSA,L,R=301]

Now one can use /data/projects/acme-challenge the webroot directory for all cert requests.

Simply doesn’t follow the redirect on Nginx ??? Unless I specify the location to /.well-known in the port 80 ???

If you are referring to my latest post, I think you did not read it correctly. I decided to use port 80 for the acme challenge after all, because there could be rewrite rules on the web site on port 443 already (which means I would have to either change the web config or the .htaccess file). To make it less work and not dependent on the real web root of the domain, I use the solution I posted.

I also mentioned that I use one single challenge directory (web root) for all virtual hosts (subdomain and domains) that run on this machine.

So now I can run the following command and it works: ./cerbot-auto certonly -w /data/projects/acme-challenge -d domain1.xx -d domain2.xx -d sub.domain3.xx -s sub2.domain4.xx

Sorry didn’t read properly will have a look in the morning, thanks. I do think a single webroot location is best. Sorry so tied for time these days with my dying father I tend to read things in haste and my attention span is shoddy to say the least.

Hey, no worries. I did not judge, merely pointing out that you might have misunderstood. All the best with your father.