Use Ansible to (re)define root and first user password?


I’m currently writing an Ansible playbook with roles to setup a series of public Dedibox servers at Scaleway.

Rocky Linux 8 is installed on these (bare metal) servers via a web interface that only allows setting password for up to 15 characters.

Now I’d like to write a little playbook that redefines passwords for root as well as the initially created user called microlinux.

I already know how to handle sensible data using Ansible Vault, but I wonder what is the recommended “best practice” for managing sensible passwords with the ansible.builtin.user module.

Let’s say I have a machine

I would create a host_vars/sd-123456/vars.yml file like this:

passwd_root: my_super_secret_root_password
passwd_microlinux: my_super_secret_microlinux_password

Then I would encrypt this file using the ansible-vault encrypt command.

And then somewhere in the playbook I would use these variables like this:

- name: Set password for root
    name: root
    password: "{{passwd_root}}"

And then a similiar stanza for the microlinux user.

Does this look correct to you ? Or is there maybe a simpler way to do this ?


the password value in the variable will need to be encrypted.

This seems to show a few examples on how to encrypt it: bash - Creating a new user and password with Ansible - Stack Overflow

Best one I’ve used is:

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

so for yours would be:

password: "{{ passwd_root  | password_hash('sha512') }}"

notice the lack of quotes around passwd_root, that is because yours is a variable. If you were to put the password here without using a variable, then the single quotes would be required eg: ‘password’

1 Like

I tried the last example, which worked BUT I get a big fat deprecation warning:

[DEPRECATION WARNING]: Encryption using the Python crypt module is deprecated. 
The Python crypt module is deprecated and will be removed from Python 3.13. Install 
the passlib library for continued encryption functionality. This feature will be removed 
in version 2.17. Deprecation warnings can be disabled by setting 
deprecation_warnings=False in ansible.cfg.

And I have no idea what to do here. Unfortunately this is very poorly documented even in the official documentation. Judging from various forum and blog posts, you have to be a member of some secret society to perform an action like setting a password with Ansible. :upside_down_face:

For now it’s working, so you can use it. For the future though it will need to be changed to the new method.

Try installing python3-passlib for starters, as that will be required.

This: properly support passlib module in password_hash · Issue #17266 · ansible/ansible · GitHub seems to hint that installing the python package should be enough.

I installed the python3-passlib package from EPEL on the Ansible control host and ran the playbook again, but to no effect. I still get the same deprecation warning.

On a side note, I just stumbled over a nice hack that makes password definition idempotent:

- name: Set password for root
    name: root
    password: >-
      {{passwd_root | 
        password_hash('sha512', 65534   |
        random(seed=inventory_hostname) |
        string) }}

- name: "Configure admin user: microlinux"
    name: microlinux
    groups: wheel
    password: >-
      {{passwd_microlinux | 
        password_hash('sha512', 65534   |
        random(seed=inventory_hostname) |
        string) }}

Works like a charm.

As for python3-passlib, I simply kept deprecation_warnings = false in ansible.cfg. The current function is still supported until Python 3.13, so I’ll cross that bridge when I get there.

You’ll need on all the hosts that you connect to as well. The playbook is ran on each of the servers you connect to. So python3-passlib needs to be installed there also.

Nope, still no luck. Installed python3-passlib on the controller and all the hosts, and I still get the deprecation warning. I’m puzzled.

Same version of ansible on the controller and all the hosts? Assuming there is no ansible mixmatch in between. Or python differences.

I sometimes had deprecated things popup on my Fedora control host, then compared to a Debian 11 control host - due to ansible versions. So if something like this, the deprecation can be ignored for now.

1 Like

I defined the root password as an encrypted group var and call this task to set it:

- name: Set password for root |
    echo 'root:{{ root_password | default('*') }}' | chpasswd --encrypted
  become: true