Remember if you used the RPM packages to install lighty, the init.d scripts will point to the wrong binary of lighty than the one you just compiled. The location of where you compiled lighty should be displayed near the end of make install. Once the location of the binary is found please edit the /etc/init.d/lighttpd script and change what is defined in the lighttpd="/usr/sbin/lighttpd" to your new lighty location.

To enable SSL, you have to provide a valid certificate and have to enable the SSL engine in each socket scope, i.e. ssl.engine = "enable" in each $SERVER["socket"] that should be SSL-enabled, and in the global scope if server.bind and server.port should be SSL-enabled.

To make lighttpd SSL-only, simply put the following in your main config. By default, lighttpd listens to "0.0.0.0:80" unless server.bind and server.port are set to something else. To listen on port "0.0.0.0:443" and not on port 80:

This simply enables SSL on port 443. It seems that lighttpd also automatically starts listening on port 443 this way. Like this, all of the other configuration applies to both HTTP and HTTPS. This means that the same pages will be available on both HTTP and HTTPS. If you want to serve different sites, you can change the document root inside the socket conditional:

When you are using lighttpd 1.4.19 or later, you can also use the scheme conditional to distinguish between secure and normal requests. Note that you can't use the scheme conditional around ssl.engine above, since lighttpd needs to know on what port to enable SSL.

As a special case in lighttpd 1.4.46 and later, if ssl.engine = "enable" in the global scope and along with ssl.pemfile, then $SERVER["socket"] blocks can inherit the exact global config by setting ssl.engine = "enable" and no other ssl.* directives in the $SERVER["socket"] block. The following will set lighttpd to be HTTPS-only listening on both port 80 and 443, on the default INADDR_ANY (0.0.0.0) and in6addr_any ([::]) wildcard addresses.

If you have a .crt and a .key file, cat them together into a single PEM file (the order isn't strictly important):

$ cat host.key host.crt > host.pem

ssl.cipher-list is a list of ciphers that you want (or don't want) to use when talking SSL. For a list of ciphers and how to include/exclude them, see sections "CIPHER LIST FORMAT" and "CIPHER STRINGS" on the man-page for ciphers. For the latest list of recommended strong ciphers, see https://cipherli.st/ and periodically revisit the page.

Some certificate authorities use chained certificates. This means that your webserver certificate is not signed by the CA root certificate directly, but by an intermediate certificate (which is in turn signed by the root CA). Since browser typically only ship the root certificates and not all intermediate certificates, there is no way for a browser to verify your chained certificate if you don't supply the browser with the intermediate certificate.

Using the ssl.ca-file configuration variable, you can tell lighttpd about these intermediate certificates. You can put multiple certificates in a single file, if needed. For example:

If you set a password on your SSL certificate, then each time lighttpd starts you will be requested to enter it manually. ie: "Enter PEM pass phrase:". To prevent this, remove the password from your private key file. At present there is no configuration option to enable storage of SSL certificate passwords in the lighttpd config file (but it wouldn't make much sense, since having the password stored on disk is not more secure than having no password at all).

Diffie-Hellman and Elliptic-Curve Diffie-Hellman key agreement protocols will be supported in lighttpd 1.4.29. By default, Diffie-Hellman and Elliptic-Curve Diffie-Hellman key agreement protocols use, respectively, the 1024-bit MODP Group with 160-bit prime order subgroup from RFC 5114 and "prime256v1" (also known as "secp256r1") elliptic curve from RFC 4492. The Elliptic-Curve Diffie-Hellman key agreement protocol is supported in OpenSSL from 0.9.8f version onwards. For maximum interoperability, OpenSSL only supports the "named curves" from RFC 4492.

Using the ssl.dh-file and ssl.ec-curve configuration variables, you can define your own set of Diffie-Hellman domain parameters. For example:

A traditional problem with SSL in combination with name based virtual hosting has been that the SSL connection setup happens before the HTTP request. So at the moment lighttpd needs to send its certificate to the client, it does not know yet which domain the client will be requesting. This means it can only supply the default certificate (and use the corresponding key for encryption) and effectively, SSL can only be enabled for that default domain. There are a number of solutions to this problem, with varying levels of support.

This is the classic solution, which requires a separate IP address for each domain. Since Lighttpd knows the ip address that the client connected to before the SSL negotiation, it can simply select the right certificate to use based on the IP address. The most obvious downside to this approach is that it requires multiple addresses, which are not always available and can be expensive. This approach is currently the most reliable, since it works with all clients.

It is possible to put multiple names in a single certificate. These certificates are usually referred to as UCC (Unified Communications Certificates) certificates, or SAN (Subject Alternative Name) certificates. These certificates use the SAN property to store multiple domain names in a single certificate. This allows lighttpd to always use the same certificate, which is valid for all the domains it serves.

The main disadvantage of this approach is that you will have a single certificate with a lot of domain names in it and the certificate needs to change whenever you add a new domain name. When serving sites for different parties, this can be a problem.

According to digicert, SAN certificates are supported by nearly all browsers (except for some mobile browsers) and should be pretty safe to use.

Using a SAN certificate requires no special configuration for Lighttpd.

Certificates support the use of wildcards, which can be useful to support multiple subdomains. For example, one can get a certificate for the *.example.org domain to support all of the subdomains of the example.org domain.

This approach of course does not scale well to multiple different domains. Again according to digicert, wildcard certificates should be supported by virtually all clients.

An extension to the SSL / TLS protocol that has gained support recently is Server Name Indication. This addition is simple and elegant: During the SSL negotiation, the client sends the name of the host it wants to contact to the server, which can then use this information to select the correct certificate.

This is of course the best and most fitting solution to the problem. Lighttpd supports SNI since 1.4.24, if openssl 0.9.8f or newer is available.

The big downside of this approach is the limited browser support. The newest versions of the major browsers support SNI, but in particular Internet Explorer on Windows XP seems to lack support and support with mobile browsers is unclear.

To use SNI with lighttpd, simply put additional ssl.pemfile configuration directives inside host conditionals under the socket conditional. A default ssl.pemfile is still required in the socket conditional, though.

To enable TLS/SSL in multiple $SERVER["socket"] contexts, but sharing ssl.* config, either duplicate the ssl.* config within each $SERVER["socket"], or put the ssl.* directives in the global context and have $SERVER["socket"] config block contain ssl.engine = "enable" without any other ssl.* directives in that $SERVER["socket"] config block.

The simple config suggested above, is perhaps too "vague" when serving multiple hosts, one per IP (the traditional and still most common way, until Windows XP dies and nearly all browsers support SNI). Consider this config:

connecting to IP 10.0.0.2 because it has somehow resolved domain1.com to 10.0.0.2 (see above). Then lighty WILL serve the content of domain2 despite recevieving "Host:domain1.com" in the request header! You are kind of protected because your client should give an SSL domain mismatch warning here. However, as was the case in our config, domain1 and domain2 were actually subdomains and covered by the same wildcard cert => no ssl warning!

So we were getting CONTENT FROM "WRONG" DOMAIN/DOCROOT just because of stale DNS.

This ensures that 10.0.0.2:443 will ONLY EVER serve content with a "Host: domain2.com" request header. If domain1.com is requested from 10.0.0.2:443 lighty will now respond with 404, which is better we think.

NOTE: the HTTP["host"] conditional should come after ssl engine config (ssl.enable, pemfile, cyphers...) as these are required to establish the connection, and must come before "host" is available (unless you are relying on SNI). Once the connection is up, we can make all subsequent config (docroot, log, rewrite etc) conditional upon "Host" as shown. Tested with lighttpd 1.4.32.

I should clarify the reason for this work. From September 19th, all major online vendors taking card payments will be required to comply with the Payment Card Industry (PCI) Data Security Standard. Smaller vendors may self-certify but they will be more liable if fraud is committed.

Part of this standard is the disabling of SSLv2 and the removal of support for ciphers that have a key length of less than 128 bits. For this reason, I believe that the default SSL configuration for lighttpd should reflect this standard.

to disable SSLv2 and set a cipher-list. Make sure this settings are in the same block than ssl.engine = "enable", this will not work as global options.

cipher-list accepts a string containing the ciphers you would like to accept separated by whitespace. A list of strings will not work.

Matthew also provide a list of possible ciphers:

Hope it can be of use. Next time I'll submit a proper svn patch but I was in a hurry! Which might explain my somewhat short list of supported ciphers. I've since done some research and this list of supported ciphers is much more comprehensive. It supports all ciphers >= 128 bit key lengths for SSL v3.0, TLS v1.0, and AES cipher suites from RFC3268, extending TLS v1.0 (these seem to be the ones used by recent browsers, not included in the original list): ::

[FYI] bb says: the requirements permit use of SSLv2 as long as it isn't the only version available. for example, having SSLv2, SSLv3, and TLSv1 enabled is PCI compliant. SSLv2 should still be disabled, however, both because it is weak and because you can expect the PCI requirements to become more stringent in the future. here is my recommended cipher list, in order, which also happens to be PCI compliant: ::