Creating a Wildcard SSL Certificate for a DigitalOcean Droplet

This post will tell you how to create a Certificate Authority (CA) signed SSL certificate for a Droplet hosted on DigitalOcean with its own domain name. This assumes you own a domain name and have it pointing to an Ubuntu server.

Let’s Encrypt provides signed SSL certificates for free as long as their site can verify that you do manage a domain name.  They do it by having you make a few temporary entries to the DNS records pertaining to the domain name that they can match to the machine making the request.  This is how it is done.

Install the client (the official Let’s Encrypt ACME client)

sudo add-apt-repository ppa:certbot/certbot
sudo apt-get update
sudo apt-get install certbot

Create the request for the wildcard certificate. Let’s say you own example.com. Your certificate will be valid for any subdomains of that, such as www.example.com, mail.example.com, etc., but not simply example.com. For that you’ll need to add an extra term in the request, and add a second entry to your DNS records for Let’s Encrypt.  Execute the following command, enter ‘Y’ to have your IP logged, but do not hit enter until after adding the entries, in the next step.

sudo certbot certonly --server https://acme-v02.api.letsencrypt.org/directory --agree-tos --manual --preferred-challenges dns -d example.com -d *.example.com
Saving debug log to /var/log/letsencrypt/letsencrypt.log
Plugins selected: Authenticator manual, Installer None
Obtaining a new certificate
Performing the following challenges:
dns-01 challenge for example.com
dns-01 challenge for example.com

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NOTE: The IP of this machine will be publicly logged as having requested this
certificate. If you're running certbot in manual mode on a machine that is not
your server, please ensure you're okay with that.

Are you OK with your IP being logged?
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
(Y)es/(N)o: Y

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Please deploy a DNS TXT record under the name
_acme-challenge.example.com with the following value:

yvKpslex2Qxd5G8altPOv2K_dfTBgIxNEiwVFXD_Ex8

Before continuing, verify the record is deployed.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Press Enter to Continue

Go to your DigitalOcean Networking panel and access the records for example.com  add a TXT entry with the specifics provided by the certbot client (sample shown above).  You’ll need to paste the long string of gibberish into the VALUE field and type _acme-challenge into the  HOSTNAME.  Note, do not type the .example.com domain ending, as it is added automatically on DigitalOcean (and many other providers).

Adding a DNS challenge entry for Let’s Encrypt

Now go back and hit Enter in your certbot client.  You’ll have to do this twice, once for example.com, and once for *.example.com.  Once done, you’ll see something like the following, which will tell you how to renew your certificates in ninety days, when they expire (but they’re free, and it’s literally a one line command to renew them).

IMPORTANT NOTES:
 - Congratulations! Your certificate and chain have been saved at:
   /etc/letsencrypt/live/example.com/fullchain.pem
   Your key file has been saved at:
   /etc/letsencrypt/live/example.com/privkey.pem
   Your cert will expire on 2019-01-17. To obtain a new or tweaked
   version of this certificate in the future, simply run certbot
   again. To non-interactively renew *all* of your certificates, run
   "certbot renew"
 - If you like Certbot, please consider supporting our work by:

   Donating to ISRG / Let's Encrypt:   https://letsencrypt.org/donate
   Donating to EFF:                    https://eff.org/donate-le

You may now delete those TXT entries in the DNS records.  Your certificates are in a non-standard place, not /etc/ssl/cert and /etc/ssl/private, so be sure to update your Apache or Nginx configuration files accordingly.

Creating a Self-signed SSL Certificate

In this post I will explain how to create a self-signed certificate for testing purposes.  If you have a virtual machine running on your home network (such as inside VirtualBox, Hyper-V, or inside Windows Subsystem for Linux), it will not be able to get a Certificate Authority (CA) signed SSL certificate because it isn’t accessible on a static IP address attached to a domain name.  However, you may still want to set it up as if it was a public facing server in order to test out a configuration, e.g. Postfix, GitLab.

You must have openssl installed.  This will be installed on any Linux machine, but under Windows, binaries can be hard to come by.  I recommend installing the excellent development environment MSYS2, and installing it by opening up an MSYS2 window and typing:

pacman -S openssl

Once it’s installed, you’ll be creating a private key, a certificate request, and then you’ll sign the request with the private key to create a public certificate. You can use any names you want for the files, but I have chosen to replicate what Let’s Encrypt gives you by default.

Generate the private key

sudo openssl genrsa -out "privkey.pem" 2048

Generating RSA private key, 2048 bit long modulus
…..+++++
…+++++
e is 65537 (0x10001)

Generate the certificate request
You’ll be entering in some information here. The important one is the Common Name. Although you don’t have a real domain, it’s a good idea to make up one for your private network. I have seen people use the .lcl extension for it. Do not enter anything for the challenge password.

sudo openssl req -new -key "privkey.pem" -out "certrequest.pem"
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [AU]:US
State or Province Name (full name) [Some-State]:New Mexico
Locality Name (eg, city) []:Albuquerque
Organization Name (eg, company) [Internet Widgits Pty Ltd]:.
Organizational Unit Name (eg, section) []:.
Common Name (e.g. server FQDN or YOUR name) []:*.example.lcl
Email Address []:john.doe@example.lcl

Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:

 

Generate the certificate by signing the certificate request with the private key

sudo openssl x509 -req -days 30 -in "certrequest.pem" -signkey "privkey.pem" -out "cert.pem"
Signature ok
subject=C = US, ST = New Mexico, L = Albuquerque, CN = *.example.lcl, emailAddress = john.doe@example.lcl
Getting Private key

 

Now move them to a standard spot for certificates.

sudo chmod 644 cert.pem
sudo chmod 644 certrequest.pem
sudo chmod 640 privkey.pem
sudo mv cert.pem /etc/ssl/certs
sudo mv certrequest.pem /etc/ssl/certs
sudo mv privkey.pem /etc/ssl/private

You may now reference them in software that uses certificates such as Apache, Nginx, or Node.js apps. You will still get a warning saying that the certificate is invalid, but the data sent will be encrypted.