Your requirement

You want to set up a server service on the Internet which provides encrypted SSL or TLS connections (e.g. HTTPS, POP3S, IMAPS, LDAPS, SMTP with TLS).

The difficulty

To offer a connection secured with SSL/TLS, you need a server certificate. This must be signed by a certification authority (CA).

An official server certificate, which is signed by an official authority, is unfortunately not free. In most cases, annual fees of several hundred euros will be incurred.

A possible solution

Under Linux, you can set up your own CA with on-board tools, and then create and sign your own certificates. This is a process of a few minutes. All details for the procedure are described in this article.

In this case, the only difference to a certificate signed by a recognised authority is that the client (email program, browser, etc.) will issue a warning that it does not recognise the CA. The user only needs to confirm this once, and can then accept the certificate despite such a warning.

Detailed procedure

1. Install OpenSSL

OpenSSL is almost always used under Linux for the administration of the certificates and for the encryption of the connections with SSL and TLS. This is probably why it is already installed on your system. If not, you will have to install the openssl package. You will need the openssl command-line command from this package.

2. Creating the CA

First create a directory in which you want to store the certificate. In our example we use /root/ca:

root@linux# mkdir /root/ca
root@linux# cd /root/ca

We deliberately set the validity very high at 10 years. If the CA expires, all server certificates signed with it become invalid. The CA contains a secret key which is automatically generated and stored in the file cakey.pem. The CA certificate is written to cacert.pem. The following command generates a key with a length of 2048 bits for the certificate:

root@linux# openssl req -new -x509 -newkey rsa:2048 -keyout cakey.pem -out cacert.pem -days 3650
Generating a 2048 bit RSA private key
..............................................................
..............................................................
.........................................+++
......................................+++
writing new private key to 'cakey.pem'

Anyone who knows the secret key of the CA can use it to sign any server certificates. Therefore this key file is not stored in plain text on the hard disk, but encrypted with a passphrase. You will always require this passphrase if you want to issue new certificates with the CA:

Enter PEM pass phrase: wrzlprmpft
Verifying - Enter PEM pass phrase: wrzlprmpft

You will now be asked to enter data that identifies the CA. This will be displayed to the client when they are asked to accept or reject the certificate. The code for Germany is DE. If you want to leave a field empty, enter a dot (period). Otherwise, the default value in square brackets is entered:

-----
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]: DE
State or Province Name (full name) [Some-State]:.
Locality Name (eg, city) []:Muenchen
Organization Name (eg, company) [Internet Widgits Pty Ltd]:Hinz und Kunz AG
Organizational Unit Name (eg, section) []:.

The Common Name (CN) field is the official name of the certification body. For your own CA you can simply enter your own name:

Common Name (eg, YOUR name) []: Adam Hinz
Email Address []: adam@hinzag.eu

Done. The following two files have been created:

root@linux# ll
insgesamt 9
drwxr-xr-x   2 root root  112 2006-04-30 12:08 .
drwx------  12 root root  600 2006-04-30 11:54 ..
-rw-r--r--   1 root root 1212 2006-04-30 12:08 cacert.pem
-rw-r--r--   1 root root  963 2006-04-30 12:08 cakey.pem

As a precaution you should set the rights so that only root can read the key file:

root@linux# chmod 600 cakey.pem

You can now try out whether you can open the key again using the passphrase:

root@linux# openssl rsa -in cakey.pem -noout -text
Enter pass phrase for cakey.pem: wrzlprmpft
Private-Key: (1024 bit)
modulus:
    00:d5:a5:37:51:e9:d9:fa:e3:97:e7:46:b2:88:1a:
    b5:46:80:47:76:14:ae:2b:8b:3e:35:5c:ab:15:84:
    53:d9:63:2e:7f:08:4b:ec:77:db:02:45:f8:c7:46:
    58:cd:2d:f9:29:4d:96:3d:d8:6c:5d:9f:79:8a:04:
    cf:b7:3a:89:da:a9:63:9f:44:b3:83:cf:0d:70:7d:

etc...

3. generate the key for the server certificate

Now that we have our own CA, it can finally issue a certificate for our server. First we generate a 2048 bit long RSA key, which is encrypted with AES 128 and stored on the disk (yes really, again an encrypted key). The passphrase does not have to be very secret this time, because we will remove it afterwards anyway. However, OpenSSL does not allow an empty phrase:

root@linux# openssl genrsa -out serverkey.pem -aes128 2048 -days 3650
Generating RSA private key, 2048 bit long modulus
....+++
.......................................+++
e is 65537 (0x10001)
Enter pass phrase for serverkey.pem: jaja
Verifying - Enter pass phrase for serverkey.pem: jaja

Like this. Now we remove the passphrase again. Why? After all, the server service (Apache, Cyrus, etc.) must be able to read the key without your intervention. Or do you want to have to enter a password every time the server boots?

root@linux# openssl rsa -in serverkey.pem -out serverkey.pem
Enter pass phrase for serverkey.pem: jaja
writing RSA key

4. Certificate Signing Request erzeugen

Der nächste Schritt zum eigenen Zertifikat ist ein CSR. Dies muss dann nur noch von der CA signiert werden. Hier sind wieder Angaben analog zum Erstellen der CA nötig, was oft Verwirrung stiftet. Die allgemeinen Daten kann man ggfl. gleich wie oben eingeben:

root@linux#  openssl req -new -key serverkey.pem -out req.pem -nodes
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]: DE
State or Province Name (full name) [Some-State]:.
Locality Name (eg, city) []:Muenchen
Organization Name (eg, company) [Internet Widgits Pty Ltd]:Hinz und Kunz AG
Organizational Unit Name (eg, section) []:.

ATTENTION – here comes the important part: With the server certificate, the Common Name is of crucial importance. It must contain the DNS name under which the client addresses the server! If the certificate is used for an HTTPS connection to www.hinzag.eu, the Common Name must be exactly www.hinzag.eu otherwise the browser will not accept the certificate, because it will assume that it has landed on the wrong server.

Common Name (eg, YOUR name) []: www.hinzag.eu
Email Address []: adam@hinzag.eu

Other options can simply be left blank:

A challenge password []:
An optional company name []:

By now there will already be four files in our directory:

root@linux# ll
insgesamt 17
drwxr-xr-x   2 root root  168 2006-04-30 12:29 .
drwx------  12 root root  600 2006-04-30 11:54 ..
-rw-r--r--   1 root root 1212 2006-04-30 12:08 cacert.pem
-rw-------   1 root root  963 2006-04-30 12:08 cakey.pem
-rw-r--r--   1 root root 1017 2006-04-30 12:29 req.pem
-rw-r--r--   1 root root 1679 2006-04-30 12:21 serverkey.pem

5. Customise the OpenSSL configuration

Unfortunately OpenSSL does not allow you to pass all data as command line arguments. Annoyingly, you need to change some settings in the file /etc/ssl/openssl.cnf before one can sign. Open this file and adjust the following lines in the [ CA_default ] section:

/etc/ssl/openssl.cnf:dir             = .              # Where everything is kept
new_certs_dir   = $dir           # default place for new certs
private_key     = $dir/cakey.pem # The private key
RANDFILE        = $dir/.rand     # private random number file
default_days    = 3650           # how long to certify for

The default_days field is preset to 365 days, and defines the validity of the certificate. Expired certificates are also a very common problem. When the time has been exceeded, nobody recognises the certificate anymore. For this reason you can increase the lifetime to 10 years, for example, as shown in the example.

If you have not specified a state in the server certificate, you need to make the following change in [ policy_match ]:

stateOrProvinceName     = optional

Now you have to create some files:

root@linux# echo 01 > serial
root@linux# touch index.txt

6. Sign the Server Certificate
Let us come to the ceremonial conclusion – our CA now signs the certificate:

root@linux# openssl ca -in req.pem -notext -out servercert.pem
Enter pass phrase for ./cakey.pem: wrzlprmpft

...

Certificate is to be certified until Apr 27 10:45:36 2016 GMT (3650 days)
Sign the certificate? [y/n]: y


1 out of 1 certificate requests certified, commit? [y/n] y
Write out database with 1 new entries
Data Base Updated

7. Install the certificate

Where you install the certificates depends on the server service. What they all have in common: You only need the files cacert.pem, servercert.pem and serverkey.pem. The cakey.pem file is not required. It is best not to store it on the server but in a safe place on another computer.

Linux knowledge

These articles were written by the founder of Checkmk many years ago.
They are still valid though and thus we keep them on our website.
Mathias has since then developed a monitoring software called Checkmk

Find out more