# Lighttpd usable chained file

**URL:** <https://community.letsencrypt.org/t/lighttpd-usable-chained-file/3357>\
**Category:** Feature Requests\
**Created:** [November 8, 2015, 8:06pm UTC](https://community.letsencrypt.org/t/lighttpd-usable-chained-file/3357 "2015-11-08T20:06:09Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![th3l0nius](https://avatars.discourse-cdn.com/v4/letter/t/c67d28/32.png) [@th3l0nius](https://community.letsencrypt.org/u/th3l0nius)\
**Post date:** [November 8, 2015, 8:06pm UTC](https://community.letsencrypt.org/t/lighttpd-usable-chained-file/3357/1 "2015-11-08T20:06:09Z")

</div>

As to read in the [lighttpd docs](http://redmine.lighttpd.net/projects/1/wiki/docs_ssl "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/…

---

<div class="post-metadata">

**Author:** ![shellster](https://avatars.discourse-cdn.com/v4/letter/s/f475e1/32.png) [@shellster](https://community.letsencrypt.org/u/shellster)\
**Post date:** [December 4, 2015, 7:08pm UTC](https://community.letsencrypt.org/t/lighttpd-usable-chained-file/3357/2 "2015-12-04T19:08:32Z")

</div>

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"
}
```

---

<div class="post-metadata">

**Author:** ![th3l0nius](https://avatars.discourse-cdn.com/v4/letter/t/c67d28/32.png) [@th3l0nius](https://community.letsencrypt.org/u/th3l0nius)\
**Post date:** [December 5, 2015, 10:48am UTC](https://community.letsencrypt.org/t/lighttpd-usable-chained-file/3357/3 "2015-12-05T10:48:53Z")

</div>

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:

```bash
#!/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:

```auto
$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`:

```auto
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

```

---

<div class="post-metadata">

**Author:** ![empor](https://avatars.discourse-cdn.com/v4/letter/e/9f8e36/32.png) [@empor](https://community.letsencrypt.org/u/empor)\
**Post date:** [December 9, 2015, 12:42pm UTC](https://community.letsencrypt.org/t/lighttpd-usable-chained-file/3357/4 "2015-12-09T12:42:00Z")

</div>

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
```

---

<div class="post-metadata">

**Author:** ![jean\_bruder](https://sea3.discourse-cdn.com/letsencrypt/user_avatar/community.letsencrypt.org/jean_bruder/32/3816_2.png) [@jean\_bruder](https://community.letsencrypt.org/u/jean_bruder)\
**Post date:** [December 31, 2015, 9:44am UTC](https://community.letsencrypt.org/t/lighttpd-usable-chained-file/3357/5 "2015-12-31T09:44:33Z")

</div>

Dear All,

I juste try to use your scripts, but got the following errors for my domains : Failed authorization procedure. [mydomain.no-ip.org](http://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](http://myotherdomain.no-ip.org)

I have to precise that [myotherdomain.no-ip.org](http://myotherdomain.no-ip.org) is a CNAME alias to [mydomain.no-ip.org](http://mydomain.no-ip.org).

Maybe somebody could help me ?

Many thanks in advance,  
Best regards,  
Jean
