Proper self-signed certificates on Debian


Generating self-signed certificates is a common task that every admin needs to do from time to time for any number of reasons. Here’s how to make an OpenSSL configuration file to generate properly formed certificates quickly.

The issue

Previously, it was only necessary to specify a common name (cn) that matched your test server and life was good. A while ago though, Google led the charge by making Chrome require SAN entries on all certificates. This meant that self-signed certificates now needed their SAN DNS.1 property specified and matched to the cn. No biggie, but nearly impossible to do via the command-line. So, that’s why a certificate request config file that you can edit and reuse is a great idea. Let’s make one.

OpenSSL configuration file

Open your favourite text editor and type/copy the following text.

default_bits = 4096
default_md = sha256
distinguished_name = dn
req_extensions = san
x509_extensions = san
prompt = no

[ dn ]
countryName = CA
stateOrProvinceName = Alberta
localityName = Calgary
organizationName = My Techie-Thoughts
CN =

[ san ]
subjectAltName = @alt_names

[ alt_names ]
DNS.1 =
DNS.2 =
DNS.3 =

The value for DNS.1 MUST match CN or the certificate will be invalid. Following that line of reasoning, if your system has no alternate names, then only list DNS.1.

I’d suggest saving this somewhere that’s easy to find and with a name that makes sense. I’m partial to naming my file /etc/ssl/selfsigned.cnf. That’s what I’ll be using throughout this post.

What everything means

Curious, aren’t you? If you’re actually not, then skip this section. If you are, then go ahead and expand the following sections!

request stanza (unlabelled)

default_bitsThis is the RSA key size we want to use. You can change this to 2048 as a minimum, but most modern systems can easily generate a 4096 bit key.
default_mdThe default digest algorithm we want to use. SHA256 is the default here in most cases. Note that Google-stuff sometimes barfs if you exceed SHA384. Run “openssl list –digest-commands” to see all your options.
distinguished_nameTells OpenSSL to read the [ dn ] section when forming this certificate’s distinguished (full) name. You can specify any name, like [ name ], for example. Just remember to update the rest of the file.
req_extensionsTells OpenSSL to read the [ san ] section when assigning extensions to our request. You can specify any name, like [ othernames ], for example. Just remember to update the rest of the file.
x509_extensionsTells OpenSSL to read the [ san ] section when assigning extensions to our certificate. Again, you can use any name just like above. In this configuration, you should be referencing the same section as above.
promptWe say ‘no’ here so that OpenSSL just reads our defaults and doesn’t bother us with prompts.

Distinguished Name (dn) stanza

countryNameThe ISO standard two-letter abbreviation for the certificate subject’s country of residence.
stateOrProvinceNameFull name of the State, Province, Canton, etc. where the certificate subject is located.
localityNameThe region/city/village/etc. where the certificate subject is located.
organizationNameThe company, organization or individual to which the certificate subject belongs.
OUThis means ‘organizational unit’ and is optional. I use ‘TESTING’ for all my test certificates. In larger companies, you may use department names like “HR”, “Finance”, etc.
CNThis MUST match the primary DNS name of your server.

Subject Alternate Name (san) stanza

In this section we just refer OpenSSL to an array list of alternate names for the subject of our certificate. In this case, I called it alt_names but you can call it anything you want. The ‘@’ just means it’s going to be an array list.

Alternate Names (alt_names) array

Here we list alternate names that our certificate’s subject answers to and should also be covered by the certificate we’re issuing. Pay attention to DNS.1 – it MUST match your certificate’s common name otherwise the certificate is invalid on face! That’s why we’re making this file in the first place since you can’t really specify SANs on the command line.

Issue the certificate and self-sign

Here’s the magic – just run this command:

openssl req -new -x509 -days 365 -nodes -out /etc/ssl/certs/mycert.crt -keyout /etc/ssl/private/mycert.key -config /etc/ssl/selfsigned.cnf

Let’s go though what that all means quickly:

reqProcess a certificate signing request.
-newCreate a new request and, since we’re not supplying a key, generate a key for us.
-x509Generate a self-signed certificate.
-daysHow long should this certificate be valid for? A year is good. Less than 90 days will generate warnings in most browsers.
-nodesDon’t encrypt the generated private key. If it’s encrypted, we need to enter a password every time we use it!
-outWhere to save the issued certificate.
-keyoutWhere to save the generated private key. Make sure you choose a safe spot!
-configTell OpenSSL to use the fancy configuration file we created in the last step!

Optional: Add to local trusted certificates

If you want your (I assume Debian-based) system to trust your certificate, it’s a good idea to add it to the trusted store that’s contained in the /etc/ssl/certs/ca-certificates.crt file. While you can just do this yourself, there is a script that makes it super easy. Follow these steps:

  1. Copy your generated self-signed certificate to /usr/local/share/ca-certificates/ and make sure it has the extension .crt
  2. Run update-ca-certificates. It should report that it imported 1 certificate.

Reusing your configuration file

Whenever you need to generate other self-signed certificates, simply change the CN parameter and update the alt_names list as necessary. Remember that DNS.1 MUST match CN or the certificate is invalid. Then run the same openssl command and generate your new certificates :-) If you need to trust the certificate, just go through the same procedure in the previous section with your new certificate.

Final thoughts

That’s it! You have a properly formed self-signed certificate you can use for all sorts of testing, etc. Remember that other systems will not trust this certificate unless you install it on them first! That’s why self-signed certificates are usually just for test purposes. Otherwise, knock yourself out getting whatever you need setup and running with your shiny new certificate.

Thanks for reading my techie-thoughts on this issue. Have any comments or suggestions? Want to add your tips? Things you want me to cover in a future article? Comment below!