76

On Ubuntu, it looks like the best place for a private key used to sign a certificate (for use by nginx) is in /etc/ssl/private/

This answer adds that the certificate should go in /etc/ssl/certs/ but that seems like an unsafe place. Do .crt files need to be kept safe or are they considered public?

Jesse Nickles
  • 250
  • 1
  • 12
Adam Nelson
  • 1,557
  • 3
  • 13
  • 12
  • 29
    You can put your `.crt` up on a Times Square billboard, if you like. – ceejayoz Jul 05 '16 at 17:57
  • I proposed to Let's Encrypt to store both cert and key into /etc/ssl/private/ https://github.com/certbot/certbot/issues/1425#issuecomment-1150116062 I'll appreciate any your feedback – Sergey Ponomarev Jun 08 '22 at 16:23

5 Answers5

56

The .crt file is sent to everything that connects; it is public. (chown root:root and chmod 644)

To add to the private key location; make sure you secure it properly as well as having it in there. (chown root:ssl-cert and chmod 640)

Raphaël
  • 135
  • 5
Shane Madden
  • 112,982
  • 12
  • 174
  • 248
  • I wonder why that directory isn't g+s by default. – Collin Anderson Sep 30 '14 at 17:43
  • 2
    It doesn't need to be; the directory is 0750, so there's no way for any users not in the group to traverse into the directory to read the files. – womble Aug 12 '15 at 20:52
  • For most of the applications I use, I see the behavior as described in the linked answer: they use the user `root` to load the certificate. But the permissions here are well explained. – SimonSimCity Jan 07 '16 at 10:36
  • 2
    Looks like ssl-cert is an invalid group name on ubuntu. Maybe it should be chown root:root instead – Atif Mar 20 '18 at 21:33
  • 1
    @Atifm The ssl-cert cert group was introduced on either 16.04 or 18.04. I can't remember which. – DylanYoung Jun 18 '19 at 13:26
  • I believe its been there since 12.04, but I'm not certain. – Atif Jun 18 '19 at 14:46
  • 1
    @DylanYoung: it is present on Ubuntu 12.04 for sure, and I believe it is created by the package `ssl-cert`, used to, perhaps among other things, create self-signed snakeoil certificates – MestreLion Jul 20 '19 at 07:36
  • @MestreLion Interesting. My old 12.04 box must have been provisioned differently somehow, as I didn't see it there. Looking at the changelogs for the ssl-cert package, I see mention since 6.04 (Dapper). – DylanYoung Jul 21 '19 at 16:39
  • @Atifm perhaps it's because you don't have the ssl-cert package installed? – DylanYoung Jul 21 '19 at 16:41
  • This won't work for non-root users, since /etc is owned by root. Setting the certs directory to ssl-cert group won't grant that group access to /etc. – Cerin Oct 26 '20 at 13:12
47

It really doesn't matter where you put them as long as you properly protect your private key file(s). The public certificate is public; no protection needed - server privileges or otherwise.

To expand on the answer, I do not use the default location /etc/ssl.
It's easier for me to keep all mine in a separate area due to backups+other reasons.

For Apache SSL, I keep mine in /etc/apache2/ssl/private or similar "root area" in /etc/apache2.

Example Setup

This post is geared toward Ubuntu (Debian) + Apache, but should work on most systems.
Just apply the permissions and update location/path in given config (apache/nginx/etc).

This answer also assumes you are NOT using LetsEncrypt/Certbot, or some automated SSL service. You have bought, or created a SSL certificate and have obtained the file bundle.

If the SSL key file(s) are protected correctly (directory & files), you will be fine. Note the notes!

Create directories:

sudo mkdir /etc/apache2/ssl
sudo mkdir /etc/apache2/ssl/private
sudo chmod 755 /etc/apache2/ssl
sudo chmod 710 /etc/apache2/ssl/private

Note:
chmod 710 supports ssl-cert group under Ubuntu.
(See comments)
Setting permission to 700 on /etc/apache2/ssl/private will also work fine.

Place SSL files:

Put the public SSL certificate(s) AND intermediate certificate(s) in:
/etc/apache2/ssl (These are *.crt files, normally)

Put the corresponding private SSL key(s) in:
/etc/apache2/ssl/private (These are *.key files, or no extension, normally)

Note: LetsEncrypt/Certbot uses the ".pem" extension for all SSL files (public, intermediate chains and private). But, you do not need to move (or protect) those files. They are already in place and protected. Just call them directly in your Apache '.conf'.

Set owner:

Note - If you do not have a ssl-cert group, just skip the 2nd line:

sudo chown -R root:root /etc/apache2/ssl/
sudo chown -R root:ssl-cert /etc/apache2/ssl/private/

Set permissions:

Public Certificate(s)

sudo chmod 644 /etc/apache2/ssl/*.crt

Private Key(s)

sudo chmod 640 /etc/apache2/ssl/private/*.key

Note:
The group permission for private key(s) is set to READ (640) due to Ubuntu ssl-cert group. Using '600' (owner only control) is the normal permission for private keys and will work fine as well.

Enable the Apache SSL module

sudo a2enmod ssl

Edit any Apache site files and enable

(see last paragraph) *

sudo nano /etc/apache/sites-available/mysiteexample-ssl.conf
sudo a2ensite mysiteexample-ssl
#             ^^^^^^^^^^^^^^^^^ <-Substitute your ".conf" filename(s)

Restart Apache2 service

sudo service apache2 restart

or

sudo systemctl restart apache2.service

Done. Test your new SSL site.

* Again this goes beyond the question, but you can copy the default Apache SSL site configuration file (sudo cp /etc/apache2/sites-available/default-ssl.conf /etc/apache2/sites-available/mysiteexample-ssl.conf) as a good starting point/example of default directives/directories normally used under a simple (Ubuntu/Debian) Apache/SSL 'conf' file. It normally points to a self-signed SSL certificate+key (snakeoil), CA bundles, as well as common directives used for a given SSL site.

After copying, just edit the new .conf file and add/remove/update it as needed with new information/paths above then execute sudo a2ensite mysiteexample-ssl to enable it. Reload/restart apache2. Test.

B. Shea
  • 959
  • 10
  • 22
  • not sure why you would suggest setting 710 for permissions for /etc/apache2/ssl/private. Setting the execute bit for the directory (for the group) without setting the read bit for the directory (for the group) doesn't make a lot of sense to me. Did you mean to set it as 750? – chriv Mar 22 '16 at 18:09
  • @chriv I just set permissions based on how I see it setup under Ubuntu default SSL area. See /etc/ssl/certs & /etc/ssl/private & ssl-certs group use. See http://stackoverflow.com/a/23408897/503621 – B. Shea Jun 11 '16 at 23:31
  • 1
    A very nicely and detailed explanation to a generic question with many possible answers. Thank you. Just to add a couple of things, your `` section in your `sites-available/mysite.conf` should include the certificates like so: `SSLEngine on` `SSLCertificateFile /etc/apache2/ssl/mysite.crt` `SSLCertificateKeyFile /etc/apache2/ssl/private/mysite.key` – George Dimitriadis Sep 29 '18 at 08:18
  • BTW - It's also possible to just combine your :80 and :443 configs in one Apache ".conf" file.I redirect anything hitting port :80 at :443/SSL anyway. It's also possible to put basic SSL settings in the .conf file and create an additional 'detailed' SSL settings file (to set ciphers used/etc for example) and just [include](https://httpd.apache.org/docs/2.4/mod/core.html#include) it in all your .conf files outside virtual areas. I use these settings to 'harden' SSL a bit and I include it in each virtual site .conf. I can get A+ at [SSL Labs](https://www.ssllabs.com/ssltest/) in this manner . – B. Shea Sep 29 '18 at 17:30
16

All the answers here seem OK, but I want to mention one thing I found is a problem... If you have to concatenate your cert with intermediates or roots to come up with a chain file, don't put that in /etc/ssl/certs, because when c_rehash is run, it may create hash symlinks to your certs due to the roots or intermediates within them.

Then later down the road if your certs have expired and you remove them, and don't know to re-run c_rehash, you may have broken hash symlinks in your /etc/ssl/certs directory, and weird things start happening when your local machine tries to connect to itself through SSL, and it can't find the roots to validate against. For example, with curl I suddenly started getting:

curl: (60) SSL certificate problem: unable to get issuer certificate

Shortly after cleaning up some old .crt and concatenated .pem files I had in /etc/ssl/certs.

Storing at least your chains somewhere else avoids this problem. I ended up making a /etc/ssl/local_certs to hold my certs and chains, so they weren't lost in the mess of CA certs you'll find in /etc/ssl/certs

barryp
  • 161
  • 1
  • 2
7

Locations are correct:

  • /etc/ssl/certs/ for .crt file
  • /etc/ssl/private for .key file

Owner:

  • root:root for /etc/ssl/certs
  • root:ssl-cert for /etc/ssl/private

Permissions:

  • 644 for .crt file
  • 600 for .key file

This will work for nginx.

4

There's not really an unsafe place if permission for the individual files/directory is set to something like chown root :0 private.key and chmod 600 private.key so that only root can read it. CSRs and certificate files are less sensitive as you say.

With those permissions the paths you mention and /usr/local/ssl should be fine.

Jonathan Ross
  • 2,173
  • 11
  • 14
  • 1
    Often, applications accessing private keys are running as non-root users. I'd suggest maintaining access for the ssl-cert group. – Shane Madden Apr 13 '11 at 16:12
  • 1
    Understood but web servers like Apache spawn a root 'parent' process and assuming nginx too this is pertinent. – Jonathan Ross Apr 13 '11 at 16:19