Oleksandr Gavenko's blog
2017-01-25 01:30 Setting Let’s Encrypt on Lighttpd

Tonight I'll show how to set Let’s Encrypt forLighttpd.


Let’s Encrypt is a free, automated, and open Certificate Authority.

Serving site via HTTP means that user interaction with server can be intercepted, studied, altered.

If you are prompted to enter password on HTTP page most probably it will be send in clear text across HTTP...

Browsers have ability to hide interaction with user. It was done via SSL/TSL standards.

Unfortunately on time of creation of these standards they dealt with another problem - how user can trust server. It is resolved with using of certificates.

Certificated are ordered in chain of trust. Certificate issuers ask browser vendors to include their root certificates in browser distribution. If you haven't managed certificates in browser in any way that root certificates are trusted by you by default...

Certificate issuers sell signature for certificate for site owners and site owners embed own certificate with issuer signature in web servers.

Within browser along with HTML pages you get site owners certificate with issuer signature. Signature checked, browser checks if issuer is known and included in trusted database and if all OK it decides to trust to site and establish encrypted connection with server.

This model have some sides of attack but we here is not going to discuss SSL/TSL security.

Among all that do certificate issuers and site owners, web server and browser implementation of SSL/TSL protocol we have encrypted connection between browser and server.

While authentication of server is a good thing call for secured communication is more important nowadays. It is mathematically possible to establish secure connection between server and browser without selling signatures but industry stuck with historical implementations and can't move further.

Let’s Encrypt project bring encryption to historical implementations by supplying site owners with free of cost SSL/TSL certificates.

Their root certificate already included in all major browsers and software distributions certificate stores. Of cause this root certificate marked as weak and have only intention to establish encryption between points.

Let’s Encrypt organization performs basic checks before singing your certificate - if you own domain name and server behind that domain name.

They developed protocol to automate issuing of certificate signatures.

certbot is client that implement that protocol.


Automatically enable HTTPS on your website with EFF's Certbot, deploying Let's Encrypt certificates.

It is available in Debian repositories:

$ sudo apt install python-certbot

certbot designed to be extensible via plug-ins but at this moment there is no plug-in for Lighttpd. Although there is generic method implemented in webroot plug-in that provide automatic updated of certificates.

webroot plug-in put special files into you site web root directory under /.well-known/ sub-directory and Let’s Encrypt service expect to find that file under HTTP /.well-known/ path to be shure that you are domain/site owner.

Cron job for lighttpd and certbot is:


# -q  quiet
# -n  do not prompt
#  --webroot  plugin
certbot certonly -n --expand --webroot \
  -w /srv/www/base/ -d defun.work \
  -w /srv/www/blog/ -d blog.defun.work \
  -w /srv/www/resume/ -d resume.defun.work \
  -w /srv/hg/ -d hg.defun.work



cat $privkey $cert >$server_pem
cat $chain >$chain_pem

service lighttpd restart

Paths to certificates defined in one of:

$ cat /etc/letsencrypt/renewal/defun.work.conf

# renew_before_expiry = 30 days
version = 0.9.3
cert = /etc/letsencrypt/live/defun.work/cert.pem
privkey = /etc/letsencrypt/live/defun.work/privkey.pem
chain = /etc/letsencrypt/live/defun.work/chain.pem
fullchain = /etc/letsencrypt/live/defun.work/fullchain.pem

# Options used in the renewal process
authenticator = webroot
installer = None
account = XXXXXX
webroot_path = /srv/www/base, /srv/www/blog, /srv/www/resume, /srv/hg
resume.defun.work = /srv/www/resume
defun.work = /srv/www/base
hg.defun.work = /srv/hg
blog.defun.work = /srv/www/blog

Configuration for static site hosting by lighttpd is looking like:

$ cat /etc/lighttpd/conf-available/92-resume.conf

$HTTP["host"] == "resume.defun.work" {
  server.document-root = "/srv/www/resume"

Configuration for SSL:

$ cat /etc/lighttpd/conf-available/10-ssl.conf

$SERVER["socket"] == "" {
  ssl.engine  = "enable"
  ssl.pemfile = "/etc/lighttpd/server.pem"
  ssl.ca-file = "/etc/lighttpd/chain.pem"

  ssl.cipher-list = "ECDHE-RSA-AES256-SHA384:AES256-SHA256:!RC4:HIGH:!MD5:!aNULL:!EDH:!AESGCM"
  ssl.honor-cipher-order = "enable"

The only problem I have is with GCI hosted Mercurial, I added exception in activation of CGI, any request to /.well-known/ is hosted as file resource:

$ cat /etc/lighttpd/conf-available/92-hgweb.conf

$HTTP["host"] == "hg.defun.work" {
  server.document-root = "/srv/hg"
  url.rewrite-once = (
    "/static/avatar/(.*)" => "/$1",
    "/.well-known.*" => "$0",
    "^/?(.*)" => "/hgweb.cgi/$1",
  $HTTP["url"] !~ "^/.well-known" {
    cgi.assign = ( "/hgweb.cgi" => "" )
  setenv.add-environment = ( "HGWEB_CONFIG" => "/srv/hg/hgweb.config" )
  dir-listing.activate = "disable"
  index-file.names = ()

Let’s Encrypt issues single SAN (Subject Alternative Name) certificate and with modern browsers this allows serving virtual hosts via HTTPS via single IP.

See also:


Certbot manual on usage.


SSL on multiple domains.


How To Set Up Multiple SSL Certificates on One IP with Lighttpd.

That's all for this night!

UPDATE. Some old mobile browser report that sertificate is not valid.

You can figure out problems with your site certificate via online service:


My site missed intermidiate certificate. It's due to Let's Encrypt is not in old program trusted storages. As workaround Let's Encrypt have signature from DST Root CA X3 which is already in trusted storages.

In order to pass that intermidiate / chain certificate I should tell Lighttpd where it is:

ssl.ca-file = "/etc/lighttpd/chain.pem"

See also:


Request for combined priv/pub certificate for Lighttpd.


Docs about support of intermidiate/chain certificate in Lighttpd.


Page for testing Let's Encrypt certificate in real browser.


List of supported by Let's Encrypt certificate clients.


List of supported by Let's Encrypt certificate clients.

security, lighttpd, admin, web


all / emacs / java / python


admin(1), anki(1), blog(1), css(2), cygwin(2), emacs(3), fs(1), git(2), gradle(1), hg(2), html(1), interview(11), java(2), js(3), lang(2), lighttpd(1), mobile(1), naming(1), oracle(1), print(1), problem(5), quiz(6), rst(1), security(1), sql(2), srs(1), style(1), unit(1), utils(1), vcs(3), web(2), win(2)