Secure Apache with a Self-Signed TLS/SSL Certificate on Ubuntu 20.04

Updated on November 21, 2023
Secure Apache with a Self-Signed TLS/SSL Certificate on Ubuntu 20.04 header image

Introduction

Transport Layer Security (TLS) and Secure Sockets Layer (SSL) are both internet-based security protocols that encrypt data over a network. For instance, when clients connect to your webserver to request a web page, you should encrypt the connection with a TLS/SSL certificate when receiving their sensitive data such as passwords and credit card information.

There is always a serious cyber threat across the internet when you exchange classified information in plain text between a client (for instance, a web browser, a mobile app, or desktop software) and a server system like Apache. Therefore, you need to implement a security layer between your systems. This is where an SSL/TLS certificate comes into play.

To generate an SSL/TLS certificate, you start by creating a Certificate Signing Request (CSR) on your server which generates a public/private key pair and a subject identifying the name of your website. Then, you simply send the CSR to a trusted Certificate Authority (CA) for signing at a fee.

Sometimes, there is no need to send the certificate for signing to a publicly trusted third-party CA. You can easily deploy and customize a self-signed certificate using OpenSSL without incurring any costs. However, only you can trust the certificate and anyone trying to connect to your web server will get a warning in their browser. Nevertheless, these kinds of certificates are highly suitable for internal networks and testing environments when performing initial configurations.

In this guide, you'll secure your Apache webserver with a self-signed certificate on Ubuntu 20.04 server.

Prerequisites

To complete this guide, make sure you've the following:

1. Generate a Private Key and a Certificate File

When securing your web traffic with the SSL/TLS protocol, you simply share your public key with anyone and keep your private key on your server. To create these keys, run the following openssl command.

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

The openssl command explained:

  1. req -x509: You're using this option to create a self-signed certificate instead of generating a CSR.

  2. -nodes: By specifying this option, you're telling openssl to avoid encrypting the private key with a passphrase. This is because you don't want to keep entering a password manually every time your server restarts. Apache should read this file without your intervention.

  3. -days n: This is the number of days that you want the certificate to remain valid. For instance 365 days.

  4. -newkey rsa:2048: You declare an explicit key size with this option. The smallest acceptable file is 512 bits but a larger value of 2048 offers more security.

  5. -keyout filename: This is the file name where you're saving your newly created private key.

  6. -out filename: Here, you specify an output *.crt file to store your signed certificate.

Once you execute the openssl command, you'll be prompted to provide the following information to generate your certificate. Enter the appropriate values and press Enter after every response.

Country Name (2 letter code) [AU]: Keyin a two-letter code of your country. For instance KE, or USA.
State or Province Name (full name) [Some-State]: Enter a full name for your state, for instance, CALIFORNIA.
Locality Name (eg, city) []: Enter your city e.g. LOS ANGELES.
Organization Name (eg, company) [Internet Widgits Pty Ltd]: Enter the name of your organization. For instance, SAMPLE COMPANY
Organizational Unit Name (eg, section) []: Key in your organization department e.g. IT.
Common Name (e.g. server FQDN or YOUR name) []: Enter the fully qualified domain name or IP address for your server. For instance example.com or 192.0.2.1.
Email Address []: Enter your email address e.g. info@example.com.

Once you complete providing the information, the openssl command should generate a private key and a certificate file in the following locations.

/etc/ssl/private/apache.key
/etc/ssl/certs/apache.crt

You've now generated the necessary files for your SSL/TLS certificate. In the next step, you will configure the SSL/TLS settings on the Apache virtual host file.

2. Enable SSL on the Virtual Host File

Apache maintains a default virtual host file to handle SSL traffic under the /etc/apache2/sites-available directory named default-ssl.conf. In order for the webserver to encrypt data with your certificate, you'll make some configuration changes in this file.

Use nano text editor to open the /etc/apache2/sites-available/default-ssl.conf file.

$ sudo nano /etc/apache2/sites-available/default-ssl.conf

In this file, locate the line ServerAdmin sample_email@example.com as shown below.

...

ServerAdmin sample_email@example.com

DocumentRoot /var/www/html
...

Under the above line, add the ServerName name directive followed by your domain name or the public IP address of your server as shown below.

...

ServerAdmin sample_email@example.com
ServerName 192.0.2.1
DocumentRoot /var/www/html
...

Then, still in the same file, locate the SSL settings below.

SSLCertificateFile      /etc/ssl/certs/ssl-cert-snakeoil.pem
SSLCertificateKeyFile /etc/ssl/private/ssl-cert-snakeoil.key

Specify the full file paths of your certificate (/etc/ssl/certs/apache.crt) and private key (/etc/ssl/private/apache.key). The two lines should look as follows after editing.

SSLCertificateFile    /etc/ssl/certs/apache.crt
SSLCertificateKeyFile /etc/ssl/private/apache.key

Save and close the file when you're done with editing. Next, use the Apache a2enmod command to enable the ssl module.

$ sudo a2enmod ssl

Then, use the a2ensite to enable the default-ssl.conf virtual host file.

$ sudo a2ensite default-ssl.conf

Restart the Apache webserver to load the new changes.

$ sudo systemctl restart apache2

Your apache web server is now ready to serve encrypted content. However, before you test the new settings, you'll configure your firewall to allow secure connections through port 443.

3. Enable SSL Port on the Firewall

In Apache, you should allow secure traffic to be exchanged through port 443 as opposed to the default port 80 which sends data in plain text. You can enable the HTTPS port using the ufw utility. First, enable your firewall by executing the following command.

$ sudo ufw enable

When prompted, press Y and Enter. Ensure you get the following response.

Firewall is active and enabled on system startup

Next, allow Apache to listen on both ports 80 and 443 by executing the command below.

$ sudo ufw allow 'Apache Full'

Output.

Rule added
Rule added (v6)

To avoid locking yourself out of the server, allow ssh connections through the OpenSSH port by running the following command.

$ sudo ufw allow 'OpenSSH'

Output.

Rule added
Rule added (v6)

Make sure you've opened any other port depending on the applications you're running. Then, execute the ufw status command to check if you've successfully added the new firewall rules.

$ sudo ufw status

You should receive the following output.

To                         Action      From
--                         ------      ----
Apache Full                ALLOW       Anywhere
OpenSSH                    ALLOW       Anywhere
Apache Full (v6)           ALLOW       Anywhere (v6)
OpenSSH (v6)               ALLOW       Anywhere (v6)
...

You've now configured your firewall to allow encrypted traffic to your webserver. In the next step, you'll visit your secured site and see if everything works as expected.

4. Test the New Configuration

Visit the URL below in a web browser and replace 192.0.2.1 with the correct public IP address or domain name. Make sure you're using the https:// protocol.

Your Apache server should now encrypt any data that you may try to exchange using the SSL/TLS certificate. Please note, your browser may issue a warning when you visit the page (Your connection is not private) because this certificate is not signed by a trusted CA. However, just suppress the warning and visit the page because you're only interested in the encryption part of your certificate. In the next step, you'll direct anyone trying to connect to the server via the insecure port 80 to the encrypted port 443.

5. Redirect HTTP Traffic to HTTPS (Optional)

Once you've generated, set up, and tested your SSL/TLS certificate, you can optionally redirect any HTTP traffic to HTTPS by editing the /etc/apache2/sites-available/000-default.conf file. Use nano to open the file.

$ sudo nano /etc/apache2/sites-available/000-default.conf

Then, enter the line Redirect "/" "https://192.0.2.1/" just below the <VirtualHost *:80> opening tags. Again, replace 192.0.2.1 with your domain name or server's public IP address.

<VirtualHost *:80>
...

Redirect "/" "https://192.0.2.1/"

ServerAdmin webmaster@localhost
DocumentRoot /var/www/html


...
</VirtualHost>

Save and close the file. Next restart the Apache webserver to load the new configuration settings.

$ sudo systemctl restart apache2

Visit the HTTP URL below on a web browser. You should now be redirected to the HTTPS version of the web page.

Your SSL/TLS certificate and redirection settings are now working as expected. Any further communications between the webserver and clients will now be exchanged through the secure channel.

Conclusion

In this guide, you've secured traffic on your Apache webserver with an SSL/TLS certificate. You can now connect your APIs, mobile apps, and desktop applications to the secure port and encrypt sensitive data as it flows through the network.

To bypass SSL/TLS certificate warnings when using the self-signed certificates, refer to the resource below: