Tech Journal Back to Tech Journal

How can I set up HTTPS on Apache with a self-signed certificate?

There are two parts to this: creating the certificate for signing the SSL communication, and getting SSL to work in Apache.

Let's start with creating a certificate for signing the SSL. I went with a password-less certificate, since I didn't want to type it in every time httpd restarted.

  1. Generate the server key:
    openssl genrsa -des3 -out server.key 1024
  2. Generate CSR (certificate signing request):
    openssl req -new -key server.key -out server.csr
    [while generating the request, I was careful to enter "mysecure.craimer.org", which is the domain-name for which I'll use the cerificate, as the "Common Name (eg, your name or your server's hostname)"]
  3. Remove password from key:
    cp server.key server.key.org
    openssl rsa -in server.key.org -out server.key
    
  4. Self-sign the certificate:
    openssl x509 -req -days 365 -in server.csr -signkey server.key -out server.crt

Now that we have our certificate files, we can configure Apache.

  1. I renamed the file /etc/httpd/conf.d/ssl.conf to be ssl.conf.orig - to prevent it from being loaded automatically.
  2. I created another file to hold the virtual host information for the the secure host. I placed it in /etc/httpd/conf.d/mysecure.craimer.org.conf. You can see it below.

Important things to note:

  1. At first, I used <VirtualHost *:443> with the instruction ServerName mysecure.craimer.org. This may have caused all the requests coming in on port 443 to be re-routed to port 80. So instead of being answered by an SSL reply, they were being answer by an HTTP reply. This led to an error in every browser, with Firefox's being the most descriptive:
    SSL received a record that exceeded the maximum permissible length.
    (Error code: ssl_error_rx_record_too_long)
    
  2. Changing the VirtualHost to accepting *:443 has zero impact on how many virtual hosts I can put on HTTPS, since only 1 HTTP vhost can be served from a single IP/httpd. Anyway, changing it from mysecure.craimer.org:443 to *:443 fixed it.

Here's the contents of mysecure.craimer.org.conf:

LoadModule ssl_module modules/mod_ssl.so
Listen 443
#   Some MIME-types for downloading Certificates and CRLs
#
AddType application/x-x509-ca-cert .crt
AddType application/x-pkcs7-crl    .crl
SSLSessionCache         shmcb:/var/cache/mod_ssl/scache(512000)
SSLSessionCacheTimeout  300
SSLMutex default
SSLRandomSeed startup file:/dev/urandom  256
SSLRandomSeed connect builtin
SSLCryptoDevice builtin

## Virtual host to redirect to HTTPS
<VirtualHost *:80>
    ServerName mysecure.craimer.org:80
    Redirect permanent / https://mysecure.craimer.org:443
</VirtualHost>

##
## SSL Virtual Host Context
##

<VirtualHost *:443>
    ServerName mysecure.craimer.org
    DocumentRoot "/usr/share/roundcubemail/trunk/roundcubemail/"

         ErrorLog logs/ssl_error_log
         TransferLog logs/ssl_access_log
         LogLevel warn

         SSLEngine on

         SSLProtocol all -SSLv2

         SSLCipherSuite ALL:!ADH:!EXPORT:!SSLv2:RC4+RSA:+HIGH:+MEDIUM:+LOW

         SSLCertificateFile /etc/httpd/conf/ssl/server.crt
         SSLCertificateKeyFile /etc/httpd/conf/ssl/server.key

         <Files ~ "\.(cgi|shtml|phtml|php3?)$">
                                SSLOptions +StdEnvVars
         </Files>
         <Directory "/var/www/cgi-bin">
                                SSLOptions +StdEnvVars
         </Directory>

    # Deal with broken MSIE
         SetEnvIf User-Agent ".*MSIE.*" \
         nokeepalive ssl-unclean-shutdown \
         downgrade-1.0 force-response-1.0

    CustomLog logs/ssl_request_log \
          "%t %h %{SSL_PROTOCOL}x %{SSL_CIPHER}x \"%r\" %b"
</VirtualHost>
Last updated on 2009-08-02 05:50:15 -0700, by Shalom Craimer

Back to Tech Journal