Author: Francis NdunguLast Updated: Thu, Sep 9, 2021
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.
To complete this guide, make sure you've the following:
A sudo user.
An Apache webserver.
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
$ sudo openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout /etc/ssl/private/apache.key -out /etc/ssl/certs/apache.crt
openssl command explained:
req -x509: You're using this option to create a self-signed certificate instead of generating a CSR.
-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.
-days n: This is the number of days that you want the certificate to remain valid. For instance
-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.
-keyout filename: This is the file name where you're saving your newly created private key.
-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. email@example.com.
Once you complete providing the information, the
openssl command should generate a private key and a certificate file in the following locations.
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.
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.
nano text editor to open the
$ sudo nano /etc/apache2/sites-available/default-ssl.conf
In this file, locate the line
ServerAdmin firstname.lastname@example.org as shown below.
... ServerAdmin 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 firstname.lastname@example.org 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
$ 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
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
443 by executing the command below.
$ sudo ufw allow 'Apache Full'
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'
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.
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
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
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
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.
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: