Generating Let's Encrypt TLS Certificates for Use on Shared Hosting Plans
Published on by nick
I have been using Let's Encrypt for TLS certificates for over a year now, and I must admit -- it's awesome! Not only can you easily generate certificates; you can renew them with a one line command. I've written about setting up servers with Let's Encrypt certificates on this blog, as well.
Part of the reason this has been easy for me, however, is that I mainly use VPS or other cloud-based services that give me complete control over VMs. This means I can install whatever software I want on them, which is nice when you need control over your server...
But I realize that many users out there are still using shared hosting. This is unfortunate in many ways, as shared host providers heavily limit what you can do on your "chunk" of server. In one particular case, I have a client that uses a local shared host called Kattare. This company does some things right: they offer isolated Tomcat containers, so you can deploy your own Java applications very easily.
One thing they do wrong is use old software: older versions of Apache, PHP, Python are all common for this particular web host. Sure, you can get around much of this with some command line magic; but it makes doing most simple things harder. One thing they maintain complete control over is installing the actual TLS certificate. The workflow is generate a CSR, apply for and purchase a certificate from one of the vendors that charge loads of money, send (or copy) the certificate files, and then file a ticket with their support department to install it for you. I can't really avoid the last step, but I can control who I get certificates from and/or what tools I use to create them.
The article is a bit long and very detailed, so I'm going to summarize and highlight the bits that I found essential to making this work. Some of it is boilerplate, and regardless of whether you are buying your certificates from Comodo, Digicert, or some other vendor, these steps are required to set up HTTPS on your web site. Let's get started...
First thing you need to do is create a certificate signing request (CSR). This can be done through your cPanel or (if you have access to SSH) the terminal. I will perform these steps using the terminal method. On Linux, you should have the OpenSSL tools already installed:
This should take you to the man page for
openssl. We can issue a single command that will create a key and a CSR. It looks like this:
openssl req -new -newkey rsa:2048 -nodes -keyout sub.domain.key -out sub.domain.csr
Note that in this case,
sub.domain was used. If you create a certificate for the primary domain, you can use
domain, etc, for
example.com, you would use
example. The sub piece could be the
www part, so this would be
www.domain instead. In this case, I had to generate several certificates, corresponding to several subdomains, like
After you have the CSR, you will need to create your certificates. The way Let's Encrypt works is by running a verification on the domain you want to secure. In the case where you are running these commands on the VM that you will be running the web server on (eg, a Digital OCean droplet), you can simply make sure there is no web server running on ports 80 and 443, and then the verification use the system to verify ownership. This gets a bit tricky if you are creating certificates on a server that is not the one on which you will ultimately be running the web server. Either way, you will need access to the server where the web server will be running.
First step is to prepare the challenge directory and subdomain on your target server. This is very well explained in this article. Basically, you create a subdomain on your host, then map it to a directory on your server (eg, in
public_html, etc), and then add an Apache rewrite rule like this:
RewriteEngine On RewriteRule ^.well-known/acme-challenge/(.*)$ http://challenge.domain.com/challenge/$1 [L,R=302]
You might consider testing this is working by open a browser and testing the URL:
If all checks out, let's get that certificate created. You will need the cool little script mentioned in the article above. You can clone the git repo or download and install it directly. SSH into your server and run the following commands:
wget https://github.com/neurobin/letsacme/archive/release.tar.gz tar -xf release.tar.gz mv letsacme-release letsacme cd letsacme
In the shared hosting instance, you are working under the assumption that you can't really do things you normally would like install packages and programs system-wide. To this end, we will do all the work in this directory we're in now,
Create a Let's Encrypt account key and then transfer or copy/paste the CSR:
openssl genrsa 4096 > account.key vim domain.csr
domain.csr file open in
vim, paste the contents of the CSR into this file. Otherwise, use SCP or some other method to the server into the directory we're in.
Next, run the command to create the certificate (be sure to test the URL to
challenge before running this command or it will fail):
python letsacme.py --account-key ./account.key --csr ./domain.csr --acme-dir ~/path/to/challenge --cert-file ./signed.crt --chain-file ./chain.crt
You are welcome to use your own domain name for this step. It doesn't really matter, so do what you want but note it for future use.
Please note that if the script can't access the path you will get the common error:
E: Wrote file to /path/to/webserver/challenge_domain_com/123xyz but couldn't download http://www.domain.com/.well-known/acme-challenge/123xyz
At this point you would double check the directory on the server and the URL, making sure these are correct and that you have write permissions.
When the certificate process works successfully, you should see output like this...
Parsing account key... Parsed! Parsing CSR... CN: www.domain.com Parsed! Registering account... Already registered! Verifying www.domain.com... verified! Signing certificate... Parsing chain url... Signed! -----BEGIN CERTIFICATE----- ...certificate guts in here... -----END CERTIFICATE-----
The next steps include installing the certificate on the server. If you haven't done this before, you can see how it's done for Apache here and Nginx here. In this specific case, since this is the shared host where the support team at the hosting company requires they install the certificates, I transferred the files to the necessary folder and opened a ticket for support to install the certificate.