Lighttpd usable chained file

As to read in the lighttpd docs lighttpd needs a file that contains the privkey.pem and the fullchain.pem (or chain.pem) as “pemfile”. So it would be nice if something like that would be in /etc/letsencrypt/live/…

3 Likes

I have figured out how to get lets encrypt to work with lighttpd. Here’s my redacted cron job that I run once a month:

#! /usr/bin/env bash

cd <letsencrypt folder>

# Stop lighttpd as it is listening on 443 local host and that trips up letsencrypt
/etc/init.d/lighttpd stop

# Stop any other services running on port 80 or 443, even localhost

# Temporarily open port 80 (only necessary if you have iptables blocking port 80
iptables -A INPUT -p tcp --dport 80 -j ACCEPT

# Delete letsencrypt config (to prevent the tool from prompting about replacement):
rm -f /etc/letsencrypt/renewal/*.conf >/dev/null 2>&1

# Generate certs
./letsencrypt-auto certonly --standalone --email [your email] --agree-tos -d [domain one] #-d more.domains.example.com

# Close port 80 (Again you may not want or need this)
iptables -D INPUT -p tcp --dport 80 -j ACCEPT

# The following steps assume one domain, you would need to repeat it for each domain if multiple
cd /etc/letsencrypt/live/[your first domain]/

# Next steps required because lighttpd requires combined private key and cert
mv cert.pem cert_only.pem
    
ls | while read line; do mv "$line" "[domain name]_$line"; done    

echo -e "$(cat [domain name]_privkey.pem)\n$(cat [domain name]_cert_only.pem)" > [domain name]_cert.pem

# Move certs to lighttpd directory
cp * /etc/lighttpd/

# Restart lighttpd
/etc/init.d/lighttpd start

# Restart other services that you killed

Here’s the relevant parts of my lighttpd.conf file:

$SERVER["socket"] == ":443" {
    ssl.engine = "enable"
    ssl.pemfile = "/etc/lighttpd/[domain name]_cert.pem"
    ssl.ca-file = "/etc/lighttpd/[domain name]_chain.pem"
    server.name = "[server name]"
    ssl.use-sslv2 = "disable"
    ssl.use-sslv3 = "disable"
    ssl.use-compression = "disable"
    ssl.cipher-list = "ECDH+AESGCM:DH+AESGCM:ECDH+AES256:DH+AES256:!aNULL:!MD5:!DSS"
    ssl.honor-cipher-order = "enable"
}
2 Likes

Thank you for this quiet comprehensive lighttpd solution. I planned to post something similar in the next days.

My feature request is actually more or less superfluous since with lighttpd one has to script anyway (at least to stop and start lighttpd).

For the sake of completeness (basically same same different for a CentOS system) my version with all the tricks I know:

#!/bin/bash

dom=my.domain
le_dir=/etc/letsencrypt/live/$dom
lighttpd_dir=/etc/lighttpd/ssl

systemctl stop lighttpd.service

# details in $le_dir/cli.ini
/root/git/letsencrypt/letsencrypt-auto certonly

cat $le_dir/privkey.pem $le_dir/cert.pem > $lighttpd_dir/$dom.pem
cat $le_dir/fullchain.pem > $lighttpd_dir/$dom.ca.crt

systemctl start lighttpd.service

In my lighttd.conf:

$SERVER["socket"] == ":443" {
   ssl.engine                  = "enable"
   ssl.pemfile                 = "/etc/lighttpd/ssl/my.domain.pem"
   ssl.ca-file                 = "/etc/lighttpd/ssl/my.domain.ca.crt"
   ssl.use-compression         = "disable"
   ssl.honor-cipher-order      = "enable"
   ssl.cipher-list             = "EECDH+AESGCM:EDH+AESGCM:AES128+EECDH:AES128+EDHAES256+EDH:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA:ECDHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES128-SHA256:DHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES256-GCM-SHA384:AES128-GCM-SHA256:AES256-SHA256:AES128-SHA256:AES256-SHA:AES128-SHA:DES-CBC3-SHA:HIGH:!aNULL:!eNULL:!EXPORT:!DES:!MD5:!PSK:!RC4" 
   ssl.use-sslv2               = "disable"
   ssl.use-sslv3               = "disable"
   ssl.dh-file                 = "/etc/lighttpd/ssl/dhparam.pem" # generated by `openssl dhparam -out dhparam.pem 4096`
   ssl.ec-curve                = "secp384r1"
}

/etc/letsencrypt/cli.ini:

rsa-key-size = 4096
server = https://acme-v01.api.letsencrypt.org/directory
email = nospam@my.domain
text = True
authenticator = standalone
agree-tos = True
renew-by-default = True
domains = my.domain,www.my.domain,completely.com,different.com
1 Like

Hi all,

I tried to come up with some more checks, to verifying that the created pem file is actually valid.
Currently missing is a loop to better handle the return codes and potentially roll-back the keys.

#!/bin/bash
# renew certificates
/root/letsencrypt/letsencrypt-auto certonly --config /etc/letsencrypt/cli.ini

#create lighttpd pem file
cat /etc/letsencrypt/live/<domain>/privkey.pem /etc/letsencrypt/live/<domain>/cert.pem > /etc/letsencrypt/live/<domain>/ssl.pem

#validate, that new pem contains valid priv key
openssl rsa  -in /etc/letsencrypt/live/<domain>/ssl.pem -check   -noout
rc=$?; if [[ $rc != 0 ]]; then exit $rc; fi

#validate that new pem contains valid certificates
openssl x509 -in /etc/letsencrypt/live/<domain>/ssl.pem -subject -noout
rc=$?; if [[ $rc != 0 ]]; then exit $rc; fi

#restart service (debian)
service lighttpd reload
1 Like

Dear All,

I juste try to use your scripts, but got the following errors for my domains : Failed authorization procedure. mydomain.no-ip.org (tls-sni-01): urn:acme:error:unauthorized :: The client lacks sufficient authorization :: Correct zName not found for TLS SNI challenge. Found myotherdomain.no-ip.org

I have to precise that myotherdomain.no-ip.org is a CNAME alias to mydomain.no-ip.org.

Maybe somebody could help me ?

Many thanks in advance,
Best regards,
Jean