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

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!

Type: 

Comments

I must say, I've followed this all to the letter and it is perfect. You covered virtually every situation I ran into trying to set up my own email server on my Raspberry Pi. Kudos!

Hi Sam, Thanks for your tutorials they really are a fantastic resource. I followed your tutorial a while back and it worked great and allowed me to use certificate for email and web server.

However now I am getting notification I will need to renew my certificate, I followed the link in the email and logged into CACert website. I clicked to renew which gave me a new certificate. I then created a new certificate file and copied it over the old one, I renamed it to use same name as old one. However when I tried to restart my webserver (which is nginx) I get a message that the private key file doesn't match. Also my email stopped working. I wondered if you have any idea where I went wrong? At the moment I've copied the old one back in which has everything working again, but will expire fairly soon.

Thanks

It's a while since I've updated a cert with cacert, do they just give you a new cert or do you have to submit another CSR?

Sam

Hi Sam, No I didn't need to submit another CSR they just gave me a new certificate when I clicked the renew button. But I'm not sure what to do with it! I downloaded the pem version (if i remember right) and then renamed it to replace the old one with the new one (in /etc/ssl/certs). But that didn't seem to work. Wondered if i need to recreate symlinks or something ? Or if its because the private key doesn't work with the new cert? Anyway no worries if you don't know off top of your head. I guess I can go through the whole creating a CSR process again if I need to ..

Well, it should work. As you said, best thing to try is generating a new CSR from your private key, that way you'll know for sure that it matches the key you're using.

I can't think how, but it does seem your key and cert don't match. Those error messages are pretty reliable.

Sam

Hi Sam

Excellent set of tutorials, thank-you. However, I have a problem, after changing the SSLCertificateFile and SSLCertificateKeyFile, Apache won't reload or restart, I get the error message

pi@raspberrypi ~ $ sudo service apache2 restart
[....] Restarting web server: apache2 ... waiting Action 'start' failed.
The Apache error log may have more information.
failed!

When I try to restart, same with reload. When I change the parameters back, it works fine.

Any hints, ideas?

Thanks
Shaun

Many thanks for the excellent article and website. I've installed and pointed to the .crt applying this to sub-domains (after reading your other post) and now on the base domain the browser is throwing up cannot connect pages.

Any ideas?

What's the exact error message in your browser?

When you restart apache, do you get any errors? If so, what's in your log (/var/log/apache2/error.log)?

Sam

Thanks for the response, it appears the firewall was not forwarding the 443 port, router swapped and the ssl is working better, still a few niggles but webmin has broken the apache2 install and throwing up loads of old config files, I'm just re-installing a new raspbian as we speak :)

Hi Sam,

Again can I applaud your dedication with these great tutorials. I managed to create a CAcert on the first time of asking and it immediately picked it up on my K9 app...excellent!

Regards,

Jo

Hello,

Thank you for the excellent tutorial. One barrier I'm having is that I'm using the pagekite server to tunnel my PI to a public IP address and I do not have an actual personal domain & email address to receive the required emails.

Will I need to actually register a domain name and map the pagekite address to the domain to get the email and setup the CAcert? Any workaround for this?

Thanks again

Hi,

That's the first I've heard of pagekite. Just had a quick look at their overview page and I can't see why you'd do this rather than just forward a port from your router to the server?

You will need to register a domain.

Sam

Thanks for the great tutorials I setup a Pi Mailserver using your tuts and she is working perfectly!!!

However, I'm now being told when I open Outlook (2010) that the CAcert certificate is "expired".
I've checked with CAcert and it's valid and current.

Is there an update process I have to do on the Pi or is there something else I'm missing?

Thanks for the help!!! (I wouldn't have been able to do this without your tutorials!!!)

Hi Sam,
more feedback on Ca Cert troubles.
I used an on-line cert checker at DigiCert.com and the result is. .

DNS resolves timxjr1300.ddns.net to {not saying]

HTTP Server Header: Apache/2.2.22 (Debian)

SSL certificate

Common Name = timxjr1300.ddns.net

Subject Alternative Names = timxjr1300.ddns.net

Issuer = CA Cert Signing Authority

Serial Number = 119E19

SHA1 Thumbprint = B811771D3C854C121B9909FD8EB597644F1EDDFC

Key Length = 4096

Signature algorithm = SHA256 + RSA (excellent)

Secure Renegotiation: Supported

SSL Certificate has not been revoked

OCSP Staple: Not Enabled
OCSP Origin: Not Enabled
CRL Status: Not Enabled

SSL Certificate expiration

The certificate expires July 9, 2016 (178 days from today)

Certificate Name matches timxjr1300.ddns.net

Subject timxjr1300.ddns.net
Valid from 11/Jan/2016 to 09/Jul/2016
Issuer CA Cert Signing Authority

SSL Certificate is not trusted

The certificate is not signed by a trusted authority (checking against Mozilla's root store). If you bought the certificate from a trusted authority, you probably just need to install one or more Intermediate certificates. Contact your certificate provider for assistance doing this for your server platform.

So it appears that CA Cert is not trusted?
I must be missing something.

Regards
Tim

The CAcert root certificate isn't in the trusted root store for that checker, in the same way that it isn't in the trusted root store for your OS, which is why you had to import it.

Refer to my other comment, I hope that's it (should resolve itself by the start of next week).

Sam

At first thanks for the great tutorial!

After completing the tutorial I decided to try openssl to connect to my mail server. This ended up with this error:

openssl s_client -connect localhost:465 -quiet

depth=0 CN = [domain]
verify error:num=20:unable to get local issuer certificate
verify return:1
depth=0 CN = [domain]
verify error:num=27:certificate not trusted
verify return:1
depth=0 CN = [domain]
verify error:num=21:unable to verify the first certificate
verify return:1
220 [domain] ESMTP Postfix (Debian/GNU)

Changing localhost for my domain name also ended up with the same error. Do you have any idea what I did wrong? I changed the dovecot/postfix config files to the right certificates and restarted both services.

(sorry if this is a repost my internet browser keeps timing out when submitting this form)

Thanks in advance!

You need to use the CApath option so that openssl knows where your trusted root certs are stored (/etc/ssl/certs).

Sam

Sam,
One more question. Suppose a message is sent to the RPi mailer as wronguser@xxx.co.uk is there a way in which this message could be routed to, say, postmaster@xxx.co.uk? My current ISP mail system will route all such wrongly identified mail to admin@<my ISP mail address>. In the past this has proved helpful. (On one occasion, it exposed a robot which was sending marketing mail to random 5 letter users at my ISP mail server. This activity was reported to the ICO and led to a potential prosecution of the company involved....)

John

Yeah it's possible (I discussed it with someone else in the comments somewhere a while back), but the disadvantage is that you'll get ridiculous amounts of spam from those bots you're talking about, to the point where you're likely to fill up your SD card pretty quickly, and the overhead from processing all the email with spamassassin will be considerable. Reporting these companies rarely actually does anything, especially when the spam is sent by compromised home computers.

Sam

Thanks for all the tutorials that you have done.
I have followed the email server setup and was able to send and receive email but when i tried to add a certificate from CAcert. I'm getting failed connections.
Here is whats the error is in mail.log:
May 4 13:09:46 raspberrypi dovecot: imap-login: Disconnected (no auth attempts in 0 secs): user=<>, rip=192.168.0.26, lip=192.168.1.150, TLS handshaking: SSL_accept() failed: error:14094416:SSL r$
May 4 13:09:46 raspberrypi postfix/smtps/smtpd[1305]: connect from unknown[192.168.0.26]
May 4 13:09:47 raspberrypi postfix/smtps/smtpd[1305]: SSL_accept error from unknown[192.168.0.26]: 0
May 4 13:09:47 raspberrypi postfix/smtps/smtpd[1305]: warning: TLS library problem: error:14094416:SSL routines:SSL3_READ_BYTES:sslv3 alert certificate unknown:s3_pkt.c:1294:SSL alert number 46:
May 4 13:09:47 raspberrypi postfix/smtps/smtpd[1305]: lost connection after CONNECT from unknown[192.168.0.26]
May 4 13:09:47 raspberrypi postfix/smtps/smtpd[1305]: disconnect from unknown[192.168.0.26]

I'm not sure where i went wrong. Any help would be much appreciated.

When I go to the CAcert site and put all my information in the site gives me this message:
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
Also when I try to send out or receive messages in the Thunderbird my server times out. Not but I think I missing something, any ideas?
-Cassie

Weird, did you see anything in your logs (/var/log/mail.log) when you submitted the information to CAcert? If there's nothing in there then maybe you have a DNS or firewall/port forwarding problem.

Sam

I input tail -f /var/log/mail.log and this what it gave me:
Jun 23 23:46:44 Ajax dovecot: master: Warning: Killed with signal 15 (by pid=192 5 uid=0 code=kill)
Jun 23 23:46:44 Ajax dovecot: master: Dovecot v2.2.13 starting up for imap (core dumps disabled)
Jun 23 23:55:43 Ajax postfix/master[1680]: terminating on signal 15
Jun 23 23:55:44 Ajax postfix/master[2137]: daemon started -- version 2.11.3, con figuration /etc/postfix
Jun 23 23:55:54 Ajax dovecot: master: Warning: Killed with signal 15 (by pid=215 8 uid=0 code=kill)
Jun 23 23:55:54 Ajax dovecot: master: Dovecot v2.2.13 starting up for imap (core dumps disabled)
Jun 23 23:57:10 Ajax postfix/master[2137]: reload -- version 2.11.3, configurati on /etc/postfix
Jun 23 23:58:12 Ajax postfix/master[2137]: reload -- version 2.11.3, configurati on /etc/postfix
Jun 21 23:17:20 Ajax dovecot: master: Dovecot v2.2.13 starting up for imap (core dumps disabled)
Jun 21 23:17:23 Ajax postfix/master[1700]: daemon started -- version 2.11.3, con figuration /etc/postfix

I then input tail /var/log/err.log
un 21 22:57:34 Ajax dovecot: imap(test1234): Error: stat(/home/test1234/Maildir/tmp) failed: Permission denied (euid=1002(test1234) egid=1002(test1234) missing +x perm: /home/test1234/Maildir, dir owned by 1003:1003 mode=0700)
Jun 21 23:07:34 Ajax dovecot: imap(test1234): Error: stat(/home/test1234/Maildir/tmp) failed: Permission denied (euid=1002(test1234) egid=1002(test1234) missing +x perm: /home/test1234/Maildir, dir owned by 1003:1003 mode=0700)
Jun 21 23:17:34 Ajax dovecot: imap(test1234): Error: stat(/home/test1234/Maildir/tmp) failed: Permission denied (euid=1002(test1234) egid=1002(test1234) missing +x perm: /home/test1234/Maildir, dir owned by 1003:1003 mode=0700)
Jun 23 23:23:13 Ajax dovecot: imap(test1234): Error: stat(/home/test1234/Maildir/subscriptions) failed: Permission denied
Jun 23 23:23:13 Ajax dovecot: imap(test1234): Error: opendir(/home/test1234/Maildir) failed: Permission denied (euid=1002(test1234) egid=1002(test1234) missing +r perm: /home/test1234/Maildir, dir owned by 1003:1003 mode=0755)
Jun 23 23:23:13 Ajax dovecot: imap(test1234): Error: opendir(/home/test1234/Maildir) failed: Permission denied (euid=1002(test1234) egid=1002(test1234) missing +r perm: /home/test1234/Maildir, dir owned by 1003:1003 mode=0755)
Jun 23 23:23:13 Ajax dovecot: imap(test1234): Error: opendir(/home/test1234/Maildir) failed: Permission denied (euid=1002(test1234) egid=1002(test1234) missing +r perm: /home/test1234/Maildir, dir owned by 1003:1003 mode=0755)
Jun 23 23:23:13 Ajax dovecot: imap(test1234): Error: opendir(/home/test1234/Maildir) failed: Permission denied (euid=1002(test1234) egid=1002(test1234) missing +r perm: /home/test1234/Maildir, dir owned by 1003:1003 mode=0755)
Jun 23 23:23:13 Ajax dovecot: imap(test1234): Error: stat(/home/test1234/Maildir/.Trash) failed: Permission denied (euid=1002(test1234) egid=1002(test1234) missing +x perm: /home/test1234/Maildir, dir owned by 1003:1003 mode=0700)
Jun 23 23:23:13 Ajax dovecot: imap(test1234): Error: stat(/home/test1234/Maildir/tmp) failed: Permission denied (euid=1002(test1234) egid=1002(test1234) missing +x perm: /home/test1234/Maildir, dir owned by 1003:1003 mode=0700)

what do you think?
-Cassie

total 12
drwx------ 2 1003 1003 4096 May 28 02:46 cur
drwx------ 2 1003 1003 4096 May 28 02:46 new
drwx------ 2 1003 1003 4096 May 28 02:46 tmp

Not sure how you've ended up with that... change the ownership to test1234:

sudo chown -R test1234:test1234 /home/test1234/Maildir

Sam

Hi, sam
I got as far as the Submitting the CSR to CAcert step when i ran into trouble. I got the following error when i submitted the form

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.

I used the email address(not testmail) from your raspberry pi email server tutorial, for which I am submitting for the cert. Am I getting the error because i don't have the cert for the address yet, or could there be a problem with my email server? Should I just use a different email address in the CaCert form?

Pages

Add new comment