Tutorial

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

Published on April 15, 2014
How To Set Up Multiple SSL Certificates on One IP with Lighttpd

Introduction

Server Name Indication (SNI) is a feature of the TLS protocol which enables setting up multiple SSL certficates on a single IP address.

Lighttpd must already be setup and running. Read these articles to get it up.

Setup

Two domains will be used for this tutorial. Both will use self-signed SSL certificates.

Domain 1: example.com Common Name: *.example.com

Domain 2: digitalocean.com Common Name: www.digitalocean.com

SSL setup needs a default certificate just like a default virtual host. We will use the first domain’s certificate for this.

Create private keys

Create a directory inside the /etc/lighttpd to place the keys and certificates.

mkdir /etc/lighttpd/certs

Create a private key and enter a passphrase. The second command is for removing the passphrase.

cd /etc/lighttpd/certs
openssl genrsa -des3 -out example.com.key 2048
openssl rsa -in example.com.key -out example.com.key

Do the same for the second domain too.

openssl genrsa -des3 -out digitalocean.com.key 2048
openssl rsa -in digitalocean.com.key -out digitalocean.com.key

If the passphrase isn’t removed, Lighttpd will prompt for it each time it starts or restarts.

Create a Certificate Signing Request

Create a CSR for both the domain names.

cd /etc/lighttpd/certs
openssl req -new -key digitalocean.com.key -out digitalocean.com.csr
openssl req -new -key example.com.key -out example.com.csr

Fill in the details and enter a dot . if you wish to leave a field blank.

-----
Country Name (2 letter code) [AU]:US
State or Province Name (full name) [Some-State]:.
Locality Name (eg, city) []:NYC
Organization Name (eg, company) [Internet Widgits Pty Ltd]:DigitalOcean Inc
Organizational Unit Name (eg, section) []:.
Common Name (e.g. server FQDN or YOUR name) []:www.digitalocean.com
Email Address []:webmaster@digitalocean.com

Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:

When filling the Common Name field for example.com make sure to enter *.example.com.

-----
Country Name (2 letter code) [AU]:IN
State or Province Name (full name) [Some-State]:.
Locality Name (eg, city) []:Chennai
Organization Name (eg, company) [Internet Widgits Pty Ltd]:.
Organizational Unit Name (eg, section) []:.
Common Name (e.g. server FQDN or YOUR name) []:*.example.com
Email Address []:admin@example.com

Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:

We have entered a different country and city for this CSR so that it is easy to distinguish which certificate is presented.

Sign your SSL Certificates

Here again, we will set a different validity length (-days argument) for both the certificates so that we can easily differentiate between them.

cd /etc/lighttpd/certs
openssl x509 -req -days 100 -in example.com.csr -signkey example.com.key -out example.com.crt
openssl x509 -req -days 200 -in digitalocean.com.csr -signkey digitalocean.com.key -out digitalocean.com.crt

Create a .pem file from the certificates and their private keys.

cat example.com.{key,crt}> example.com.pem
cat digitalocean.com.{key,crt}> digitalocean.com.pem

Secure the files in this directory by only allowing the root user to read these files.

chmod -R 400 /etc/lighttpd/certs/

The Lighttpd daemon starts with root privileges before coming down to www-data so this should not be a problem.

Configure Lighttpd for SSL

Edit the /etc/lighttpd/lighttpd.conf file and add the following lines at the end.

$SERVER["socket"] == "0.0.0.0:443" {
    ssl.engine = "enable"
    ssl.pemfile = "/etc/lighttpd/certs/example.com.pem"
    $HTTP["host"] =~ "(^|www\.)digitalocean.com" {
        ssl.pemfile = "/etc/lighttpd/certs/digitalocean.com.pem"
    }
}

Since the ceritifcate of example.com is the default one, we do not place it inside a host condition.

Restart the Lighttpd daemon.

service lighttpd force-reload

The service should successfully restart if you have not made errors in the certificate paths or when creating the .pem file.

Testing HTTPS

The easy way of testing this without editing the hosts file is to use curl.

This command has a --resolve argument which maps domains with IP addresses. Replace 1.1.1.1 with the IP address of your Droplet.

curl -k -o /dev/null --resolve "www.digitalocean.com:443:1.1.1.1" -s -v https://www.digitalocean.com

This will give a verbose output. The -o redirects all HTML output as we do not need it. This is the snippet we are interested in.

* SSL connection using AES256-SHA
* Server certificate:
*        subject: C=US; L=NYC; O=DigitalOcean Inc; CN=www.digitalocean.com; emailAddress=webmaster@digitalocean.com
*        start date: 2014-03-26 18:39:25 GMT
*        expire date: 2014-10-12 18:39:25 GMT
*        common name: www.digitalocean.com (matched)
*        issuer: C=US; L=NYC; O=DigitalOcean Inc; CN=www.digitalocean.com;    emailAddress=webmaster@digitalocean.com
*        SSL certificate verify result: self signed certificate (18), continuing anyway.

Examine the next domain.

curl -k -o /dev/null --resolve "www.example.com:443:1.1.1.1" -s -v https://www.example.com

Cert details from output:

* SSL connection using AES256-SHA
* Server certificate:
*        subject: C=IN; L=Chennai; CN=*.example.com; emailAddress=admin@example.com
*        start date: 2014-03-26 18:39:20 GMT
*        expire date: 2014-07-04 18:39:20 GMT
*        common name: *.example.com (matched)
*        issuer: C=IN; L=Chennai; CN=*.example.com; emailAddress=admin@example.com
*        SSL certificate verify result: self signed certificate (18), continuing anyway.

Notice the differences between both the certificates in the subject: and expire date: fields.

Try accessing the IP address directly.

user@droplet~$ curl -k -o /dev/null -s -v https://1.1.1.1

* SSL connection using AES256-SHA
* Server certificate:
*        subject: C=IN; L=Chennai; CN=*.example.com; emailAddress=admin@example.com
*        start date: 2014-03-26 18:39:20 GMT
*        expire date: 2014-07-04 18:39:20 GMT
*        common name: *.example.com (does not match '128.199.206.19')
*        issuer: C=IN; L=Chennai; CN=*.example.com; emailAddress=admin@example.com
*        SSL certificate verify result: self signed certificate (18), continuing anyway.

This should return the certificate of example.com.

<div class=“author”>Submitted by: <a rel=“author” href=“http://jesin.tk/”>Jesin A</a></div>

Thanks for learning with the DigitalOcean Community. Check out our offerings for compute, storage, networking, and managed databases.

Learn more about us


About the authors
Default avatar
Jesin A

author

Still looking for an answer?

Ask a questionSearch for more help

Was this helpful?
 
7 Comments


This textbox defaults to using Markdown to format your answer.

You can type !ref in this text area to quickly search our full set of tutorials, documentation & marketplace offerings and insert the link!

I am stuck when I get to this part:

cd /etc/lighttpd/certs

openssl x509 -req -days 100 -in example.com.csr -signkey example.com.key -out example.com.crt

example.com.crt: No such file or directory.

I don’t understand. It’s supposed to be creating a file isn’t it?

Any help much appreciated!!

James

Thank you Kamal, Now i have not choice, i must redirect some vhost from https to http to avoid problems. Cheers.

Kamal Nasser
DigitalOcean Employee
DigitalOcean Employee badge
June 5, 2014

@xlynx: No, you haven’t done anything wrong. It’s just how most webservers handle https connections which I believe is done to make sure clients that do not support SNI can load your website.

Hi, You said : SSL setup needs a default certificate just like a default virtual host. We will use the first domain’s certificate for this. I added a default certificate, but what i seen is that all vhosts (which are not configured for HTTPS), can be access with the default https.

The certificates run very nice, but its weird that all other vhosts can be loaded with HTTPS.

Did something wrong? I must redirect all no SSL vhosts from https to http?. Thank you.

Hey Thank you so much Andrew, that was fast. Best!

Andrew SB
DigitalOcean Employee
DigitalOcean Employee badge
June 2, 2014

@contact: The second one looks good to me. You might also want to take a look at:

http://redmine.lighttpd.net/projects/1/wiki/Docs_SSL#Server-Name-Indication-SNI

Hello, Thank you so much for this tutorial, i followed your instructions, and i tested on a local machine. I am a little confused how to configure the lighttpd.conf for development server, i have multi vhosts, i want to use 2 vhosts with 2 ssl, but how do this? I don’t understand what do you mean by : Since the ceritifcate of example.com is the default one, we do not place it inside a host condition.

I must do this : $SERVER[“socket”] == “0.0.0.0:443” { ssl.engine = “enable” ssl.pemfile = “/etc/lighttpd/ssl/domain1.com.pem” $HTTP[“host”] =~ “(^|www.)domain2.com” { ssl.pemfile = “/etc/lighttpd/ssl/domain2.com.pem” } }

Or

$SERVER[“socket”] == “0.0.0.0:443” { ssl.engine = “enable” $HTTP[“host”] =~ “(^|www.)domain1.com” { ssl.pemfile = “/etc/lighttpd/ssl/domain1.pem” } $HTTP[“host”] =~ “(^|www.)domain2.com” { ssl.pemfile = “/etc/lighttpd/ssl/domain2.com.pem” } }

Do i need to replace “0.0.0.0” with my ip adress ?

Your help is welcome. Thank you!

Try DigitalOcean for free

Click below to sign up and get $200 of credit to try our products over 60 days!

Sign up

Join the Tech Talk
Success! Thank you! Please check your email for further details.

Please complete your information!

Get our biweekly newsletter

Sign up for Infrastructure as a Newsletter.

Hollie's Hub for Good

Working on improving health and education, reducing inequality, and spurring economic growth? We'd like to help.

Become a contributor

Get paid to write technical tutorials and select a tech-focused charity to receive a matching donation.

Welcome to the developer cloud

DigitalOcean makes it simple to launch in the cloud and scale up as you grow — whether you're running one virtual machine or ten thousand.

Learn more
DigitalOcean Cloud Control Panel