it would be great if, as part of the SSL integration, ikiwiki-hosting would call up on the letsencrypt.org gods to install proper certs.

First implementation

so far I have done this by hand, using the main client (previously called letsencrypt, now called certbot, those instructions may need to be updated):

  1. define some handy variables:

     domain=example.com
     email=nobody@$domain
     username=w-example
     webroot=/home/$username/public_html/
    
  2. install the letsencrypt client software:

    • if you are on Debian sid, stretch or jessie (with backports):

         apt install certbot
      
    • otherwise, run the magic commands:

         git clone https://github.com/certbot/certbot
         cd certbot
         ./cerbot-auto --help
      
  3. request a certificate:

     sudo -s
     [ -d .git ] && source venv/bin/activate # only use virtualenv if checking out from git
     certbot certonly --webroot \
       --agree-tos \
       --webroot-path="$webroot" \
       --domains $domain --email $email
    

    ... notice how you need to change the two last lines for your environment.

  4. this will create a certificate in /etc/letsencrypt/live/example.com. install it where ikiwiki expects it:

     ln -s /etc/letsencrypt/live/$domain/cert.pem /etc/ikiwiki-hosting/config/$username/ssl.crt
     ln -s /etc/letsencrypt/live/$domain/fullchain.pem /etc/ikiwiki-hosting/config/$username/ssl.chain
     ln -s /etc/letsencrypt/live/$domain/privkey.pem /etc/ikiwiki-hosting/config/$username/ssl.key
    
  5. regenerate the apache configs and restart apache:

     ikisite enable $domain
     service apache2 reload # or restart?
    

Ikiwiki hosting would need to perform steps 3 to 5, and probably have a Recommends on certbot. -- anarcat

Potential clients

Finally, note that there is now a fairly large set of Let's Encrypt clients, here's a short list (those have not been reviewed or tested for compatiblity with ikiwiki-hosting):

  • letsencrypt.sh, bash-only client that should work all Debian releases back to Wheezy
  • simp_le, much simpler implementation in Python (not in Debian)
  • acme, root-less, more minimal implementation than the official client, in Go (ITP for acmetool)
  • acme-tiny is a very small client (~200 lines of python code) that aims to be easily audited and to do only one thing well. for example, you need to generate your RSA key yourself, which may actually be a good thing considering how ikiwiki-hosting works (in Debian stretch and sid)

Renewals

Also, renewals need to be processed in some way. It seems that it's possible to just run:

letsencrypt -c /etc/letsenctypt/renewal/$domain.conf --renew-by-default

--renew-by-default renews every time it's run; --keep-until-expiring instead waits until 30 days before expiry and renews then. I think that's the simpler approach, and the same letsencrypt command line can then both obtain the original cert and renew it. --Joey

True, makes a lot more sense! --anarcat

Actually, the -c /etc/letsenctypt/renewal/$domain.conf doesn't work at all. The 0.4 client features a new renew command that does the right thing (including renewing only if necessary). I tested it here and it seems to work fairly well. My complete update run looks more something like this now: --anarcat

letsencrypt renew --non-interactive
git -C /etc add -A letsencrypt
git commit -m"renew all certs"

So the software name changed: it's certbot now. And yes, the renew command seems to work better. There is a --post-hook that can restart apache and do various things with certs, but unfortunately prior to 0.7, it runs all the time. Normally, the --post-hook is one of those variables that would be saved on renewal, but I haven't tested this because I don't want to have that hook run twice a day. So I'm waiting for this to hit backports before automating this completely, especially since I do not want to diverge from the package's /etc/cron.d/certbot cronjob. My test renewal line now looks like:

certbot --dry-run renew --post-hook 'service apache2 reload; etckeeper commit "certbot renewed domains: $RENEWED_DOMAINS"'

I'll test this again in a few weeks, hopefully when the new package hits backports. --anarcat

Rate limits

Regarding rate limits, they don't seem to be a problem unless you run a really huge site (500 registrations per 3 hours per IP!). The limits are:

  • 100 Names/Certificate (how many domain names you can include in a single certificate)
  • 20 Certificates per Domain per week
  • 500 Registrations/IP address per 3 hours
  • 300 Pending Authorizations/Account per week

That seems to be 5 certificates per domain, not subdomain. Eg, I asked for tmp.kitenet.net 5 times and now it's not allowing getting a cert for downloads.kitenet.net.

So, this seems a pretty big problem; ikiwiki-hosting sites often use subdomains, and if so, quite likely use more than 5. It could keep a site site http-only until it got a cert. But with 100 sites, that would be nearly half a year of delay! And, what about renewal, wouldn't that be rate limited too?

Seems like getting a cert for 100 subdomains under branchable.com (eg), and then moving onto the next cert etc would be the best we could do. But that's a lot more complicated. --Joey

Ouch, yes, that is a significant problem for branchable!!! Maybe this should be brought up upstream... I wonder if this couldn't be a way to finance letsencrypt, to have larger providers pay a monthly fee for the service, and bypass those limits. --anarcat

WP.com switched to LE, so there's probably a way around those. --anarcat

I asked around and the limits were bumped to 20 certs/domain/week recently. Also, they can tweak the limits upon request. --[[anarcat]

Discussion

Oh, and this could be a plugin, not sure if that would make sense, but it's the way it works on that side of the world. --anarcat

I would much rather use something small enough to be reviewable, particularly if we're going to have to run it unattended as root; the official Let's Encrypt client is huge. We don't have to worry about portability to non-Debian environments or non-Apache web servers, which takes away a lot of the reason to use something so big. --smcv

Kind of agreed, but I'm more interested in ameanability to automation than overall code size. https://github.com/hlandau/acme is one client that seems promising. At the moment only letsencrypt is seems packaged in debian yet and that's the first bar. --Joey

Agreed as well. Just scratching an itch here... The acme client looks interesting, but it's go, which brings a whole set of dependencies in. But I like its philosophy and it could integrate well. Also note that the above instructions fail to take into account the canonical and alias names of the site, which breaks openid logins... Something to fix in my future renewals... --anarcat

Here's an interesting puppet implementation that mentions another (!) golang client (lego), which has the interesting property of supporting DNS challenges. The puppet code itself uses the shell script previously mentioned. --anarcat


how to only enable ssl once a certificate is available

Tip from Joey:

Letsencrypt has a bit of a chicken and egg problem, in that the http server has to be up to get the certificate, but the apache site config file has to contain both the http and the https vhost. And the https vhost needs to point to cert files not available until letsencrypt has run.

smcv was thinking about dealing with that by generating a temporary self-signed cert first. But, I don't like the possibility that a http site would come up with such a cert during normal operation.

I found a way around this when adding letsencrypt support to propellor: Make the apache site config file contain only the http vhost, and use IncludeOptional to include another file which contains the https vhost. Generate that file only once letsencrypt has generated the cert.

Note that IncludeOptional has to be used with a wildcard to avoid it being an error if the included file doesn't exist. So, something like:

IncludeOptional /etc/apache2/sites-available/$domain/*.conf

The way I did this here was to generate the cert with the HTTP-only vhost, and only after the cert was generated create the HTTPS vhost... Can't you have a modified HTTPS vhost generated only after the cert is generated? --anarcat