Configure Apache With Self-Signed TLS/SSL Certificate on Ubuntu 16.04

Published on: Fri, Sep 29, 2017 at 4:47 pm EST

SSL, and its successor TLS (Secure Sockets Layer / Transport Layer Security) add a layer of encryption between the client and the server. Without this technology, data is sent to the server in plain text, allowing third-parties to read all information sent and received by your server.

This tutorial will teach you how to create an SSL/TLS certificate and activate it on Apache 2.4 on Ubuntu 16.04. I assume Apache is already set up and running. If you want to learn how to install a LAMP stack, see this Vultr doc.

Attention

SSL/TLS certificates are normally generated by a trusted CA (certificate authority). By generating it yourself, you will be the signer, meaning the browser won't be able to verify whether the identity of the certificate should be trusted, and it will warn the user. Although it is possible to bypass this alert, public-facing sites should be using a certificate signed by a trusted CA. Let's encrypt is a CA that offers certificates for free. You can learn how to install their certificate in Apache and Ubuntu 16.04 here.

For internal applications, using a self-signed certificate might be valid, especially if you don't have a domain name.


Step 1: Generating the certificate

  1. First, let's create a place to store the file.

    mkdir ~/certificates
    cd ~/certificates
    
  2. Generate CSR and private key.

    openssl req -x509 -newkey rsa:4096 -keyout apache.key -out apache.crt -days 365 -nodes
    

    It will ask for information for the certificate request. Complete with the appropriate information.

    Country Name (2 letter code) [AU]: US
    State or Province Name (full name) [Some-State]: FL
    Locality Name (eg, city) []: Miami
    Organization Name (eg, company) [My Company]: My Company
    Organizational Unit Name (eg, section) []:
    

    Common name should be your domain name or the server's IP address. Also, fill in your email.

    Common Name (e.g. server FQDN or YOUR name) []: 203.0.113.122
    Email Address []:webmaster@example.com
    
  3. Now, move the certificate to Apache configuration folder.

    mkdir /etc/apache2/ssl
    mv ~/certificates/* /etc/apache2/ssl/.
    
  4. The certificate is ready! Next, we will prepare Apache to work with the certificate.

Step 2: Firewall configuration

  1. We have to make sure TCP port 443 is open. This port is used in SSL connections instead of port 80. In this tutorial, we will be using UFW.

  2. Make sure UFW is enabled.

    sudo ufw enable
    
  3. Now allow the predefined Apache settings for the firewall.

    sudo ufw allow 'Apache Full'
    
  4. By typing "sudo ufw status", you can see a list of the current rules. Your configuration should resemble this:

    To                         Action      From
    --                         ------      ----
    Apache Full                ALLOW       Anywhere
    OpenSSH                    ALLOW       Anywhere
    Apache Full (v6)           ALLOW       Anywhere (v6)
    OpenSSH (v6)               ALLOW       Anywhere (v6)
    
  5. You should also allow OpenSSH here for future connections.

    sudo ufw allow 'OpenSSH'
    

Step 3: Apache virtual host configuration

  1. Navigate to the default Apache site config directory.

    sudo nano /etc/apache2/sites-available/default-ssl.conf
    
  2. This file tells the server where to look for the SSL certificate. With the comments removed, it should look like the following config.

    <IfModule mod_ssl.c>
      <VirtualHost _default_:443>
       ServerAdmin webmaster@localhost
    
       DocumentRoot /var/www/html
    
       ErrorLog ${APACHE_LOG_DIR}/error.log
       CustomLog ${APACHE_LOG_DIR}/access.log combined
    
       SSLEngine on
    
       SSLCertificateFile    /etc/ssl/certs/ssl-cert-snakeoil.pem
       SSLCertificateKeyFile /etc/ssl/private/ssl-cert-snakeoil.key
    
       <FilesMatch "\.(cgi|shtml|phtml|php)$">
        SSLOptions +StdEnvVars
       </FilesMatch>
       <Directory /usr/lib/cgi-bin>
        SSLOptions +StdEnvVars
       </Directory>
    
     </VirtualHost>
    </IfModule>
    
  3. Edit this line:

    ServerAdmin email@example.net
    
  4. Add this right below the ServerAdmin line:

    ServerName ADD_YOUR_IP_OR_DOMAIN_NAME_HERE
    
  5. Now, edit these lines with our certificate location:

    SSLCertificateFile    /etc/apache2/ssl/apache.crt
    SSLCertificateKeyFile /etc/apache2/ssl/apache.key
    
  6. Our final file should resemble this:

    <IfModule mod_ssl.c>
     <VirtualHost _default_:443>
      ServerAdmin email@example.net
      ServerName 203.0.113.122
    
      DocumentRoot /var/www/html
    
      ErrorLog ${APACHE_LOG_DIR}/error.log
      CustomLog ${APACHE_LOG_DIR}/access.log combined
    
      SSLEngine on
    
      SSLCertificateFile    /etc/apache2/ssl/apache.crt
      SSLCertificateKeyFile /etc/apache2/ssl/apache.key
    
      <FilesMatch "\.(cgi|shtml|phtml|php)$">
       SSLOptions +StdEnvVars
      </FilesMatch>
      <Directory /usr/lib/cgi-bin>
       SSLOptions +StdEnvVars
      </Directory>
    
     </VirtualHost>
    </IfModule>
    
  7. Save and close the file.

Step 4: Enabling Apache SSL module

  1. Enable the SSL module by typing:

    sudo a2enmod ssl
    
  2. Now enable the site we have just edited:

    sudo a2ensite default-ssl.conf
    
  3. Restart Apache:

    sudo service apache2 restart
    
  4. Let's access the new secure website! Open it in your browser (make sure you type https://).

    https://YOUR_SERVER_IP
    

Your browser will warn you that the certificate is invalid, as we expected. This happens because the certificate is not signed. Follow the steps offered by your browser to proceed to your site.

Step 5: Redirect all HTTP traffic to HTTPS (Optional)

  1. Open the Apache default virtual host file:

    nano /etc/apache2/sites-available/000-default.conf
    
  2. Add this line inside the <VirtualHost *:80> tag:

    Redirect / https://YOUR_SERVER_IP_OR_DOMAIN/
    
  3. Reload Apache configuration:

    sudo service apache2 reload
    

All website traffic will now automatically redirect to HTTPS.