Creating Self-Signed Certificates on Ubuntu Server


As I investigated how to set up Apache2 on Ubuntu/Debian, I found out that there were different ways of generating self-signed certificates.

I’ll try to summarise what I gathered in this post, for the sake of understanding and remembering.

Procedure 1: The Ubuntu/Debian way

On Ubuntu/Debian,there is a utility named make-ssl-cert that is a debconf to openssl wrapper whose description is available at http://man.he.net/man8/make-ssl-cert
The utility will generate a .pem file containing both a certificate and a private key

$sudo /usr/sbin/make-ssl-cert /usr/share/ssl-cert/ssleay.cnf ./myCertificate.pem

The commands needs a template (/usr/share/ssl-cert/ssleay.cnf) to generate the certificate.

The generated PEM file contains both the private key and the certificate:

—–BEGIN PRIVATE KEY—–

—–END PRIVATE KEY—–
—–BEGIN CERTIFICATE—–

—–END CERTIFICATE—–

Procedure 2: The OpenSSL way with a passphrase

To generate a self-signed certificate with OpenSSL, one must go through several steps. To generate the certificate, one needs:

  • A private key
  • A Certificate Signing Request (CSR)

To generate a private key using the RSA algorithm, run the following command:

$ openssl genrsa -des3 -out myKey.pem 2048

The command works as follows:

  • The command genrsa generates an RSA private key
  • The option -des3 encrypts the private key with triple DES
  • The option -out outputs to the provided filename
  • 2048 is the size of the private key to generate in bits

The outcome of the command will be

Generating RSA private key, 2048 bit long modulus
..........+++
...................................................+++
e is 65537 (0x10001)
Enter pass phrase for myKey.pem:
Verifying - Enter pass phrase for myKey.pem:

The key is generated in a PEM format.
The contents of the generated file looks as follows:

Here is an example
----BEGIN RSA PRIVATE KEY-----
Proc-Type: 4,ENCRYPTED
DEK-Info: DES-EDE3-CBC,B86D06044242EA6B

...
-----END RSA PRIVATE KEY-----

Caveat: As the key was used to generate a passphrase, you will have to keep it preciously. For example, when using the certificate with Apache2, the passphrase will be requested at each startup of the server.

Now that we have a private key, we have two possibilities. Either we generate the Certificate Signing Request and the Certificate in one command, or we do it with two commands

Variant a – step 1: Generate a Certificate Signing Request

Run the command:

$ openssl req -new -key myKey.pem -out server.csr

The command will request you to enter quite some information as you can see on the following output:

Enter pass phrase for myKey.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]:BE
State or Province Name (full name) [Some-State]:Brabant
Locality Name (eg, city) []:Brussels
Organization Name (eg, company) [Internet Widgits Pty Ltd]:My Company
Organizational Unit Name (eg, section) []:My Division
Common Name (eg, YOUR name) []:My Name
Email Address []:my.name@myorganisation.com

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

The contents of the generated server.csr looks like this:

-----BEGIN CERTIFICATE REQUEST-----
...
-----END CERTIFICATE REQUEST-----

Variant a – step 2: Generate the self-signed certificate based on the CSR

Run the following command to issue a certificate that will be valid for 365 days.

$ openssl x509 -req -days 365 -in server.csr -signkey myKey.pem -out myCertificate.pem

The output will look like:

Signature ok
subject=/C=BE/ST=Brabant/L=Brussels/O=My Company/OU=My Division/CN=My Name/emailAddress=my.name@myorganisation.com
Getting Private key
Enter pass phrase for myKey.pem:

The contents of the certificate file looks liks:

-----BEGIN CERTIFICATE-----
...
-----END CERTIFICATE-----

Variant b: Generate the Certificate without generating the CSR

Run the following command to issue a certificate that will be valid for 365 days. You will have to enter the data as for the CSR but none will be generated.

$ openssl req -new -x509 -key myKey.pem -out myCertificate.pem -days 365

The output will look like:

Enter pass phrase for myKey.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]:BE
State or Province Name (full name) [Some-State]:Brabant
Locality Name (eg, city) []:Brussels
Organization Name (eg, company) [Internet Widgits Pty Ltd]:My Organisation
Organizational Unit Name (eg, section) []:My Division
Common Name (eg, YOUR name) []:My Name
Email Address []:my.name@mycompany.com

Variant c: Remove the passphrase from the key

It is also possible to remove the Triple DES encryption from the key and therefore the need to input the passphrase. This requires that one knows the passphrase and that the access rights on the certificate be well set and be only readable by the root user.

$ openssl rsa -in myKey.pem -out myCertificate.pem

The output of the command looks like:

Enter pass phrase for myKey.pem:
writing RSA key

The contents of the generated PEM file looks like this:


-----BEGIN RSA PRIVATE KEY-----
...
-----END RSA PRIVATE KEY-----

Procedure 3:  The OpenSSL way without a passphrase

The procedure using OpenSSL without the passphrase differs at the key generation phase. In order to generate the private key this way, run the following command, which does not request to use Triple DES:

$ openssl genrsa -out myKey.pem 2048

The output looks like:

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

The contents of the server.key file looks like:

-----BEGIN RSA PRIVATE KEY-----
...
-----END RSA PRIVATE KEY-----

Let’s now generate the Certificate with generating an intermediate CSR

$ openssl req -new -x509 -key myKey.pem -out myCertificate.pem -days 365

The output looks like:

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]:BE
State or Province Name (full name) [Some-State]:Brabant
Locality Name (eg, city) []:Brussels
Organization Name (eg, company) [Internet Widgits Pty Ltd]:My Company
Organizational Unit Name (eg, section) []:My Division
Common Name (eg, YOUR name) []:My Name
Email Address []:my.name@mycompany.com

Setting up Apache HTTP Server with SSL support on Ubuntu/Debian


I need to set up a server to host our subversion in a secured fashion and to make it available on the Web. Therefore, I first install the Apache HTTP Server (httpd) and configure it to allow for SSL connections only.

If there are mistakes in this post, please comment. I’m eager to improve it and learn.

It took me quite some time to find some proper documentation on how to configure Apache2 on Ubuntu/Debian. I came across that interesting page on the apache Web site that pointed me to a README file: /usr/share/doc/apache2/README.Debian.gz that contains information on how to configure Apache2 on Debian.

Step 1: Install the Apache2 package

There is an Apache httpd package readily available for aptitude under the name apache2. To install it, run the following command from the terminal.

$ sudo apt-get install apache2

To test that the package was properly installed, open the following address in your browser: http://yourhostname. If the installation was successful, the browser shall display the following:

It works!

This is the default web page for this server.

The web server software is running but no content has been added, yet.

Step 2: Configure httpd to support SSL

The module mod_ssl (http://httpd.apache.org/docs/2.0/mod/mod_ssl.html) provides SSL/TLS support to httpd. It is available in the httpd installation as a part of the apache2-common package.

On Ubuntu/Debian, use the following commands to enable SSL

$ sudo a2ensite default-ssl

That yields

Enabling site default-ssl.
To activate the new configuration, you need to run:
service apache2 reload

$ sudo a2enmod ssl

That yields

Enabling module ssl.
See /usr/share/doc/apache2.2-common/README.Debian.gz on how to configure SSL and create self-signed certificates.
To activate the new configuration, you need to run:
service apache2 restart

As written, let’s restart Apache2 to apply the changes with the following command:

$ sudo service apache2 restart

That command yields the following outcome:

* Restarting web server apache2 … waiting

and restart httpd:

$ sudo /etc/init.d/apache2 restart

Which yields again:

* Restarting web server apache2 … waiting

To test that the module was properly installed, open the following address in your browser: https://yourhostname. The first time you access the page, the browser will warn you that the certificate of the site is not trusted. You can proceed and you will get to the same page as before:

It works!

This is the default web page for this server.

The web server software is running but no content has been added, yet.

Step 3: Generate a self-signed certificate

To use a self-signed certificate, the package ssl-cert must be installed, which it was on my install.

I wanted to configure my own self-signed certificate for the server and to store it in /etc/apache2/ssl. To do so, run the following command from the terminal:

$ sudo mkdir /etc/apache2/ssl
$ sudo /usr/sbin/make-ssl-cert /usr/share/ssl-cert/ssleay.cnf /etc/apache2/ssl/apache.crt

The command prompts you to enter the hostname to use in the certificate. Once done, you can now see that there is a new file in the /etc/apache2/ssl directory:

drwxr-xr-x 2 root root 4096 2011-12-16 14:40 ./
drwxr-xr-x 8 root root 4096 2011-12-16 14:12 ../
lrwxrwxrwx 1 root root 10 2011-12-16 14:40 a9630d61 -> apache.crt
-rw——- 1 root root 2685 2011-12-16 14:40 apache.crt

That last command will have generated an apache.crt file that contains both the certificate and the key. Let’s now separate that file into two files:

  • apache.pem to store the certificate
  • apache.key to store the key

I will simply copy the original apache.crt file twice, one with each name and edit each file.

$ cd /etc/apache2/ssl
$ sudo cp apache.crt apache.pem
$ sudo cp apache.crt apache.key

The apache.pem file must contain everything from the beginning line to the ending line of the certificate

-----BEGIN CERTIFICATE-----
...
-----END CERTIFICATE-----

The apache.key file must contain everything from the beginning line to the ending line of the key

-----BEGIN PRIVATE KEY-----
...
-----END PRIVATE KEY-----

Step 4: Configure httpd to use the certificate

Now, I have to configure httpd to use my new certificate. To do so, I edit the configuration with nano

$ sudo nano /etc/apache2/sites-enabled/default-ssl

We have to update the following two lines

SSLCertificateFile /etc/ssl/certs/ssl-cert-snakeoil.pem
SSLCertificateKeyFile /etc/ssl/private/ssl-cert-snakeoil.key

with the following two lines

SSLCertificateFile /etc/apache2/ssl/apache.pem
SSLCertificateKeyFile /etc/apache2/ssl/apache.key

The private key shall only be readable by root:

$ sudo chmod 600 /etc/apache2/ssl/apache.key

Let’s now restart Apache2

$ sudo /etc/init.d/apache2 restart

Step 5: Disable the HTTP port

On Ubuntu/Debian, the enabled ports are defined in /etc/apache2/ports.conf. As I want to disable the HTTP listener, I simply disable that port in that file by commenting out the following two lines:

#NameVirtualHost *:80
#Listen 80

Final test

To check that everything works fine, let’s try to access the page at http://localhost with curl

curl http://localhost
curl: (7) couldn’t connect to host

Let’s no try to access the page at https://localhost with curl -k. The -k is used to allow connections from sites without a certificate.

$ curl -k https://localhost</pre>
<h1>It works!</h1>
<pre>
This is the default web page for this server.

The web server software is running but no content has been added, yet.


That’s it.

%d bloggers like this: