Ansible: Generate Crypted Passwords for the User Module

The user module can be used to create user accounts and set passwords.

The Problem

How to use the user module to set passwords for Linux accounts? This is something that took me a while to figure out. Luckily, there is a reference to Ansible FAQ in ansible-doc.

The Solution: Hashing Filters

The answer is taken from Ansible FAQ. To get a sha512 password hash with random salt, we can use the following:

{{ 'password' | password_hash('sha512') }}

Let us store the plaintext password in Ansible vault:

$ ansible-vault view my_vault.yml
Vault password: 
my_password: myPlaintextPassword

Our playbook that uses the vault file my_vault.yml will look something like this:

---
- name: Create New Users
  hosts: all
  become: true
  gather_facts: false
  vars_files:
    - my_vault.yml
  tasks:
    - name: Create Users
      user:
        name: "{{ item }}"
        password: "{{ my_password | password_hash('sha512') }}"
        shell: /bin/bash
      loop:
        - alice
        - vincent

Note that while the playbook does the job, it’s not idempotent. The password hash will be generated every time the playbook is run, and the /etc/shadow file will be updated.

To make the playbook idempotent, set update_password: on_create. This will only set the password for newly created users.

---
- name: Create New Users
  hosts: all
  become: true
  gather_facts: false
  vars_files:
    - my_vault.yml
  tasks:
    - name: Create Users
      user:
        name: "{{ item }}"
        password: "{{ my_password | password_hash('sha512') }}"
        shell: /bin/bash
        update_password: on_create
      loop:
        - alice
        - vincent

14 thoughts on “Ansible: Generate Crypted Passwords for the User Module

  1. Hello, how can i do it for several users?. Same playbook for more users eachone with a different password?.

    I’m trying to do it, but i have problem with the variables.

    • You can do this by just creating a dictionary of users with their passwords, then vaulting that and referring to that in a loop.

      To chew it out:
      my_vault.yml:

      my_users:
      alice: secretpassword123
      vincent: vincentspassword456

      Then ansible-vault encrypt that file and run the above play, with the task modified to loop through all the users and passwords:

      – name: Create users, each with a unique password
      user:
      name: “{{ item.key }}”
      password: “{{ item.value | password_hash(‘sha512’) }}”
      shell: /bin/bash
      update_password: on_create
      loop: “{{ my_users | dict2items }}”

      (Note: code is untested but should function)

    • Vault encrypted and idempotent approach:

      – name: Setting default root password
      ansible.builtin.user:
      name: root
      password: “{{ PASSWORD_VAR | string | password_hash(‘sha512’, 65534 | random(seed=inventory_hostname) | string)}}”

  2. update_password: on_create
    is not the best choice. If you already have a user and want to change its password, your playbook won’t change it, because you can change password only when you create a user.
    I found solution from https://docs.ansible.com/ansible/latest/user_guide/playbooks_filters.html, but it’s hard to remember:
    password: “{{ my_password | password_hash(‘sha512’, 65534 | random(seed=inventory_hostname) | string) }}”
    I’d like to understand this expression, but there is no explanation in document. If you can explain, please do it.

    • Thanks, I’m aware of that. If you want to change the password every time, you can set it to “always”. Keep in mind that your playbook will no longer be indepotent.

  3. There is a nice one-line ad-hoc command for doing this as well:

    ansible localhost -m debug -a msg=”{{ ‘yourpasswordhere’ | password_hash(‘sha512’) }}”

    Of course, make sure to remove the line from your history afterwards.

Leave a Reply

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