facebook youtube pinterest twitter reddit whatsapp instagram

Securing Apache Server Using a (Self Signed Certificate) [Ubuntu]

In this guide, you'll learn how to use SSL to secure Apache, this way, you can ensure your websites are encrypted and available over HTTPS.

By default, Apache configuration listens for traffic on port 80 in Ubuntu, and not port 443 (HTTPS).

Confirm by running the following command:

sudo netstat -tulpn |grep apache

This would be the output if apache is only listening to port 80:

tcp6 0 0 :::80  :::*  LISTEN 1163/apache2   

If the server is listening on port 443, the below output should look similar:

tcp6 0 0 :::80 :::* LISTEN 3356/apache2
tcp6 0 0 :::443 :::* LISTEN 3356/apache2

To enable support for HTTPS traffic, you need to first enable the SSL module, and you then restart:

sudo a2enmod ssl
sudo systemctl restart apache2

Ubuntu default Apache includes a site configuration listening for a connection on port 443, and other config related to SSL.

Open it up to understand how it works:

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

This is the output would the comment stripped out:

<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>
  • On the first line, you see IfModule mod_ssl.c, this is pretty explanatory, the <IfModule mod_>...</IfModule> section is used to mark directives that are conditional on the presence of a specific module. The directives within a <IfModule> section are only processed if the module is true. If the module is false, everything between the start and end markers is ignored.
  • On the second line, the virtual host is listening on port 443, and the _default_ option applies to unspecified traffic, which means any traffic coming into port 443 that hasn't already been identified in any other virtual host.
  • The ServerAdmin email specifies the email address that is displayed in any error messages shown in case there is a problem with the site.
  • Documentroot is the location you are serving the website content from, in this case, I am serving the content from /var/www/html, this is totally customizable.
  • The error log is stored at /var/log/error.log and contains information you can use whenever someone has trouble
  • The access log contains information relating to HTTP requests that come in, and by default is stored in /var/log/access.log.
  • SSLEngine on enables SSL traffic
  • Right after that, you have options for your SSL certificate file, and key files, which we would get over in a moment.
  • FileMatch is used to target multiple files, in this case, it is targeting those file HTML, PHP, etc. and adding an SSL encryption for the matched file.
  • The <Directory> clause allows us to apply specific options to a
    directory. In this case, the /usr/lib/cgi-bin directory is being applied to the SSLOptions +StdEnvVars setting, which enables default environment variables for use with SSL.

By default, the default-ssl.conf file is not enabled,  In order to benefit from its configuration options, we'll need to enable it, which we can do with the a2ensite command as we would with any other virtual host:

sudo a2ensite default-ssl.conf

Our site isn't secured just yet, as we would need to install SSL certificated on our web server.

There are two ways you can do this, you can either go with a self-signed certificate which most browsers won't trust by default (it would return a not secure error, which you can bypass anyway) and the other way is to install certificates signed by a certificate authority, which is the recommended method.

We would be using a self-signed certificate as an illustration in this guide, they are not recommended for a production environment, so, if you are planning to secure Nginx on a production server, you can go with this article: Securing Apache Server Using (Let's Encrypt) [Ubuntu]

Installing a Self-Signed Certificate

Create a directory that houses our certificate. Create a certs directory under /etc/apache2/

Change your working directory into /etc/apache2/ and run the following command

sudo mkdir certs

To avoid an error when issuing a self-signed certificate in Ubuntu, you might need to create a .rnd in your user directory, make sure this is owned by the user of the home directory, it is used by OpenSSL to store some amount (256 bytes) of seed data.

Create the .rnd file:

touch ~/.rnd

Now, request for the certificate and key pair with the following command:

Note: You can also change the name of the key and cert file to match the name of your website.

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

You would be asked a series of questions, this is would be incorporated in your certificate request, here is the questions, and answer of mine:

Country Name (2 letter code) [AU]:NG
State or Province Name (full name) [Some-State]:Lagos
Locality Name (eg, city) []:Ikeja
Organization Name (eg, company) [Internet Widgits Pty Ltd]:Devsrealm
Organizational Unit Name (eg, section) []:IT
Common Name (e.g. server FQDN or YOUR name) []:blog.devsrealm.com
Email Address []:faruq@devsrealm.com

Now, if you go into the /etc/apache2/certs directory, you'll see two files created: mywebsite.crt and mywebsite.key, which represent the certificate and private key respectively.

Now that these files have been generated, the next thing for us to do is to configure Apache to use them.

Find the following line in the  /etc/apache2/sites-available/default-ssl.conf file:

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

Comment out the lines by placing # symbol in front of both:

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

Add the generated certificate and key below the commented out line. e.g:

SSLCertificateFile /etc/apache2/certs/mywebsite.crt
SSLCertificateKeyFile /etc/apache2/certs/mywebsite.key

Reload Apache to add the new configuration:

sudo systemctl reload apache2

There is one more step to go, our certificate file is already installed, but we need to inform Apache of when to apply them.

Add Severname option to the above file to ensure the site supports SSL.

ServerName mywebsite.com:443

Now, when traffic comes in to your server on port 443 requesting a domain that matches the domain you typed for the ServerName option, it should result in a secure browsing
session for the client.

As this certificate isn't coming from a known certificate authority, you might see an error, which you can skip. This doesn't mean the encryption isn't working though, the browser is just skeptical of the certificate

If you want to host multiple websites over HTTPS, you might want to separate the virtual host file for each domain.

To do this:

  • copy all the content in the /etc/apache2/sites-available/default-ssl.conf
  • create a new file under sites-available, e.g website1.conf
  • Change the virtual to listen for anything coming in on port 443 e,g <VirtualHost *:443>
  • Make sure the servername is changed to the specific domain, and it's listening on port 443
  • Change the documentroot to the folder the website file is located
  • Lastly, customize the error and access log
  • Here is an example:
<IfModule mod_ssl.c>
<VirtualHost *:443>
ServerName website1.com:443
ServerAdmin webmaster@localhost
DocumentRoot /var/www/website1
ErrorLog ${APACHE_LOG_DIR}/website1.com-error.log
CustomLog ${APACHE_LOG_DIR}/website1.com-access.log combined
SSLEngine on
SSLCertificateFile /etc/apache2/certs/website1/acme.crt
SSLCertificateKeyFile /etc/apache2/certs/website1/acme.key
<FilesMatch ".(cgi|shtml|phtml|php)$">
SSLOptions +StdEnvVars
</FilesMatch>
<Directory /usr/lib/cgi-bin>
SSLOptions +StdEnvVars
</Directory>
</VirtualHost>
</IfModule>

Related Post(s)

  • Setting Up Send-Only Mail Server From Scratch (With Haraka)

    In this guide, I would walk you through the steps of setting up an email server that can be used as a send-only mail server, we would not be dealing with receiving mails, we only care about sending em

  • Send Mail with Attachment Using Mutt in GNU/Linux

    Mutt is a powerful text&#x2d;based mail client for Unix/Linux operating systems. It features color support, message threading, MIME support...

  • Using Pageant To Automatically Authenticate SSH key in Putty

    I can't count how many times I have typed my ssh key passphrase whenever my ssh connection times out, it is so annoying and repetitive. Well, thanks to the putty pageant, you can do that seamlessly.

  • Installing WP-CLI In a GNU/Linux Server

    WP-CLI is a command-line interface for WordPress. It can also be used with ClassicPress, as they are no differences in their usage, maybe just minimal if you are updating or downloading new ClassicPr

  • How To Send Mail To Multiple Addresses Using (mailx)

    In this guide, you'll learn a couple of ways you can send mail to multiple addresses using mailx. mailx is a utility program for sending and receiving mail. I assume you already have mailx command, i

  • Monitoring Multiple Log Files In RealTime With MultiTail (Ubuntu)

    Oh my... I really find scanning through the logs file time consuming, and painful. Luckily for me, I founded Multitail, which is an awesome, and powerful tool for not only browsing through several f