Deploying SSL private keys with Ansible

When you’re using Ansible or any other configuration management tool, you might come in contact with deploying SSL certificates sooner or later. While deploying public SSL certificates isn’t a security issue at all, the deployment of private keys become more critical – at least if you want to deploy them securely.

The problem with private keys

The word private already explains a lot, because private keys should be held private – in any case. But if you’re working in a new fancy environment with a lot of automation and configuration management in place, you might ask yourself:

How can I deploy and configure my SSL encrypted application in a most automated way?

Fortunately in Ansible there are several options available.

Option 1: Check only for file permissions

The most simple option is to skip the whole deployment of the certificates and private keys via Ansible. Instead of deploying the certificate, just make sure the files are in place and the permissions are correct:

You’ll benefit of an error message when the certificate isn’t installed while you’re deploying your application. Of course Ansible will also correct the file permissions, if you’ve installed your certificate manually and forgot to set the permissions.

Unfortunately you’ve to install the certificate manually, because it isn’t stored in the Ansible SCM repository at all.

Option 2: Copy the certificate with Ansible on-demand

However it can be annoying if you’ve to deploy several servers and everything is automated, except for the freaking certificates. So there’s a workaround with an “on-demand” task via ansible command:

With the commands above you can simply copy your certificate and private key to all the webservers out there. Depending on your ansible configuration, you might also have to use the -i (inventory) and   -s (sudo) flag.

Unfortunately you still have to copy the certificates to your Ansible control node and execute the commands manually before you’re running your application deployment play. Just make sure you delete the certificate after the deployment from your control node, or at least set the correct permissions so only authorised users can read it.

Option 3: Deploy certificates after prompting for vars

However there’s another alternative which is a mix of the options above. You still use the task from option 1, but instead of the  file module you’re using the copy module from option 2. Then instead of defining a fix src, we’re using a variable:

Then prompt the user for the certificate and private key paths in the playbook.

This is the most secure option if you’re removing the certs from your control node after the deployment. Unfortunately it’s not fully automated because you’ve to prompt the user for the paths.

Option 4: Deploy certificates via Ansible play

Of course the automated deployment of credentials or private keys would be really nice, though security is really important. You shouldn’t even think about storing credentials or private keys in an unprotected format in your config management SCM repository out there like other did. Just don’t even think about it – don’t do it – never – seriously, forget it!

Anyway if you want to use automated deployments of certificates and private keys, you might have to store them in your Ansible SCM repository as well. As I already mentioned, don’t store the unprotected! Ansible introduced the Vault in version 1.5, which is a nice piece to keep your sensitive data private. Vaults are like variable files, but they’re encrypted.

First of all, create a new vault or edit an existing one:

Now add the certificate and private keys as variables:

Make sure the vault is loaded, either via  vars_files directive in your playbook or via  include_vars statement in your role/tasks:

Install the certificate and private key via copy module:

When you now run the ansible-playbook command, you’ve to set the  --ask-vault-pass or --vault-password-file FILE CLI argument:

With the setup you can deploy certificates within your playbook. The nice thing about variable files is, that they can be stored anywhere, so you’re not forced to store everything in your Ansible SCM repository. Of course if you need your Ansible installation to be portable (i.e. for multiple control nodes) you’ve to store your vault in the repository or any other shared storage. But if you’re using only one single control node, you can store your certificate vault outside of your repository as well.


The most secure way is to keep your key really private, so options 1, 2 or 3 might be the “most secure” options. Though it can be annoying.

If you’re looking forward to deploy sensitive data like private keys via Ansible in an automated way, I’ll go with option 3. You might store your data in the Ansible SCM repository, but at least everything is encrypted.



  • Thomas Kerpe Reply

    The problem with private keys is … they are private.

    Another option is not to deploy them at all but create them and do the rest on the server.
    This approach is for sure not possible on all environments but it is sometimes a very good solution.

  • Thomas Reply

    src: ‘{{ itme.src }}’

    should be ‘{{ item.src }}’ I guess

  • JamesP Reply

    You can now ansible-vault encrypt arbitrary files so there is no need to embed the contents in variables.

  • Len Reply

    In step 4 content of certificate.yml is wrong. You need spaces:

    ssl_certificate: |


    ssl_private_key: |


    • Len Reply


      ssl_certificate: |

      ssl_private_key: |

      where S = space.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.