Quick Links

Signing your own SSL certificates is usually done as an easy alternative to certificate authorities for internal communications or non-user facing sites that need still encryption. Here's how to set one up with Apache.

Generate and Self Sign an SSL Certificate

We'll use the openssl utility to generate the certificate and corresponding private key. You likely have this installed already, as it's a dependency of Apache, but if it's somehow missing you can install it from your distro's package manager. For Debian-based systems like Ubuntu, that would be:

sudo apt-get install openssl

After openssl is installed, you can generate the certificate with the following command:

sudo openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout /etc/ssl/private/apache.key -out /etc/ssl/certs/apache.crt

openssl will ask you for some info about your organization. You can leave most of this blank, but the one important thing you'll need to fill out is the "Common Name," which you'll want to set to your server's IP address or domain name.

Country Name (2 letter code) []:
    

State or Province Name (full name) []:

Locality Name (eg, city) []:

Organization Name (eg, company) []:

Organizational Unit Name (eg, section) []:

Common Name (eg, fully qualified host name) []: your_ip_address

Email Address []:

openssl will take a second to run and generate a new private RSA key, which is used to sign the certificate and store it in /etc/ssl/private/apache.key. The certificate itself is stored in /etc/ssl/certs/apache.crt, and will be valid for a year.

We'll also want to generate a Diffie-Hellman group. This is used for perfect forward secrecy, which generates ephemeral session keys to ensure that past communications cannot be decrypted if the session key is compromised. This isn't entirely necessary for internal communications, but if you want to be as secure as possible you shouldn't skip this step. Note, this does require you to have Apache version 2.4.8 or higher, so make sure you're up to date.

sudo openssl dhparam -out /etc/ssl/certs/dhparam.pem 4096

This does take a while---about an hour depending on how fast your server is. Grab some lunch, and come back to your terminal in a bit to configure Apache.

Configure Apache to Use Your Self-Signed Certificate

To make things easy, we'll do all our configuration in a snippet file. Create a new one in Apache's sites-available directory (here's how to find Apache's configuration folder).

sudo touch /etc/apache2/conf-available/ssl-params.conf

Open it up in your favorite text editor, and paste in the following configuration:

SSLCipherSuite EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH
    

SSLProtocol All -SSLv2 -SSLv3 -TLSv1 -TLSv1.1

SSLHonorCipherOrder On

Header always set X-Frame-Options DENY

Header always set X-Content-Type-Options nosniff

SSLCompression off

SSLUseStapling on

SSLStaplingCache "shmcb:logs/stapling-cache(150000)"

SSLSessionTickets Off

SSLOpenSSLConfCmd DHParameters "/etc/ssl/certs/dhparam.pem"

The first block sets a few default SSL parameters, and the last line configures Apache to use the Diffie-Hellman group. You can omit this line if you skipped that step.

Next, open up the default SSL Virtual Host file, usually located at /etc/apache2/sites-available/default-ssl.conf. Change the following lines to point to your certificate and key file:

SSLCertificateFile /etc/ssl/certs/apache.crt
    

SSLCertificateKeyFile /etc/ssl/private/apache.key

SSL should now be working, but you will likely will need to copy over some configuration from your current configuration file, because you just modified a blank one. You'll have to make sure the ServerName , ServerAdmin , and DocumentRoot  directives are pointing to the correct locations.

Additionally, you'll want to set up a redirect to forward HTTP traffic over to the encrypted HTTPS. Open up the default Apache config at /etc/apache2/apache2.conf , and add the following lines to rewrite HTTP traffic:

RewriteEngine On 
    

RewriteCond %{SERVER_PORT} 80

RewriteRule ^(.*)$ https://www.yourdomain.com/$1 [R,L]

You'll also want to make sure your firewall is open. HTTPS uses port 443, rather than port 80, so you'll need to open that to connect to the server. If you're using iptables or UFW, you can open ports from the command line. If you're hosting your server on a service like AWS, your provider may give you a web interface to open ports from.

AWS firewall interface

Self-signed certificates are most commonly used for private servers, so it's not a bad idea to whitelist access to only your private LAN and use a VPN server to connect to it.

Once the ports are open you can test your SSL settings by navigating to your site in your browser. If everything worked correctly, you should see this warning:

chrome SSL warning

This is normal, so don't worry. You'll have to manually select that you trust this certificate, which is the reason you can't use self-signed certs for public facing sites.

The warning doesn't mean your site is insecure---SSL is still turned on and encrypting traffic. If your private key is compromised, then the communication could be decrypted, but it will be perfectly secure if you set up Diffie-Hellman forward secrecy, which negates that attack vector. The problem here is with identity. Chrome can't verify that you are who you say you are or that you own the domain, which you'll need a "real" CA for.