Use Private Certificate Authority to Sign Certificate Signing Request on Linux

I’ll assume that you created a private CA using my tutorial. I also make the following assumptions before proceeding with the tutorial.

  • OpenSSL has been installed
  • CA private key is in /home/cg/myca/private/
  • CA root certificate is in /home/cg/myca/certs/
  • CA’s config file, caconfig.cnf, is in /home/cg/myca/conf/
  • serial is in /home/cg/myca/
  • index.txt is in /home/cg/myca/

Copy CSR

You should copy/download the CSR to /home/cg/myca/csr/ directory.

Sign CSR

Then run the following command to sign it.

openssl x509 -days 3650 -CA certs/crt.ca.cg.pem -CAkey private/key.ca.cg.pem -req -in csr/csr.server1.pem -outform PEM -out certs/crt.server1.pem -CAserial serial

You’ll be asked to provide the passphrase for the CA root certificate key. The final file, crt.server1.pem, is to be sent to the person who initiated the CSR. This is the final certificate they’ll use.

Generate Certificate Signing Request on Linux

You create a CSR and have it signed by a CA before you can use a certificate. This tutorial is a continuation from my tutorial on creating a CA. However, you do not need to create a CA to generate a CSR.

Install Prerequisites

I wrote this tutorial using Fedora 18. The only prerequisite I needed was OpenSSL.

su -c 'yum install openssl'

Create Directory Structure

mkdir /home/cg/mycert

cd /home/cg/mycert/

mkdir private conf csr

We will run all commands by default in the /home/cg/mycert directory, unless stated otherwise.

Config File

vim /home/cg/mycert/conf/serverconfig.cnf

This file would serve as the config file if you wish to use it. An example file is below.

[ ca ]
default_ca = CA_default

[ CA_default ]
dir = /home/cg/mycert/
certs = $dir/certs
crl_dir = $dir/crl
database = $dir/index.txt
new_certs_dir = $dir/newcerts
certificate = $dir/certs/cacert.pem
serial = $dir/serial
#crl = $dir/crl.pem
private_key = $dir/private/cakey.pem
#RANDFILE = $dir/private/.rand
x509_extensions = usr_cert
#crl_extensions = crl_ext
default_days = 3650
#default_startdate = YYMMDDHHMMSSZ
#default_enddate = YYMMDDHHMMSSZ
#default_crl_days= 30
#default_crl_hours = 24
default_md = sha1
preserve = no
#msie_hack
policy = policy_match

[ policy_match ]
countryName = match
stateOrProvinceName = match
localityName = match
organizationName = match
organizationalUnitName = optional
commonName = supplied
emailAddress = optional

[ req ]
default_bits = 4096 # Size of keys
default_keyfile = key.pem # name of generated keys
distinguished_name = req_distinguished_name
attributes = req_attributes
x509_extensions = v3_ca
#input_password
#output_password
string_mask = nombstr # permitted characters
req_extensions = v3_req

[ req_distinguished_name ]
countryName = Country Name (2 letter code)
countryName_default = US
countryName_min = 2
countryName_max = 2
stateOrProvinceName = State or Province Name (full name)
stateOrProvinceName_default = New York
localityName = Locality Name (city, district)
localityName_default = New York
organizationName = Organization Name (company)
organizationName_default = Code Ghar
organizationalUnitName = Organizational Unit Name (department, division)
organizationalUnitName_default = IT
commonName = Common Name (hostname, FQDN, IP, or your name)
commonName_max = 64
commonName_default = CGIT
emailAddress = Email Address
emailAddress_max = 40
emailAddress_default = codeghar@example.com

[ req_attributes ]
#challengePassword = A challenege password
#challengePassword_min = 4
#challengePassword_max = 20
#unstructuredName = An optional company name

[ usr_cert ]
basicConstraints= CA:FALSE
subjectKeyIdentifier=hash
authorityKeyIdentifier=keyid,issuer:always
#nsComment = ''OpenSSL Generated Certificate''
#nsCertType = client, email, objsign for ''everything including object signing''
subjectAltName=email:copy
issuerAltName=issuer:copy
#nsCaRevocationUrl = http://www.domain.dom/ca-crl.pem
#nsBaseUrl = 
#nsRenewalUrl =
#nsCaPolicyUrl = 
#nsSslServerName =

[ v3_req ]
basicConstraints = CA:FALSE
keyUsage = nonRepudiation, digitalSignature, keyEncipherment

[ v3_ca ]
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always,issuer:always
basicConstraints = CA:TRUE
#keyUsage = cRLSign, keyCertSign
#nsCertType = sslCA, emailCA
#subjectAltName=email:copy
#issuerAltName=issuer:copy
#obj=DER:02:03

[ crl_ext ]
#issuerAltName=issuer:copy
authorityKeyIdentifier=keyid:always,issuer:always

Generate CSR

You can use the config file (serverconfig.cnf) we created in the previous step to answer a lot of the questions asked during certificate generation. Just run the following command and answer the questions. Most questions will have the default values provided in serverconfig.cnf.

openssl req -new -config conf/serverconfig.cnf -keyform PEM -keyout private/key.csr.server1.pem -outform PEM -out csr/csr.server1.pem -nodes

If you want to provide your own custom values you may run the following command instead.

openssl req -new -newkey rsa:4096 -keyform PEM -keyout private/key.csr.server1.pem -outform PEM -out csr/csr.server1.pem -nodes

You will be asked relevant questions. Following is an example output of the process.

Generating a 4096 bit RSA private key
..............................................................................++
.................++
writing new private key to 'private/key.csr.server1.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) [US]:
State or Province Name (full name) [New York]:
Locality Name (city, district) [New York]:
Organization Name (company) [Code Ghar]:
Organizational Unit Name (department, division) [IT]:
Common Name (hostname, FQDN, IP, or your name) [CGIT]:
Email Address [codeghar@example.com]:server1@example.com

Two files, key.csr.server1.pem and csr.server1.pem, will be created in $dir/private and $dir/csr directories respectively. Keep these files in a safe location and back them up.

You will submit csr.server1.pem to the CA who will sign it. The CA will sign the file and return the resulting file to you. That will be the certificate you will finally use.

Create Private Certificate Authority on Linux

This tutorial will show you how to create your own private CA or Certificate Authority. This will give you the opportunity to sign your own certificates without having to pay someone else. However, since your private CA will not be trusted by others it may prompt warnings when others use it. You will need to add your root certificate to the machines you want to trust your CA.

I had written a similar article in 2008 (Create a Certificate Authority and Certificates with OpenSSL) but this tutorial supersedes the instructions for creating CA in the older one.

Install Prerequisites

I wrote this tutorial using Fedora 18. The only prerequisite I needed was OpenSSL.

su -c 'yum install openssl'

Create Directory Structure

mkdir /home/cg/myca

cd /home/cg/myca/

mkdir private certs newcerts conf export csr

echo '01' > serial

touch index.txt

We will run all commands by default in the /home/cg/myca directory, unless stated otherwise.

Config File

vim /home/cg/myca/conf/caconfig.cnf

This file would serve as the default config file for the CA. It should look something like the following:

[ ca ]
default_ca = CA_default

[ CA_default ]
dir = /home/cg/myca/
certs = $dir/certs
crl_dir = $dir/crl
database = $dir/index.txt
new_certs_dir = $dir/newcerts
certificate = $dir/certs/cacert.pem
serial = $dir/serial
#crl = $dir/crl.pem
private_key = $dir/private/cakey.pem
#RANDFILE = $dir/private/.rand
x509_extensions = usr_cert
#crl_extensions = crl_ext
default_days = 3650
#default_startdate = YYMMDDHHMMSSZ
#default_enddate = YYMMDDHHMMSSZ
#default_crl_days= 30
#default_crl_hours = 24
default_md = sha1
preserve = no
#msie_hack
policy = policy_match

[ policy_match ]
countryName = match
stateOrProvinceName = match
localityName = match
organizationName = match
organizationalUnitName = optional
commonName = supplied
emailAddress = optional

[ req ]
default_bits = 4096 # Size of keys
default_keyfile = key.pem # name of generated keys
distinguished_name = req_distinguished_name
attributes = req_attributes
x509_extensions = v3_ca
#input_password
#output_password
string_mask = nombstr # permitted characters
req_extensions = v3_req

[ req_distinguished_name ]
countryName = Country Name (2 letter code)
countryName_default = US
countryName_min = 2
countryName_max = 2
stateOrProvinceName = State or Province Name (full name)
stateOrProvinceName_default = New York
localityName = Locality Name (city, district)
localityName_default = New York
organizationName = Organization Name (company)
organizationName_default = Code Ghar
organizationalUnitName = Organizational Unit Name (department, division)
organizationalUnitName_default = IT
commonName = Common Name (hostname, FQDN, IP, or your name)
commonName_max = 64
commonName_default = CGIT
emailAddress = Email Address
emailAddress_max = 40
emailAddress_default = codeghar@example.com

[ req_attributes ]
#challengePassword = A challenege password
#challengePassword_min = 4
#challengePassword_max = 20
#unstructuredName = An optional company name

[ usr_cert ]
basicConstraints= CA:FALSE
subjectKeyIdentifier=hash
authorityKeyIdentifier=keyid,issuer:always
#nsComment = ''OpenSSL Generated Certificate''
#nsCertType = client, email, objsign for ''everything including object signing''
subjectAltName=email:copy
issuerAltName=issuer:copy
#nsCaRevocationUrl = http://www.domain.dom/ca-crl.pem
#nsBaseUrl = 
#nsRenewalUrl =
#nsCaPolicyUrl = 
#nsSslServerName =

[ v3_req ]
basicConstraints = CA:FALSE
keyUsage = nonRepudiation, digitalSignature, keyEncipherment

[ v3_ca ]
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always,issuer:always
basicConstraints = CA:TRUE
#keyUsage = cRLSign, keyCertSign
#nsCertType = sslCA, emailCA
#subjectAltName=email:copy
#issuerAltName=issuer:copy
#obj=DER:02:03

[ crl_ext ]
#issuerAltName=issuer:copy
authorityKeyIdentifier=keyid:always,issuer:always

Thanks to http://wwwneu.secit.at/web/documentation/openssl/openssl_cnf.html for helping with this file.

Generate Root Certificate

You can use the config file (caconfig.cnf) we created in the previous step to answer a lot of the questions asked during certificate generation. Just run the following command and answer the questions. Most questions will have the default values provided in caconfig.cnf.

openssl req -new -x509 -days 3650 -config conf/caconfig.cnf -keyform PEM -keyout private/key.ca.cg.pem -outform PEM -out certs/crt.ca.cg.pem

Although we specified the default number of days in caconfig.cnf file, we still have to specify the days flag when using the x509 flag. If we don’t the certificate is created with a default value of 30 days. Thanks to Re: default_days problem and OpenSSL req(1).

If you want to provide your own custom values you may run the following command instead.

openssl req -new -x509 -days 3650 -newkey rsa:4096 -extensions v3_ca -keyform PEM -keyout private/key.ca.cg.pem -outform PEM -out certs/crt.ca.cg.pem

You will be asked for a passphrase. Make sure you use a secure passphrase and don’t forget it. You will also be asked other relevant questions. Following is an example output of the process.

Generating a 4096 bit RSA private key
..............................................................................++
...........................................................................................................................................................................................................................................++
writing new private key to 'private/key.ca.cg.pem'
Enter PEM pass phrase:
Verifying - Enter PEM pass phrase:
-----
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) [US]:
State or Province Name (full name) [New York]:
Locality Name (city, district) [New York]:
Organization Name (company) [Code Ghar]:
Organizational Unit Name (department, division) [IT]:
Common Name (hostname, FQDN, IP, or your name) [CGIT]:
Email Address [codeghar@example.com]:

Two files, key.ca.cg.pem and crt.ca.cg.pem, will be created in $dir/private and $dir/certs directories respectively. Make sure you keep these files in a secure place and make their backups.

crt.ca.cg.pem is your root certificate and will be used to sign all the other certificates.

Verify Root Certificate

You should verify that the certificate was created properly with accurate information.

openssl x509 -in certs/crt.ca.cg.pem -inform pem -noout -text

Export Root Certificate

Since this newly created CA and its root certificate are not recognized and trusted by any computer, you need to import the root certificate on all other computers. By default an OS will have a list of trusted CAs and you need to import your CA to that list. The process varies for different OSes.

Windows

The root certificate we created is in PEM encoded format. For Windows we need it to be in DER encoded format. A great resource on the differences between the two is DER vs. CRT vs. CER vs. PEM Certificates and How To Convert Them.

openssl x509 -in certs/crt.ca.cg.pem -outform der -out export/ca.cg.crt

Verify the certificate was created successfully.

openssl x509 -in export/ca.cg.crt -inform der -noout -text

Once you have the exported file, copy it to your Windows machine. You can follow the instructions provided by How To Import a Trusted Root Certification Authority In Windows to import the certificate to the Trusted Root Certification Authorities store on Local Computer.

You can also export the certificate to PKCS12 format. Thanks to Importing a User Certificate to the Windows Certificate Store for this information.

openssl pkcs12 -export -out export/ca.cg.p12 -in certs/crt.ca.cg.pem -inkey private/key.ca.cg.pem

You will be asked to provide the passphrase you used to create the root certificate. You will also be asked for a new “Export Password”.

Copy the .p12 file to Windows and double-click it. A wizard will open and guide you to install it.

Conclusion

The process to create a CA is very simple. Next I will write about signing a certificate request.

Further Reading

Create a Certificate Authority and Certificates with OpenSSL

THIS POST HAS BEEN DEPRECATED/SUPERSEDED

NOTE: I have written three new posts that supersede this post. Please read those instead of this page.

  1. Step 1: Create Private Certificate Authority on Linux
  2. Step 2: Generate Certificate Signing Request on Linux
  3. Step 3: Use Private Certificate Authority to Sign Certificate Signing Request on Linux

I’m keeping this post here since it may have been linked to by other places on the web.

ORIGINAL POST

This tutorial will assume that you are using Ubuntu 7.10 (Gutsy Gibbon). This tutorial has been adapted from Setting up OpenSSL to Create Certificates and OpenSSL – Community Ubuntu Documentation. I would recommend that you get the latest info from these resources as mine may be out of date. Both of them are very helpful. Besides, without them I would not have been able to create this one.

Install OpenSSL

sudo apt-get install openssl

Create Directory Structure

You need to create a directory structure to store files and also create some initial files. We will first create a main directory. I would recommend creating it under /home so that if you upgrade, you will have access to those files.

mkdir /home/ca /home/ca/private /home/ca/certs /home/ca/conf

cd /home/ca

echo '01' > serial

touch index.txt

Create Certificate Authority (CA)

sudo vim /home/ca/conf/caconfig.cnf

This file would serve as the default config file for the CA. It should look something like the following (taken from the Setting up OpenSSL resource), of course with your own settings:

#..................................
[ ca ]
default_ca = CA_default
[ CA_default ]
dir = /home/ca

serial = $dir/serial
database = $dir/index.txt
new_certs_dir = $dir/certs
certificate = $dir/certs/cacert.pem
private_key = $dir/private/cakey.pem
default_days = 365
default_md = md5
preserve = no
email_in_dn = no
nameopt = default_ca
certopt = default_ca
policy = policy_match
[ policy_match ]
countryName = match
stateOrProvinceName = match
organizationName = match
organizationalUnitName = optional
commonName = supplied
emailAddress = optional
[ req ]
default_bits = 1024 # Size of keys
default_keyfile = key.pem # name of generated keys
default_md = md5 # message digest algorithm
string_mask = nombstr # permitted characters
distinguished_name = req_distinguished_name
req_extensions = v3_req
[ req_distinguished_name ]
# Variable name Prompt string
#------------------------- ----------------------------------
0.organizationName = Organization Name (company)
organizationalUnitName = Organizational Unit Name (department, division)
emailAddress = Email Address
emailAddress_max = 40
localityName = Locality Name (city, district)
stateOrProvinceName = State or Province Name (full name)
countryName = Country Name (2 letter code)
countryName_min = 2
countryName_max = 2
commonName = Common Name (hostname, IP, or your name)
commonName_max = 64
# Default values for the above, for consistency and less typing.
# Variable name Value
#------------------------ ------------------------------
0.organizationName_default = My Organization
localityName_default = NEW YORK
stateOrProvinceName_default = NEW YORK
countryName_default = US
emailAddress_default = email@mydomain.net
[ v3_ca ]
basicConstraints = CA:TRUE
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always,issuer:always
[ v3_req ]
basicConstraints = CA:FALSE
subjectKeyIdentifier = hash

Generate CA Key and Certificate

Once you have the config file created the way you want, you will have to create a root (CA) key and certificate.

You will be prompted for some questions. Those questions for which you provided the default answers in your caconfig.cnf file, you do not need to enter any other information; you may just press enter key. However, the most important thing is this: Common Name should be unique, and should be the full legal name of your organization. If you are an individual, make sure it is your name. As you create more certificates, Common Name has to be unique for each of them.

You will also have to enter a passphrase. Make sure it is long, difficult, and then keep it safe. It would be awesome if you could encrypt it as well. But whatever you do, however you save it, do not, I repeat, do not lose it.

cd /home/ca/

openssl req -new -x509 -extensions v3_ca -keyout private/cakey.pem -out cacert.pem -days 365 -config conf/caconfig.cnf

Create Server Certificate

You first have to create a key and signing request, both of which can be done in the same command. You will be prompted for some questions again, and once again you have to make sure Common Name is unique. To create a server certificate, you should always choose the full domain name of the server, or its IP address. For example, if you are creating a certificate for http://www.mydomain.net, you should enter http://www.mydomain.net as Common Name. However, if you want to use the same certificate across many domains, enter *.mydomain.net as Common Name.

I also like to name the requests, keys, and certificates after the domain I will be usig them for. So let’s say you are choosing to create a certificate for http://www.mydomain.net, then

cd /home/ca/

openssl req -new -nodes -out http://www.mydomain.net.req.pem -keyout private/www.mydomain.net.key.pem -config conf/caconfig.cnf

Next you have to sign this request to create a certificate. It will ask you to enter the passphrase chosen when creating the root key. So just enter it.

openssl ca -out certs/www.mydomain.net.cert.pem -config conf/caconfig.cnf -infiles http://www.mydomain.net.req.pem

You can use this certificate in your server applications now.

Create Client Certificate

Creating a client certificate, such as for your web browser, is similar to creating one for a server. One can use client certificates to identify clients, and also to authenticate them.

For Common Name, you should choose the name of the client. If it is an individual, their full name, or if it’s an organization then its full name. For more details, check out the details under Create Server Certificate.

cd /home/ca/

openssl req -new -nodes -out myfriend.req.pem -keyout private/myfriend.key.pem -days 365 -config conf/caconfig.cnf

Similarly, you have to sign this request with the root key. Again, details are provided under Create Server Certificate.

openssl ca -out certs/myfriend.cert.pem -days 365 -config conf/openssl.cnf -infiles myfriend.req.pem

Set up Apache 2.0 with SSL

Please read my guide titled Apache 2.0 in Ubuntu for a detailed guide.

Get Certificates from CAcert

If you do not wish to pay for certificates, check out CAcert. They are aiming to become a well-recognized CA which gives free certificates. It would be better than creating your own as it will be much more secure and you would not have to pay any money.

Hat Tips

Other very good guides and resources are: Client Authentication with SSL; subjectAltName setup;

Apache 2.0 in Ubuntu

This post will deal with setting up a web server in Ubuntu using Apache 2.0. I will not be able to cover every scenario but I hope I can cover the most common ones. Default paths and so on are based on Ubuntu 7.10, Gutsy Gibbon.

Install Apache

sudo apt-get install apache2

Make sure it has been installed and is working properly by going to the server’s IP address using any web browser.

Custom Configurations

Since Apache allows you to include other files for configuration, it might be a good idea to create a file with all your custom configurations in it. Then you just have to save that file and use it whenever needed without messing around with the default configurations.

sudo mkdir /etc/apache2/customconfig/

sudo touch /etc/apache2/customconfig/server.conf

And then add the following line to /etc/apache/apache2.conf

Include /etc/apache2/customconfig/

And from then on all custom configurations will be loaded by Apache.

Give Apache a Server Name

Check that the configuration files have a server name or not.

grep -n ServerName /etc/apache2/apache2.conf

grep -n ServerName /etc/apache2/httpd.conf

grep -n ServerName /etc/apache2/ports.conf

Usually, if a server name has not been set, Apache will complain when you start it. So just add a server name to your config file. If you have created a custom config file, such as server.conf above, just add the following line

sudo vim /etc/apache2/customconfig/server.conf

If you haven’t created a custom config file, add the following line to the main config file

sudo vim /etc/apache2/apache2.conf

And add the line:

ServerName localhost

Now when you restart Apache, it will not complain that it doesn’t have a server name.

Listen on Ports

You need to make sure that Apache is listening on at least two ports: 80 (HTTP) and 443 (HTTPS). Your /etc/apache2/ports.conf file should look something like this:

Listen 80
<IfModule mod_ssl.c>
Listen 443
</IfModule>

Create Site

To create a site, you first have to decide where to store the files. I like to store them under my home directory, with read access to the user under which Apache runs, which is more likely than not www-data in Ubuntu.

mkdir /home/me/web/ /home/me/logs/

sudo chown -R www-data /home/me/logs/

chmod g+rwx /home/me/logs

VirtualHost Configuration

Since I may need to host more than one sites on the server, I want to use VirtualHost and its associated settings. I prefer to keep separate files for each virtual host.

sudo cp /etc/apache2/sites-available/default /etc/apache2/sites-available/sitedomain

sudo vim /etc/apache2/sites-available/sitedomain

And then get to editing the file. After editing, my first virtual host config looks like this:

NameVirtualHost *:80
<VirtualHost *:80>
ServerName mydomain.com
DocumentRoot /home/me/web/
ErrorLog /home/me/logs/error.log
</VirtualHost>

Enable New Site

After creating the config file for new web site, you need to enable it.

sudo a2ensite sitedomain

But to use it, you must also disable the default site

sudo a2dissite default

Next you have to reload configurations in Apache

sudo /etc/init.d/apache2 reload

Now when you navigate to the server, it will show your new site.

Install SSL

Make sure apache has SSL module available into it:

ls /etc/apache2/mods-available | grep ssl.conf

ls /etc/apache2/mods-available | grep ssl.load

Install OpenSSL and ssl-cert

sudo apt-get install openssl ssl-cert

Your Ubuntu installation may not have one critical piece of software: apache2-ssl-certificate. You may download it from Launchpad (apache2-ssl) and do the following steps (instructions courtesy of Apache2-SSL-Certificate for Ubuntu Feisty..How to install this missing script to get the SSL certificates up):

cd ~/

wget http://librarian.launchpad.net/7477840/apache2-ssl.tar.gz

tar xvzf apache2-ssl.tar.gz

sudo mv ssleay.cnf /usr/share/apache2/

sudo mv apache2-ssl-certificate /usr/sbin

sudo mkdir /etc/apache2/ssl

Now you may proceed with the next steps.

Configure SSL

First you have to generate an SSL certificate.

sudo apache2-ssl-certificate -days 365

It started asking a bunch of questions and here are sample answers:

Country name: US
State: New York
Locality: New York
Organization Name: My Organization
Organizational Unit Name: .
Server name: ssl.mysite.net
Email: myemail@mysite.net

To enable the SSL module in Apache, run the following

sudo a2enmod ssl

Site Configuration

Your virtual host config will change and be something like:

NameVirtualHost *:80
<VirtualHost *:80>
ServerName mydomain.com
DocumentRoot /home/me/web/
ErrorLog /home/me/logs/error.log
</VirtualHost>
NameVirtualHost *:443
<VirtualHost *:443>
ServerName mydomain.com
DocumentRoot /home/me/web/
ErrorLog /home/me/logs/error.log
SSLEngine On
SSLCertificateFile /etc/apache2/ssl/apache.pem
</VirtualHost>

Now you may navigate your site without problems.

Configure SSL with OpenSSL

If you want to use OpenSSL to create and maintain your certificates, and also use them with Apache, read my guide titled Create a Certificate Authority and Certificates with OpenSSL. Once you have created server certificates, you have to make just a few changes in your virtual host config: location of the key and certificate files. For example, your config file might now look like

NameVirtualHost *:80
<VirtualHost *:80>
ServerName mydomain.com
DocumentRoot /home/me/web/
ErrorLog /home/me/logs/error.log
</VirtualHost>
NameVirtualHost *:443
<VirtualHost *:443>
ServerName mydomain.com
DocumentRoot /home/me/web/
ErrorLog /home/me/logs/error.log
SSLEngine On
SSLCertificateFile /home/ca/certs/mydomain.com.cert.pem
SSLCertificateKeyFile /home/ca/private/mydomain.com.key.pem
SSLCACertificateFile /home/ca/certs/cacert.pem
</VirtualHost>

Redirect Traffic to SSL

And if you want to redirect all your port 80 traffic to the secure, SSL-enabled part of your web server, you first have to enable the Rewrite engine

sudo a2enmod rewrite

Then you have to enable it in your virtual host configuration and change it to

NameVirtualHost *:80
<VirtualHost *:80>
ServerName mydomain.com
DocumentRoot /home/me/web/
ErrorLog /home/me/logs/error.log
RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI}
</VirtualHost>
NameVirtualHost *:443
<VirtualHost *:443>
ServerName mydomain.com
DocumentRoot /home/me/web/
ErrorLog /home/me/logs/error.log
SSLEngine On
SSLCertificateFile /home/ca/certs/mydomain.com.cert.pem
SSLCertificateKeyFile /home/ca/private/mydomain.com.key.pem
SSLCACertificateFile /home/ca/certs/cacert.pem
</VirtualHost>

Now all traffic on regular port will be redirected to secure port.

Access Using Client Certificates

If you want only selected people to be able to browse your website, you can create certificates for clients and set Apache to only allow them access. To create client certificates, read my guide titled Create a Certificate Authority and Certificates with OpenSSL.

On the Apache side, you have to change your virtual host config and make it look something like:

NameVirtualHost *:80
<VirtualHost *:80>
ServerName mydomain.com
DocumentRoot /home/me/web/
ErrorLog /home/me/logs/error.log
RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI}
</VirtualHost>
NameVirtualHost *:443
<VirtualHost *:443>
ServerName mydomain.com
DocumentRoot /home/me/web/
ErrorLog /home/me/logs/error.log
SSLEngine On
SSLCertificateFile /home/ca/certs/mydomain.com.cert.pem
SSLCertificateKeyFile /home/ca/private/mydomain.com.key.pem
SSLCACertificateFile /home/ca/certs/cacert.pem
<Directory /home/me/web>
SSLVerifyClient require
SSLVerifyDepth 1
</Directory>
</VirtualHost>

Hat Tips

To be honest, my starting point was Ubuntu LAMP Server Guide, from where I took steps and then added more details where I thought they were needed.

Also helpful were: Apache2 SSL in Ubuntu; Apache2-SSL-Certificate for Ubuntu Feisty..How to install this missing script to get the SSL certificates up; SSL FAQ;