This guide shows how to automate Linux user creation with Ansible. You’ll define a playbook that creates a user with a hashed password, adds your SSH key for passwordless login, and optionally hardens SSH (disable root login, restrict allowed users) and adds the user to sudoers.
Ansible is an open-source automation platform for configuration management, application deployment, and infrastructure as code. It runs on Unix-like systems and can manage Linux, macOS, and Windows targets.
Prerequisites
- Python 3 and pip on your control node (the machine where you run Ansible).
- Ansible installed (see Installing Ansible).
- SSH access to the target Linux server (e.g. as root or a user with sudo).
- passlib (for generating password hashes compatible with Linux).
Overview
- Install dependencies (Ansible and passlib).
- Generate a hashed password with passlib.
- Create the playbook (user, optional SSH key, optional SSH/sudo hardening).
- Run the playbook using an inventory file.
1. Install dependencies
Install passlib (used to generate SHA-512 hashes for the user password) and Ansible:
| |
Use pip install --user or a virtual environment if you prefer not to install globally. On many systems you can also install Ansible via the package manager (e.g. dnf install ansible-core on Fedora/RHEL).
2. Generate a hashed password
Ansible’s user module expects the password in hashed form (e.g. SHA-512). Plain text will not work. Generate a hash with Python and passlib:
| |
You’ll be prompted for the password; the command prints the hash. Example output:
| |
Copy the full hash; you’ll use it in the playbook vars.
3. Define the playbook
Start with the play definition: name, hosts, become (to run as root), and vars for the username and password hash:
| |
Then add the tasks below.
Task: Create the Linux user
Use the Ansible user module to create the user with the given name and hashed password, and add them to the wheel group (common for sudo on RHEL/Rocky/Alma):
| |
Optional: Add SSH public key for passwordless login
To log in via SSH without a password, add your public key to the user’s authorized_keys using the authorized_key module:
| |
Install the collection if needed: ansible-galaxy collection install ansible.posix.
Optional: Disable root SSH login
Restricting SSH to non-root users is a good security practice. Use lineinfile to set PermitRootLogin no in sshd_config:
| |
After this change, restart SSH (e.g. systemctl restart sshd) or add an Ansible handler so the service restarts when the config changes.
Optional: Restrict SSH to allowed users
You can limit which users can log in over SSH with AllowUsers:
| |
Optional: Add user to sudoers (passwordless sudo)
To let the user run sudo without a password prompt, add a line to sudoers. The validate option runs visudo -cf so the file is checked before saving:
| |
4. Full playbook example
Save the following as create-user.yaml (or any .yml file). Replace user1 and the password hash with your values:
| |
Note: Do not commit real password hashes or production IPs to version control. Use Ansible Vault, environment variables, or a secrets manager for sensitive values.
5. Run the playbook
Create an inventory file that defines remote-server (the host name used in the playbook). Example hosts.yaml:
| |
Modern Ansible uses ansible_host and ansible_user; older docs may show ansible_ssh_host / ansible_ssh_user, which also work.
Run the playbook:
| |
Use -v, -vv, or -vvv for more verbose output. Example recap when everything succeeds:
| |
If you changed sshd_config, restart SSH on the target (e.g. systemctl restart sshd) or add a handler in the playbook so the service restarts when the config file changes.
Summary
You installed Ansible and passlib, generated a SHA-512 password hash, and built a playbook that creates a Linux user (with optional SSH key, SSH hardening, and sudo access). Run it with ansible-playbook -i inventory create-user.yaml. For more, see the Ansible user module, authorized_key module, and lineinfile documentation.