SSL Certificate Signing with CAcert for Raspberry Pi, Ubuntu & Debian

Powered by Drupal
Submitted by Sam Hobbs on

CAcert logo If you run your own website, email server or other services like OwnCloud at home then you may find yourself in need of a SSL certificate. When you install Apache, it generates a self-signed "snakeoil" certificate that can be used to encrypt your session. However, while this certificate is useful for testing purposes, it falls short in a couple of important ways:

  1. The snakeoil certificate has not been signed by an authority that your browser trusts, so your browser will throw an error when you connect.
  2. The common name on the certificate probably doesn't match your domain name. Another browser error.
  3. Short of manually inspecting the certificate's checksum, you have no guarantee that you are communicating with your own server - it could easily be an imposter using another self-signed certificate.

This tutorial will show you how to generate your own SSL certificate, and get it signed by the community driven SSL certificate signing authority CAcert. Once you have imported the certificate into your browser or into your operating system's root filesystem, your computer will automatically verify the identity of the server and you will enjoy error-free secure communications. Oh, and CAcert is free of charge!

Before we start: a quick note about filename extensions

As far as I can tell, Linux is not at all bothered about what you name your certificate and certificate key files. You could use the .magic extension for your cert if you liked and it would probably still work. From what I've read, file name extensions seem to only matter on Windows, whereas on Linux they're just descriptive. However, it's probably worth noting that there are lots of different types of certificate encoding styles, which have been summarised neatly here. Some extensions such as .pem and .der imply that the file is encoded in a certain way. Since we are able to choose whatever extension we like, I've chosen the following:

  • .csr for the certificate signing request (CSR)
  • .crt for the signed certificate file
  • .key for the key file

These have the benefit of not implying any particular encoding. The first time I did this on my Pi, I used .pem for everything and got in a muddle, forgetting which file was which. This should make things much easier!

Generate your certificate

We are going to use a two step process to generate your certificate. First, run this command, which will generate a private key:

openssl genrsa -out <filename for your private key>.key 4096

Now we will generate a new certificate signing request (CSR) from your private key:

openssl req -new -key <filename for your private key>.key -out <filename for the CSR>.csr

This stage requires user input, a series of questions about what information you would like to be on the certificate. Since CAcert is an automated service, it discards most of the information on the certificate (so that it doesn't certify the information it is unable to verify), leaving only the essentials: the email address and the common name. Here is the information you will be asked for:

  • Country Name (use a two letter code e.g. GB)
  • State or Province Name (e.g. Surrey)
  • Locality Name (e.g. Guildford)
  • Organisational Name (e.g. Sam Hobbs' Personal Website)
  • Organisational Unit Name (e.g. Website)
  • Common Name (your domain name - see note below - e.g. samhobbs.co.uk)
  • Email Address (the contact address for your administrator e.g. webmaster@samhobbs.co.uk)

Don't set a password - leave it blank when asked. We will keep the key file private by setting appropriate permissions. The common name is important here: most websites rewrite https:// to https://www. or vice versa. If your website is available at https://yourdomain.com then you should use yourdomain.com as the common name; if your website is at https://www.yourdomain.com then your common name should be www.yourdomain.com or *.yourdomain.com (the wildcard will match any subdomain, meaning you can use the same cert for https://mail.yourdomain.com and https://www.yourdomain.com, which is handy). Personally, I use a wildcard certificate. If you were paying for a normal certificate authority to sign your certificate then a wildcard cert would be more expensive, but CAcert is of course free so you might as well take advantage of it!

Install the CAcert root certificate

Every operating system comes pre-loaded with a set of certificates that are seen as trusted by the OS. This includes certificates from verisign and other big name certificate signing authorities. Very few OSes trust CAcert by default, although a couple of Linux distributions do. The CAcert website provides https using a certificate that was signed by the CAcert root. Since you are going to be sending sensitive information to the website during registration, it makes sense to install the CAcert root certificate now so that you can use the site without browser errors. To install the CAcert root certificate from the commandline, you can use these commands:

cd ~
wget http://www.cacert.org/certs/root.txt
sudo cp root.txt /etc/ssl/certs/cacert-root.crt

Those commands will download the CAcert root certificate into your home directory, and then copy it to your certificates folder. If you look in your certs directory (ls -l /etc/ssl/certs) you will see that all of the certs have sensible certificate names like GeoTrust_Global_CA.pem, but there are also a load of symbolic links with names like 2c543cd1.0 that point to the certificate files with the human readable names. Those symlink names like 2c543cd1.0 are hashes of the certificate files, and are there to enable programs on your computer to quickly check whether the root certificate is in your computer's certificate directory or not. Some programs manage to recognise that the certificate is installed just fine without the symlinks, but some of them do not. Openssl is one of the ones that doesn't. So, we need to make use of one more command to create a symlink for the newly installed cacert-root.crt (this will also refresh the symlinks for the rest of the certs in the folder):

sudo c_rehash /etc/ssl/certs

Now that the CAcert root cert is installed, almost all software on your system will recognise it (chromium, rekonq etc.). The exception to this is Mozilla software such as the Firefox web browser and Thunderbird email client. Mozilla software has its own certificate database, which has both advantages and disadvantages. For example, if you're using a system where you don't have admin rights, you can still easily import the CAcert root to Firefox. The disadvantage is that if you are an administrator, you can't do a one-stop installation: you have to import it separately to Firefox. To install the certs, open Firefox and navigate to the root certificate downloads page and click on the links for the class 1 and class 3 .pem encoded root certificates. You will be prompted to decide whether to import them or not. To install to Android, follow this tutorial of mine.

Required Email Address

CAcert verifies that you own the domain it is signing a certificate for by sending a verification link to one of the following email addresses:

  • root@yourdomain.com
  • webmaster@yourdomain.com
  • postmaster@yourdomain.com

You therefore need to be able to receive email to one of these addresses. You can set up your own email server, or failing that some domain name registrars provide email forwarding capabilities. If you used my tutorials to set up your email server then you may want to add some aliases to your server so that emails to those addresses above are delivered to your username. Here's how: Edit /etc/aliases and add:

postmaster: yourusername
webmaster: yourusername
root: yourusername

Now run this command to load the new aliases:

sudo newaliases

And reload Postfix:

sudo service postfix reload

Submitting the CSR to CAcert

First things first, you will need to go to the CAcert website and create an account: Please note that CAcert has signed its own SSL certificate, so your browser may throw an error if you haven't imported the root cert yet. cacert-registration.png After you have created your account and logged in, navigate to server certificates --> new. On your server, use cat to print the the Certificate Signing Request (CSR) you created earlier and then copy & paste it into the box:

cat <filename for the CSR>.csr

...and click submit. The result will be displayed on screen, and you will also be emailed the certificate. Copy and paste it into a file with the .crt extension, e.g. using nano:

sudo nano <path to your cert>.crt

...then CTRL+SHIFT+V to paste, CTRL+X, save when prompted. Note: the BEGIN CERTIFICATE and END CERTIFICATE lines are part of the cert, so copy those too!

Certificate File Locations

Assuming your certificates and key file are in your home directory, it's a good idea to move them to the proper locations

  • Your key file should be stored at /etc/ssl/private/samhobbs.key.
  • Your certificate file should be stored at /etc/ssl/certs/samhobbs.crt.
  • You can get rid of your CSR, or keep it for reference if you like.

Permissions & Ownership

Your key file is secret. It should be owned by root, and your permissions should be set so that only the root user can read and write to it. This command will set it to be owned by root:

sudo chown root:root /etc/ssl/private/samhobbs.key

And this command will set it so that only the root user can read and modify it:

sudo chmod 600 /etc/ssl/private/samhobbs.key

Most services like Apache, Postfix etc. require root privileges to start up. They read the certs when they start and store them in RAM, so that they can still use them when they drop to their normal users ( e.g. www-datafor Apache). Unlike your key file, your signed certificate file is not a secret (it is sent to users when establishing a secure session). You want all users to be able to read the cert, but only the root user to have write access to it. As before, this command will set it to be owned by root:

sudo chown root:root /etc/ssl/certs/samhobbs.crt

And this command will set it to be readable by everyone, but only modified by root:

sudo chmod 644 /etc/ssl/certs/samhobbs.crt

Some common SSL cert configuration parameters: Apache, Postfix, Dovecot

This section is a quick reference for where to find SSL parameters for Apache, Postfix and Dovecot.

Apache

You can tell Apache to use a specific certificate file in your SSL virtualhost configuration (e.g /etc/apache2/sites-available/default-ssl) with these parameters:

SSLEngine on
SSLCertificateFile /etc/ssl/certs/samhobbs.crt
SSLCertificateKeyFile /etc/ssl/private/samhobbs.key

Then reload Apache:

sudo service apache2 reload

Postfix

Postfix' SSL cert configuration can be found in /etc/postfix/main.cf:

smtpd_tls_cert_file=/etc/ssl/certs/samhobbs.crt
smtpd_tls_key_file=/etc/ssl/private/samhobbs.key

...and reload Postfix:

sudo service postfix reload

Dovecot

Dovecot's SSL configuration is in /etc/dovecot/conf.d/10-ssl.conf:

ssl_cert = </etc/ssl/certs/samhobbs.crt
ssl_key = </etc/ssl/private/samhobbs.key

NB: the < at the start of the path isn't an error, if you miss it out Dovecot won't load. Reload dovecot:

sudo service dovecot reload

Hopefully you found that useful! If you have anything to add or a question, please feel free to leave a comment!

Comments

Hi Sam,
I tried root@freehandhealth.co, webmaster@freehandhealth.co and postmaster@freehandhealth.co and got the same error as before. (I made sure to edit /etc/aliases and add the aliases. Then sudo newaliases and sudo service postfix reload before submitting. I followed your raspberry pi email server tutorial without any errors, but I have yet to send or receive any emails. I assumed that nothing was getting through because of the lack of a proper certificate, based on the error, however it would seem that i made a mistake in installing the email server.

Hi Sam, sorry for the delay.
here's the output
Usage: usermod [options] LOGIN

Options:
-c, --comment COMMENT new value of the GECOS field
-d, --home HOME_DIR new home directory for the user account
-e, --expiredate EXPIRE_DATE set account expiration date to EXPIRE_DATE
-f, --inactive INACTIVE set password inactive after expiration
to INACTIVE
-g, --gid GROUP force use GROUP as new primary group
-G, --groups GROUPS new list of supplementary GROUPS
-a, --append append the user to the supplemental GROUPS
mentioned by the -G option without removing
him/her from other groups
-h, --help display this help message and exit
-l, --login NEW_LOGIN new value of the login name
-L, --lock lock the user account
-m, --move-home move contents of the home directory to the
new location (use only with -d)
-o, --non-unique allow using duplicate (non-unique) UID
-p, --password PASSWORD use encrypted password for the new password
-R, --root CHROOT_DIR directory to chroot into
-s, --shell SHELL new login shell for the user account
-u, --uid UID new UID for the user account
-U, --unlock unlock the user account
-Z, --selinux-user SEUSER new SELinux user mapping for the user account

Hi Sam,
Here's the output
Usage: usermod [options] LOGIN

Options:
-c, --comment COMMENT new value of the GECOS field
-d, --home HOME_DIR new home directory for the user account
-e, --expiredate EXPIRE_DATE set account expiration date to EXPIRE_DATE
-f, --inactive INACTIVE set password inactive after expiration
to INACTIVE
-g, --gid GROUP force use GROUP as new primary group
-G, --groups GROUPS new list of supplementary GROUPS
-a, --append append the user to the supplemental GROUPS
mentioned by the -G option without removing
him/her from other groups
-h, --help display this help message and exit
-l, --login NEW_LOGIN new value of the login name
-L, --lock lock the user account
-m, --move-home move contents of the home directory to the
new location (use only with -d)
-o, --non-unique allow using duplicate (non-unique) UID
-p, --password PASSWORD use encrypted password for the new password
-R, --root CHROOT_DIR directory to chroot into
-s, --shell SHELL new login shell for the user account
-u, --uid UID new UID for the user account
-U, --unlock unlock the user account
-Z, --selinux-user SEUSER new SELinux user mapping for the user account

That's OK then - one of the times you entered it, it must have worked (or you were already in the group) because the output from /etc/group shows gncadd and pi are in the adm group. I take it gncadd is your login? Sam

Michele Zarri

Sat, 09/10/2016 - 19:11

Great tutorial. All that is missing is a paypal account.. I am sure I am not the only one who would be happy to offer you a beer all the help you provided!

I would like to suggest a small improvement: could you add to the "Required email address" section that to verify the ownership of the domain you need to login your CAcert account ==> select the "+Domains" option in the menu bar on the right ==> select "Add"?

I only found that out after my attempt to get a certificate bounced.

Cheers,

Michele

"Email Address given was invalid, or a test connection couldn't be made to your server, or the server rejected the email address as invalid

Failed to make a connection to the mail server"
What to do its showing domain name does not exist.

Hi, Sam
I change my Cacert certification which is a renewed domain. (i.e. The domain becomes *.helloworld.org and the previous one is mail.helloworld.org.) My computer works well on sending mail and receiving mail with the certification. But, my phone always show up the message "Unable to verify the server identity: mail.helloworld.org". I had been referring some articles to install a .crt for my phone. It definitely installs on my phone. However, the message still shows up. Do you have any clues about this?

Best regards,
Jeff

Hi Sam,
I use iOS (Version 10.2). In addition, I found the CAcert this certificate not recognized by Chrome browser. (I think I don't make the wrong setting on my CAcert SSL.) Safari recognizes CAcert SSL by a certification management tool which also manage login password and secret key. But, iOS seems to have its certificate database for verifying the recognizable domains. What I manually import the *.crt to my phone is also in vain for my phone sending mail. Whatever it did't work right now. Hope your advices. Thank you.

Jeff

James Hughes

Sat, 01/21/2017 - 00:59

Hi Sam!

Your tutorials are awesome an I had everything working (barring gmail's spam filters because my ISP is draconian) however, now I've followed this tutorial to get an actual certificate my email server has stopped working with thunderbird, I get the following error:
The message could not be sent because the connection to Outgoing server (SMTP) pyrosoftsolutions.co.uk timed out. Try again. .

Any ideas?

James Hughes

Sat, 01/21/2017 - 01:39

After my previous comment I managed to get it working (it was some stupid copy/paste error). However, apache2 doesn't seem to be presenting this key despite adding the lines that you suggested. Any ideas?

Hi I appreciate your great series of articles, I now have a working mail server thanks to you on a Raspberry Pi 2!
The only thing is that the CACert I am finding that it is not recognized as a certificate authority by Firefox, and so I get a security warning, and have to make an exception. I thought it was a problem with my installation, but now I find that they are just not recognized.

Hi Jon, Yes, that's expected behaviour, which is why the summary at the top mentions installing the cacert certificate onto the computers you are going to use. If you don't control all of the devices you are going to use to connect (e.g. if it's a public website) then this is not an appropriate solution. If you want to get a certificate that is recognised by a "proper" CA, then you can use the CSR we generated in this tutorial along with this other tutorial of mine, which explains how to configure postfix, dovecot and apache2 to use a commercial cert. Sam

Hi there,

Following along, I get to the step where I should install the CAcert root certificate from the command line. When I do:
sudo c_rehash /etc/ssl/certs
I get nothing but permission denied messages, like:

sudo c_rehash /etc/ssl/certs
Doing /etc/ssl/certs
sh: 1: /home/pi/openssl: Permission denied
CA_Disig_Root_R2.pem => .0
sh: 1: /home/pi/openssl: Permission denied
WARNING: Skipping duplicate certificate CA_Disig_Root_R2.pem
sh: 1: /home/pi/openssl: Permission denied
WARNING: Skipping duplicate certificate DigiCert_Global_Root_CA.pem
sh: 1: /home/pi/openssl: Permission denied
WARNING: Skipping duplicate certificate DigiCert_Global_Root_CA.pem
sh: 1: /home/pi/openssl: Permission denied
WARNING: Skipping duplicate certificate SwissSign_Gold_CA_-_G2.pem
sh: 1: /home/pi/openssl: Permission denied
WARNING: Skipping duplicate certificate SwissSign_Gold_CA_-_G2.pem
sh: 1: /home/pi/openssl: Permission denied
WARNING: Skipping duplicate certificate DigiCert_High_Assurance_EV_Root_CA.pem
...this goes on for awhile...

Any thoughts what might be going on here?

Thank you for the write up! Very useful.

In the install CACert root certificate, rehash does not create the symbolic link, right? So there is a missing step of adding the ln -s. How do I get the hash for using in the symbolic link?

Thank you!

My previous (only) comment/question about adding the ln -s / rehash. Take back. You can delete my comments. I just could not find the link in the dir. There were tons of links. If I listed the file name, the sym link was not showing up... Also iit created two sym links!

Add new comment

The content of this field is kept private and will not be shown publicly.

Filtered HTML

  • Web page addresses and email addresses turn into links automatically.
  • Allowed HTML tags: <a href hreflang> <em> <strong> <cite> <blockquote cite> <code> <ul type> <ol start type> <li> <dl> <dt> <dd>
  • Lines and paragraphs break automatically.