Project

General

Profile

Actions

Setting up a simple SSL configuration with a self-signed certificate

Setting up a simple SSL configuration with lighttpd is quite easy. Though this method should be used with care because this setup will only provide proper encryption, not authentication! The user will be presented with a query whether to accept the certificate or not!

First, go into your SSL Certificates directory and do:

cd /etc/lighttpd/certs
openssl req -new -x509 -keyout lighttpd.pem -out lighttpd.pem -days 365 -nodes
chmod 400 lighttpd.pem

If lighttpd starts are root -- the default in many service configs -- then the certificate can be owned by root with permissions 0400, as lighttpd reads the certificates before dropping privileges to www-data (or other account, depending on the distro config).

Then edit /etc/lighttpd/lighttpd.conf and add:

$SERVER["socket"] == ":443" {
  ssl.engine = "enable" 
  ssl.pemfile = "/etc/lighttpd/certs/lighttpd.pem" 
}

After restarting the webserver, you should be able to access your webserver through https.

To create an elliptic curve (EC) certificate for curve SECP384R1:
openssl req -x509 -newkey ec -pkeyopt ec_paramgen_curve:secp384r1 -keyout lighttpd.pem -out lighttpd.pem -days 365 -nodes

Let's Encrypt's New Root and Intermediate Certificates

Dec 2020 / Jan 2021: If you start having trouble with Let's Encrypt certificates, please read the following links.
https://letsencrypt.org/2020/09/17/new-root-and-intermediates.html
https://letsencrypt.org/2020/11/06/own-two-feet.html
https://letsencrypt.org/2020/12/21/extending-android-compatibility.html

Use Let's Encrypt fullchain.pem and privkey.pem in lighttpd.conf

ssl.pemfile = "/path/to/fullchain.pem" 
ssl.privkey = "/path/to/privkey.pem" 

Let's Encrypt bootstrap using TLS-ALPN-01 verification challenge and dehydrated (with lighttpd 1.4.53)

Create initial self-signed cert in order to be able to configure lighttpd with SSL, including subjectAltName expected by dehydrated.
Prerequisite: DNS must be configured so that $hostname points to the an address which will serve content from the machine on which you run lighttpd.
Replace hostname=www.example.com with an appropriate hostname below.

#!/bin/bash
certdir=/etc/lighttpd/certs
hostname=www.example.com
mkdir -p $certdir/$hostname && openssl req -new -x509 -extensions req_ext -keyout $certdir/$hostname/privkey.pem -out $certdir/$hostname/cert.pem -days 365 -nodes -config <(cat <<-EOF
[ req ]
distinguished_name = dn
prompt = no
[ dn ]
CN = $hostname
[ req_ext ]
subjectAltName = @san
[ san ]
DNS = $hostname
EOF
) && cp $certdir/$hostname/cert.pem $certdir/$hostname/chain.pem

Configure /etc/lighttpd/lighttpd.conf. Note that Let's Encrypt TLS-ALPN-01 verification challenge requires that the host receive and respond to the challenge on port 443.

server.modules += ("mod_openssl")
$SERVER["socket"] == "0.0.0.0:443" {
    ssl.engine = "enable" 
    ssl.privkey= "/etc/lighttpd/certs/www.example.com/privkey.pem" 
    ssl.pemfile= "/etc/lighttpd/certs/www.example.com/fullchain.pem" 
    ssl.acme-tls-1 = "/etc/lighttpd/dehydrated/tls-alpn-01" 
    #ssl.openssl.ssl-conf-cmd = ("MinProtocol" => "TLSv1.2") # (lighttpd 1.4.56 default; recommended to accept only TLSv1.2 and TLSv1.3)
    #ssl.ca-file= "/etc/lighttpd/certs/www.example.com/chain.pem" # (needed in $SERVER["socket"] before lighttpd 1.4.56 if ssl.pemfile in $HTTP["host"])
}

Start up lighttpd

systemctl start lighttpd

Download dehydrated and force cert renewal (-x). You should review the downloaded script before running it.
The script does not need to run as root, but does need to have permission to write to the challenge directory and to the certificate directory tree.
The user account running the lighttpd web server needs permission to be able to read the files written by dehydrated, so it is recommended that dehydrated be run under the same user account as the lighttpd web server.
(Aside: one user found that he needed to set a login shell (e.g. "/bin/bash") for the lighttpd user before things worked. See https://redmine.lighttpd.net/boards/2/topics/8482)

mkdir -p /etc/lighttpd/dehydrated/tls-alpn-01
cd /tmp && git clone https://github.com/lukas2511/dehydrated && cd dehydrated
./dehydrated --register --accept-terms
./dehydrated -d www.example.com -t tls-alpn-01 --out /etc/lighttpd/certs --alpn /etc/lighttpd/dehydrated/tls-alpn-01 -c --ca letsencrypt

Restart lighttpd to use the Let's Encrypt certificates

systemctl restart lighttpd

Troubleshooting: before lighttpd 1.4.59, initial certificate creation by dehydrated may fail with "Missing acmeValidationV1 extension". Before lighttpd 1.4.59, the initial certificate may need to be provisioned outside lighttpd. Certificate renewal then appears to work.

mod_nss: Use dehydrated -a rsa (lighttpd limitation until mod_nss adds support to parse ECC certs)
mod_mbedtls: mbedtls before 2.23.0 not supported. Earlier mod_mbedtls versions do not recognize id-pe-acmeIdentifier OID and do not provide a callback that can be used to handle it.
mod_wolfssl: wolfssl requires that the Let's Encrypt certificate chain be provided in ssl.ca-file for initial certificate creation, or else OCSP validation of client certificate provided by Let's Encrypt fails when Let's Encrypt connects to lighttpd during the TLS-ALPN-01 challenge process.

Let's Encrypt bootstrap using HTTP-01 verification challenge and certbot

certbot does not yet support --preferred-challenges tls-alpn-01 so the less secure http-01 verification challenge must be used with certbot.

Configure /etc/lighttpd/lighttpd.conf. Note that Let's Encrypt HTTP-01 verification challenge requires that the host receive and respond to the challenge on port 80.

server.bind = "0.0.0.0" 
server.port = 80
server.modules += ("mod_alias")
alias.url = ("/.well-known/" => "/etc/lighttpd/certbot/.well-known/")

Start up lighttpd
systemctl start lighttpd

Install and run certbot
mkdir -p /etc/lighttpd/certbot
dnf install certbot
certbot register --agree-tos -m "responsible-admin@example.com" 
certbot certonly --preferred-challenges http-01 --webroot -w /etc/lighttpd/certbot -d www.example.com
#certbot certonly --preferred-challenges tls-alpn-01 --webroot -w /etc/lighttpd/certbot -d www.example.com

Reconfigure lighttpd.conf to use certificates retrieved by certbot
server.modules += ("mod_openssl")
$SERVER["socket"] == "0.0.0.0:443" {
    ssl.engine = "enable" 
    ssl.privkey= "/etc/letsencrypt/live/www.example.com/privkey.pem" 
    ssl.pemfile= "/etc/letsencrypt/live/www.example.com/fullchain.pem" 
    ssl.openssl.ssl-conf-cmd = ("MinProtocol" => "TLSv1.2") # (recommended to accept only TLSv1.2 and TLSv1.3)
    #ssl.ca-file= "/etc/lighttpd/certs/www.example.com/chain.pem" # (needed in $SERVER["socket"] before lighttpd 1.4.56 if ssl.pemfile in $HTTP["host"])
}

Restart lighttpd to use the Let's Encrypt certificates
systemctl restart lighttpd

See Also

========

Updated by gstrauss 11 months ago · 40 revisions