When configuring a new server with Ansible, I wanted to create a new user, then switch to that new user for the remainder of the playbook. As with any Ansible playbook, it should be idempotent. The way to do accomplish this was not straightforward, due to the way the Ansible SSH user behaves.
The playbook layout
There are two roles: maybecreateuser
and createuser
.
The maybecreateuser
role wraps the createuser
with logic to test if the user exists and to handle the variable setup required to swap ansible_user
. The createuser
role contains the user creation tasks.
Testing if the user exists
Key points:
- Stash the
ansible_user
into another variable, before swapping in the value ofinitial_user
.initial_user
is a variable defined by this role and should be the name of the initial root user on the server. - Test if the user already exists by trying to SSH explicitly
Creating the user
- Create a user with no password set, to avoid dealing with password handling
- Copy the
~/.ssh/authorized_keys
file frominitial_user
, in order to SSH in as this new user. This assumes yourinitial_user
has anauthorized_keys
file already (this is true on DigitalOcean if you provide your pubkey before creating the server). - Give the user sudo rights without a password
None of these are hard requirements. You may want your user to have a password and not give it nopasswd
sudo. You may want to use a different SSH key.
Using it in a playbook
When using the maybecreateuser
role, gather_facts: no
must be set in the playbook. Otherwise, ansible will try to do gather_facts
which requires an SSH connection, but the ansible_user
might not exist yet.
Configuring inventory
Pass the initial_user
if necessary to configure hosts whose initial user is not root
.
Set the ansible_user
to whatever you want, or don’t set it.