Letsencrypt, the free, automated, and open Certificate Authority has revolutionized the way servers of all sorts are secured to use SSL/TLS. Usually the entire process is quite smooth, but under certain circumstances requires some additional configuration. This short note explains how to configure Apache2 to use a virtual host in a user directory and redirect all http traffic to https.

Standard Installation

Letsencrypt, is a new Certificate Authority that helps users create public-private keys and certificates for free and in an automated manner. There are several guides online to help generate certificates for virtual hosts on Apache2 and other web servers. On Ubuntu this essentially boils down to running the following commands:

$ sudo add-apt-repository ppa:certbot/certbot
$ sudo apt-get update
$ sudo apt-get install python-certbot-apache
$ sudo certbot --apache -d example.com -d www.example.com

This assumes that a virtual host for example.com already exists. During this process Apache cannot be running as the certbot uses port 80 to run some of its ACME challenges. Also there should be an existing DNS entry pointing example.com to the server, i.e. the certbot must be able to resolve the IP address to the machine running the Apache server.

If everything goes well, you will be asked to provide an email address for lost key recovery and notices, and you will be able to choose between enabling both http and https access or forcing all requests to redirect to https.

When the installation is finished, the generated certificate files are stored at /etc/letsencrypt/live. You can verify the status of your SSL certificate with the following link (don’t forget to replace example.com with your base domain):

https://www.ssllabs.com/ssltest/analyze.html?d=example.com&latest

All that remains to be done is to use sudo crontab -e to add an entry for cron to automatically renew the certificate on expiry by adding the following line to the crontab:

15 3 * * * /usr/bin/certbot renew --quiet --pre-hook "/bin/systemctl stop apache2" --post-hook "/bin/systemctl start apache2"

Certonly Installation

Sometimes, it may be necessary to use the certonly mode of certificate installation, which does not involve configuring Apache (or other web server) to use the certificates. For example, if the certificates are being used to secure an application running on example.com. The command used in this case is:

$ sudo certbot certonly --standalone --standalone-supported-challenges http-01 -d example.com

The generated files are stored as earlier in /etc/letsencrypt/live.

Now if at some point one does wish to use the same certificate to secure a web server at example.com, it becomes necessary to add the configuration settings that the certbot would have added under a standard install.

Document root in user directory

This is entirely optional and sometimes considered bad security practice to host websites in user directories. At the very least, please ensure that:

  • Everything under public_html is owned by group www-data
  • All files have permissions 664
  • All directories have permissions 775
  • All directories have permission +s

Enable module userdir by

$ sudo a2enmod userdir

and ensure that the configuration file looks as follows:

$ sudo vi /etc/apache2/mods-enabled/userdir.conf
<IfModule mod_userdir.c>
        UserDir public_html
        UserDir disabled root

        <Directory /home/*/public_html>
                AllowOverride All
                Options MultiViews Includes FollowSymLinks
                Order allow,deny
                <Limit GET POST OPTIONS>
                        Require all granted
                </Limit>
                <LimitExcept GET POST OPTIONS>
                        Require all denied
                </LimitExcept>
        </Directory>
</IfModule>

The Options directive does not include Indexes to avoid displaying the contents of directories.

Create a separate document root for each virtual host that you want to host on the server.

$ mkdir -p ~/public_html/example.com

Set the persmissions as above. Create an html document to test that the server works.

$ vi ~/public_html/example.com/index.html
<html>
  <head>
    <title>Welcome to example.com!</title>
  </head>
  <body>
    <h1>Success! The virtual host is working!</h1>
  </body>
</html>

Create virtual host

$ sudo /etc/apache2/sites-available/example.com.conf
<VirtualHost *:80>
 ServerName example.com
 DocumentRoot /home/ubuntu/public_html/example.com/
 DirectoryIndex index.php index.html index.cgi index.pl index.xhtml index.htm
 <Directory /home/ubuntu/public_html/example.com/>
 AllowOverride All
 Order Deny,Allow
 Allow from all
 </Directory>
</VirtualHost>

Verify the document root directory suits your setup. Enable the site with:

$ sudo a2ensite example.com

Visit http://example.com in the browser and verify that the test page is displayed.

Enable secure connections

Install Apache mod_ssl and mod_rewrite to enable secure connections and redirect http to https.

$ sudo a2enmod ssl
$ sudo a2enmod rewrite

Modify the /etc/apache2/sites-available/example.com.conf file and add the rewrite engine rules to redirect all http traffic to https. The file should look like below:

<VirtualHost *:80>
 ServerName example.com
 DocumentRoot /home/ubuntu/public_html/example.com/
 DirectoryIndex index.php index.html index.cgi index.pl index.xhtml index.htm
 <Directory /home/ubuntu/public_html/example.com/>
 AllowOverride All
 Order Deny,Allow
 Allow from all
 </Directory>
RewriteEngine on
RewriteRule ^ https://%{SERVER_NAME}%{REQUEST_URI} [END,QSA,R=permanent]
</VirtualHost>

Next, create another configuration file /etc/apache2/sites-available/example.com-ssl.conf for the secure virtual host with information regarding the certificates and key files.

$ sudo vi /etc/apache2/sites-available/example.com-ssl.conf
<IfModule mod_ssl.c>
<VirtualHost *:443>
 ServerName example.com
 DocumentRoot /home/ubuntu/public_html/example.com/
 DirectoryIndex index.php index.html index.cgi index.pl index.xhtml index.htm
 <Directory /home/ubuntu/public_html/example.com/>
 AllowOverride All
 Order Deny,Allow
 Allow from all
 </Directory>
SSLCertificateFile /etc/letsencrypt/live/example.com/cert.pem
SSLCertificateKeyFile /etc/letsencrypt/live/example.com/privkey.pem
Include /etc/letsencrypt/options-ssl-apache.conf
SSLCertificateChainFile /etc/letsencrypt/live/example.com/chain.pem
</VirtualHost>
</IfModule>

When certbot manages the configuration for Apache, it creates the /etc/letsencrypt/options-ssl-apache.conf file. If it is not present, one needs to download it from the certbot GitHub repository.

$ cd /etc/letsencrypt
$ sudo wget https://raw.githubusercontent.com/certbot/certbot/master/certbot-apache/certbot_apache/options-ssl-apache.conf

Enable the ssl site using

$ sudo a2ensite example.com-ssl

Also make sure that the default sites are disabled, unless you are using them for something. But usually it is better to configure separate virtual hosts for each site that you plan to use.

$ sudo a2dissite 000-default
$ sudo a2dissite default-ssl

If all goes well, visiting https://example.com or http://example.com in the browser should now display the test html page.

One important point to note here is the DirectoryIndex directive in the configuration files. Sometimes it only includes index.php and the site does not display correctly. Make sure that the different index files are listed and if you intend to use php, that index.php is first on the list.

Conclusion

Letsencrypt has made it very easy to use secure sites and there is no reason or excuse to be using unsecure connections anymore.

Blog Comments powered by Disqus.

Next Post Previous Post