Setting up an SSL server with Apache2

With the introduction of the Apache2 packages in Debian it is much simpler to create and use a secure SSL protected webserver than in the old days with Apache 1.3, here we'll show how it is done.

If you have Apache 2.x installed already then you're good to go as you don't need anything extra installed.

If you haven't got it installed then you can do so easily:

earth:~# apt-get install apache2
Reading Package Lists... Done
Building Dependency Tree... Done
The following extra packages will be installed:
apache2-common apache2-mpm-worker apache2-utils openssl ssl-cert
Suggested packages:
apache2-doc ca-certificates
The following NEW packages will be installed:
apache2 apache2-common apache2-mpm-worker apache2-utils openssl ssl-cert
0 upgraded, 6 newly installed, 0 to remove and 0 not upgraded.
Need to get 2040kB of archives.
After unpacking 6218kB of additional disk space will be used.
Do you want to continue? [Y/n]

Once the server is installed you need to do three things to get a working SSL setup:

Generate, or import, a certificate.

Enable Apaches SSL support.

Configure your SSL options.

Generating A Certificate

Generating a certificate from scratch will give you something which will be used to protect the traffic exchanged between clients and your server, however it will be signed by a untrusted certificate authority so it will generate warnings.

Importing a paid and "trusted" certificate will avoid this problem, but that is beyond the scope of this simple introduction.

Generating an SSL certificate for Apache2 may be accomplished using the apache2-ssl-certificate script. This will ask you questions interactively then generate the certificate file appropriately.

Here's a sample session:

earth:~# apache2-ssl-certificate
creating selfsigned certificate
replace it with one signed by a certification authority (CA)
enter your ServerName at the Common Name prompt
If you want your certificate to expire after x days call this programm
with -days x
Generating a 1024 bit RSA private key
............++++++
..........................++++++
writing new private key to '/etc/apache2/ssl/apache.pem'
-----
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [GB]:
State or Province Name (full name) [Some-State]:Scotland
Locality Name (eg, city) []:Edinburgh
Organization Name (eg, company; recommended) []:Steve Kemp
Organizational Unit Name (eg, section) []:
server name (eg. ssl.domain.tld; required!!!) []:earth
Email Address []: earth-admin@steve.org.uk

Enabling SSL Support

To use the SSL facilities of Apache2 you must enable the module mod_ssl, this can be achieved using the helper tool a2enmod (We've previously discussed the Apache2 helper scripts.)

Once this is done you'll have Apache setup to accept SSL connections, but the server will still only be listening for incoming HTTP requests on port 80 - and not SSL connections on port 443. To fix this you must add a line to the file /etc/apache2/ports.conf:

Listen 443

With these two steps out of the way you now have an Apache setup which will listen for and accept SSL connections. The next step is to modify your virtualhosts to use it.

Configuring your SSL Hosts

With a certificate setup, and the server updated to load and listen for incoming SSL connections you're almost finished. The final step is to ensure that your virtual hosts, or main host, will accept SSL options.

I use virtual hosts upon my machine and this just means adding a couple of options to each one I wish to use SSL:

SSLEngine on
SSLCertificateFile /etc/apache2/ssl/apache.pem

For reference here is a complete example which should be easy to modify/understand:

OK.. this is perhaps a silly question, but is there something special I need to do to disable non-SSL Apache2 service on port 80?

I applied Steve's directions to my system, except that I didn't put in a VirtualHost stanza for port 80, and I removed Listen 80 from ports.conf .. however, while the SSL on port 443 is indeed working fine, Apache still responds to non-secure port 80 requests.

D'oh! Looks like the whole thing was due to local caching -- in fact the server had stopped responding on :80 the minute I restarted. Man, I feel like a fool. All's well. Sorry for wasting your time, Steve -- and thanks for trying.

"Please note a general limitation is that, unlike long-time players like Verisign, CAcert's root certificate is not included by default in mainstream browsers, email clients, etc. This means people to whom you send encrypted email, or users who visit your SSL-enabled web server, will first have to import CAcert's root certificate, or they will have to agree to pop-up security warnings (which may look a little scary to non-techy users)."

Hello Steve, nice article...I didn't know there was such a script for quickly generating self-signed certs.

I noticed that you mentioned that you add some config lines for each vhost you wanted to enable SSL for. I remember trying before to have multiple SSL vhosts on one server, but they just couldn't work (apache complains about it, forgot the exact error...but it defaults to using the first ssl vhost I think). My workaround was to make each SSL vhost listen on different ports (1443,2443,etc) and have the vhost redirect to itself using the custom port when accessed by a client. It's not a workaround I'm particularly proud of though.

Is there actually a way to make multiple SSL vhosts "share" port 443 on one server? If not, can anyone care to share why apache would impose such a limit? Thanks!

Another good solution that I found from the CACert.org wiki is to setup either a wildcard SSL cert or a multiple CNAME cert. This solution works great if say your company has several domain names that are all hosted from one server. You just create the *.csr file using CN0=\*.example1.com CN1=\*.example1.net etc.

That is one solution for installing Apache + PHP + etc, but it is not ideal for Debian systems since it doesn't work with our packing system - and means that upgrades and security patches will need to be handled differently. Also looking at their webpages it doesn't mention SSL. Is that setup too?

Maybe when you have a single machine you can deal with that, but if you're looking after a lot it is best to stick to standard sources so you can patch them all in the same way ..

And for those that are quick reading the thread, ApacheFriends.org DOES NOT have a solution to the SSL on 1 VirtualHost problem. I missed that this was a different thread and thought I'd save anyone else from the mistake.

# This is here for backwards compatability reasons and to support # installing 3rd party modules directly via apxs2, rather than # through the /etc/apache2/mods-{available,enabled} mechanism. # #LoadModule mod_placeholder /usr/lib/apache2/modules/mod_placeholder.so

I just fixed this myself today. First off try removing the ServerName lines from your file. If you really do need it due to hosting several sites try instead configuring the file like the following.

NameVirtualHost 212.53.85.16:80

Right now you have said you are describing the * server but then in the Virtual Host you only configure the 213.x.x.x virtual host.

If that does not help then check to see if you have a second site configuration file laying around. The file you listed above seems valid. So I think you might have another in the sites-enabled directory that is causing you grief. Heck, editing with emacs might have left a backup file that would be loaded and give you this problem.

Lastly if you installed apache2 on a box that used to host apache 1.3 note that the apache2 configuation is in /etc/apache2 and not etc/apache. You might have edited the wrong conf file.

I followed this tutorial exactly, made all the config files match etc. But when I got to https://myip I keep getting it asking me for a username and pw. None of the system password's work. What am I doing wrong?

I am having the same problem. When I execute the command: openssl req -nodes -newkey rsa:2048 -keyout myserver.key -out server.csr I am getting this response: Generating a 2048 bit RSA private key ....................+++ ........................................+++ writing new private key to 'myserver.key' ----- You are about to be asked to enter information that will be incorporated into your certificate request. What you are about to enter is what is called a Distinguished Name or a DN. There are quite a few fields but you can leave some blank For some fields there will be a default value, If you enter '.', the field will be left blank. ----- Country Name (2 letter code) [GB]:problems making Certificate Request

I can not enter a two letter country code, for example th , if I do I get an error:

Country Name (2 letter code) [GB]:problems making Certificate Request > th bash: th: command not found

Thanks for the article. I have not created a default certificate using apache2-ssl-certificate but a specific certificate for every domain using openssl (/usr/lib/ssl/misc/CA.pl -newreq-nodes), so I have a certificate and a key. I am setting up two virtual hosts like this:

The cert and key files are different and have been signed by CAcert.org. The thing is that, in case I configure only the first virtualhost everything works fine. But the moment I configure the second virtualhost, then both offer the certificate of the second one when you connect.

I'm a real estate broker (non-tech variety) and run a web site containing a rental application that is not secure. I got everything loaded per this article and the application comes up okay as a secure page but when I hit submit (which is a post to a perl script that sends an emmail acknowledgement and creates a file on disc containing the application info)the browser produces a dialogue box that leads only to opening or saving the file containing the perl script.

Your question was fairly easy understand, and you came back to supply followup details. Too often people ask questions and don't give enough useful information to identify their problems, or simply never return to answer any questions.

Still I'm glad you're impressed. I think the visitors here all do a great job of helping each other.

Maybe it's not suitable with the article but still connected. 1. The difference of ssh and ssl?. 2. for example, I make a html page as index.html for my website on https. It's a simple html login page without using database (just enter username and password and then submit to other html page). What I want to know can we decrypt the message (read the original message before encrypted), so server can know the username and password. How to do that and can we do it for web that's not using database?. Thanx.

If you check in /etc/apache2/sites-enabled/ you will see a symlink named "000-default" which points to a file, /etc/apache2/sites-available/default, that contains a wild card NameVirtualHost directive for *. Because that host does not specify ports as a separate setting, like *:* it bullies all of the other NameVirtualHost directives you might want to create. This creates an unstable situation where Apache is not sure what all of the directives will do and it gives a warning that explains this.

A reasonable solution would be to remove the 000-default site from the sites-enabled folder. Or you could edit the default site to be a little more friendly. It is possible that *:* would play nicer than simply *.

echo echo creating selfsigned certificate echo "replace it with one signed by a certification authority (CA)" echo echo enter your ServerName at the Common Name prompt echo echo If you want your certificate to expire after x days call this programm echo with "-days x"

# use special .cnf, because with normal one no valid selfsigned # certificate is created

Thanks for the article. Only problem for me is that when opening an https URL in a web browser (https://WEB_server_IP_address/test.txt), I'm stuck with client denied by server configuration errors. Any ideas?

DEBIANHOST:~$ cat /etc/apache2/conf.d/local_configs.conf #Tighten access to the file system <Directory /> #forbid default access to file system locations Order Deny,Allow Deny from all #prevent use of .htaccess files in all directories #apart from those specifically enabled AllowOverride None </Directory> #limit available info about this server ServerSignature Off ServerTokens production #hide all files with the .inc (php include) extension <Files "*.inc"> Order allow,deny Deny from all </Files>

So adding a directive to the SSL VirtualHost solved it. <Directory /var/www/webdav> AllowOverride None Order allow,deny allow from all </Directory>

Hi Steve, I (somewhat) successfully got ssl working, with the following exception: when i access https://192.168.10.2 everything works fine. however, when i access it via fqdn https://www.ccpip.net i get a 501 not implemented - the requested method is not implemented by the server.

note that i do get a security warning that the cert does not match the server name, so it appears that some communication is taking place.

For generating certificate you might have used the "apache2-ssl-certificate" command in debian sarge but in debian etch this command not available.If you want to generate certificates you need to use openssl from you command prompt Use the following command to generate certificates

Hi, Nice work. So I would ask you for my problem: all seems work, but only seems ! I notice I did the configuration without reading this article, but I do all that is noticed. (and of course apache2 works fine before trying to add ssl feature) First a basic netstat: no more port 80 neither 443 And the /var/log/apache2/error.log says: [error] Init: Multiple RSA server certificates not allowed I defined in the <VirtualHost *:443> the directives SSL.... And I don't see any problem in the ssl.conf Thanks to your help and any explanation.

in your previous article on apache2 ( before it was packaged), there was a line saying:

SetEnvIf User-Agent ".*MSIE.*" nokeepalive ssl-unclean-shutdown

in ssl.conf.

However, this doesn't seem to appear in my etch installation of apache2.

After I added this by hand to ssl.conf my problems with Apache2 on MSIE6 disappeared. Since this is mentioned on a lot of places, I find it strange that it hasn't been included in the official package? (i installed Debian Etch Stable on the machine). Is there a reason for this, and am I missing a point somewhere?

This is different from the self signing .pem file that you generate in your example, and it simply will not work the way you describe.

However, if you manually join the .key file and the .crt file together with a text editor (vi, pico etc) you create a single file and name this domain_name.pem then you reference this file in the apache config and all will work;

This method (a .pem) file created by merging the private .key and public .crt files worked a treat. Apache asked me for my key passphrase during startup (as expected) and secured the site. What boggles me is why the other method seems to be the preferred one yet it clearly does not work!

Package apache2-common is not available, but is referred to by another package. This may mean that the package is missing, has been obsoleted, or is only available from another source However the following packages replace it: apache2.2-common apache2-utils

apache2-ssl-certificate is no where to be found. I would think it is in apache2-utils but it is not.

One of the easist things I have had to setup, thanks very much. As a newbie the only thing I had to guess was where to put the configuration lines. I simply added them to the end of my /etc/apache2/apache2.conf not sure if thats right but everything seems to be working.

Two years ago I used this article and some follow-up questions to set up ssl with a self-signed certificate. Now the certificate is about to expire and I have been unable to renew it. I have tried numerous variations of the command apache2-ssl-certificate --force and -days x but have not made them work. Could someone reply with the command that would extend the certificate 1000 days. (I am still using apache sarge. Thanks in advance.

Steve: Everything seems to be working ok but when apache2 restarts it asks for the pass phrase. Did not do this before. It's okay as long as I am sitting at the screen but it a problem otherwise. Did I miss something? Or can I automate the response?

Steve: Everything seems to be working ok but when apache2 restarts it asks for the pass phrase. Did not do this before. It's okay as long as I am sitting at the screen but it a problem otherwise. Did I miss something? Or can I automate the response?

You say: <<<<< I use virtual hosts upon my machine and this just means adding a couple of options to each one I wish to use SSL: SSLEngine on SSLCertificateFile /etc/apache2/ssl/apache.pem

For reference here is a complete example which should be easy to modify/understand: >>>>>

But it is not clear which specific filename(s) you are referring to.

I can't tell, but perhaps the article needs a slight update / modification?

I just installed today, and within the resulting files are the various 'snakeoil' files. Which is to say, it seems possible that having enabled mod_ssl, apache2/https is ready to go out of the box.

Not to say what you have isn't entirely appropriate, but perhaps a paragraph in the middle along the lines of:

With this change, you can test that all is well with apache by going to https://localhost. You will notice some extra dialogues as a result, which can be addressed by using your own (self-signed) certificate. And here's how you do that ... (proceeding with what you already have).

The command apache2-ssl-certificate is not being found in Ubuntu/Debian. Where is the script located? Perhaps you want to consider adding the script location and any other pertinent information regarding the command.

Also when you are referring to add "Listen 443" on ports.conf file you might want to specify in what section of the file to add the directive. For instance does it go at the top with the other ports or goes between the the first <IfModule mod_ssl.c> brackets.

You a assuming everyone has been using Apache for a while but a beginner might not understand your content as it will have to search for the mention information.