Changing your SSH keys is as important as changing your underpants daily, running this script on a frequent basis will ensure access to the servers are changed on a regular basis. Use Ansible to do ssh key rotation in your sleep!

Test Bed

  • Ansible control server running Ubuntu 18.04 LTS
  • Test server running Ubuntu 18.04 LTS


  1. Ansible control server
  2. SSH keys established between Ansible control server and destination server(s)
  3. A folder called “pubkeys” where the script is running from

Break Down

  1. Creates a new directory on the remote server to generate the new keys on
  2. Generates the new key pair in the newly formed folder
  3. Copies the new public key to the local machine running the ansible script under /pubkeys/ and names it “id_rsa.%hostname%.pub
  4. Removes existing private key
  5. Removes existing public key
  6. Moves new private key to the users .ssh folder
  7. Moves new public key to the users .ssh folder
  8. Changes new private key to read only
  9. Invalidates existing keys and applies the public key copied to the local host to the server
  10. Copies the new private key local host and changes the file to “id_rsa.%hostname%
  11. Removes “newsshkey” folder on remote host as a clean up


- hosts: test
  - name: Creates directory
      path: ~/.ssh/newsshkey
      state: directory
  - name: Create New SSH Key Pair
    command: ssh-keygen -f id_rsa -t rsa -N '' -f ~/.ssh/newsshkey/id_rsa
  - fetch:
      src: ~/.ssh/newsshkey/id_rsa.pub
      dest: pubkeys/{{ inventory_hostname }}.pub
      flat: yes
  - name: Remove Old Keys
    command: rm -rf ~/.ssh/id_rsa
  - name: Remove Old Pub Key
    command: rm -rf ~/.ssh/id_rsa.pub
  - name: Move New Key
    command: mv ~/.ssh/newsshkey/id_rsa ~/.ssh/
  - name: Move New Pub Keys
    command: mv ~/.ssh/newsshkey/id_rsa.pub ~/.ssh/
  - name: Change id_rsa Permissions
    command: chmod 400 ~/.ssh/id_rsa
  - name: Set authorized key, removing all the authorized key already set
      user: root
      key: '{{ item }}'
      state: present
      exclusive: True
      - pubkeys/{{ inventory_hostname }}.pub
  - fetch:
      src: ~/.ssh/id_rsa
      dest: ~/.ssh/id_rsa.{{ inventory_hostname }}
      flat: yes
  - name: Removing existing folder
      path: ~/.ssh/newsshkey
      state: absent

Note: You will need to change/remove the “- hosts:” entry

Key Management

To fully automate this I have mounted a cifs share and created a symbolic link on the Ansible server from the ~/.ssh folder to the cifs share. All my other clients are set up the same way so when you update the key it copies the key to a central repository which all other clients are symbolically linked to.


This can be greatly be improved on but is a good starting point in the rotation of your ssh keys. I’m happy to hear suggestions on how this could be improved.

7 Responses to “Automate SSH Key Rotation on Ubuntu with Ansible”

  1. abe

    Although this works on the key creation on the remote server, the local machine has to able to login with new keys generated. You will have to cp the new private key from remote machine to local machine, else you are locked out from that machine

    • Chris

      Thanks for your comment and suggestion. The last “fetch” statement covers this off and places the id_rsa.{{ hostname }} file in the root of the users .ssh folder.

      • abe

        That’s right. Ran this code; it works fine for one instance at a time. How about multiple instances(a fleet of 1000+ instances) that would create multiple keys. Then I would have to pass the vars in the hosts ini file which would not work per group because it creates one key per instance. I can only define one ansible_ssh_private_key_file per group. So, I am looking into ways on how to automate for multiple instances with its keys and run it as a monthly rotation task

        • Chris

          If I understand your question – you only want to specify one private key. If so, you can combine the keys on the ansible server (place after the last fetch command):

          - name: combine priv keys
          local_action: cat ~/.ssh/id_rsa.{{ hostname }} >> ~/.ssh/id.rsa

          • abe

            Another thought is create the key locally with local_action and then upload it to all the servers to the authorized_users file. So that way it would make sure, on every run the key is only created once?

            Also, another scenario is create one key for all instances in a group from hosts.ini.

            Here is a hosts.ini file:





  2. Abe

    I take it back. I am trying to implement more secure method. The admin user will have one key per instance. For 100 instances, I need to maintain 100 respective keys. These keys will be rotated on a frequency monthly or quarterly. I appreciate your responses. I think your solution above for the implementation I’m looking maybe not be perfect fit unless you have other suggestions

    • Chris

      I wouldn’t recommend using the same key – one breach of the key will allow access to every guest. The solution written up rotates keys for multiple guests if you specify a host group which can be defined in /etc/ansible/hosts


Leave a Reply

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

Time limit is exhausted. Please reload CAPTCHA.