Use Ansible to create user accounts on 200 Linux machines by defining a structured inventory, leveraging the built-in
user module for idempotent account management, and organizing credentials securely via Ansible Vault. This approach eliminates manual SSH entry errors and ensures consistent permission settings across your infrastructure.
Inventory Management Strategy
Before writing any playbooks, you must define where these 200 machines reside. A flat list is manageable for small batches, but for this scale, grouping is essential. Create an
inventory.ini file that categorizes servers by role or data center. For example, separate web servers from database nodes. This structure allows you to target specific subsets of machines during testing or deployment. You can also use dynamic inventories if your infrastructure is hosted on cloud providers like AWS or Azure, but static files are sufficient for most on-premise setups. Ensure all hosts in the inventory have SSH access configured correctly. If you encounter connection issues, check your key exchange protocols as described in our guide on
Troubleshooting kex_exchange_identification Error in Linux SSH Connection.
Core Playbook Structure
The foundation of your automation is the playbook YAML file. Start with a simple task that targets all hosts in your inventory. The primary module for this job is
user. It handles creation, modification, and deletion of users. You need to specify the username, whether to add the user to groups, and set the shell environment. Crucially, always set
state: present to ensure the user exists, and use
create_home: yes if home directories are required. Avoid hardcoding passwords in plain text within the playbook. Instead, reference variables defined elsewhere. This separation of concerns keeps your code clean and secure. When executing commands that require root privileges, ensure your control node has the necessary sudo permissions, similar to how one might manage elevated privileges in other contexts outlined in
Run Programs with Elevated Privileges: A Comprehensive Guide.
Secure Password Handling
Hardcoding passwords is a critical security risk. Ansible provides
ansible-vault to encrypt sensitive data. Generate an encrypted variable file named
vars.yml. Inside, define your password hashes rather than plaintext passwords. Use the
openssl passwd command or
htpasswd to generate SHA-512 crypt hashes. Then, run
ansible-vault create vars.yml and enter your encryption password. In your playbook, include this file using the
vars_files directive. When passing the password to the
user module, use the
password parameter with the variable. This method ensures that even if your repository is compromised, the actual credentials remain unreadable. Remember that you must unlock the vault each time you run the playbook, or automate this step using an SSH agent or CI/CD pipeline secrets.
Idempotency and Testing
Ansible is designed to be idempotent, meaning running the same playbook multiple times should not change the system state after the first successful run. Test this behavior carefully. Run the playbook against a single test host first using the
-l flag to limit execution. Verify that the user was created successfully. Then, run it again. Ansible should report "ok" for the user task without making changes. If it reports "changed," investigate why. Common causes include incorrect hash formats or missing attributes in subsequent runs. Also, consider adding tasks to verify group memberships and shell settings. This validation step prevents configuration drift over time.
Scaling and Execution
Once validated, execute the playbook against the full inventory. Use the
--forks option to parallelize tasks. By default, Ansible uses five forks, which may be too slow for 200 machines. Increase this number based on your control node's CPU capacity and network bandwidth. For example,
ansible-playbook site.yml --forks=20 can significantly reduce total execution time. Monitor the output for any failures. If a machine fails due to connectivity, Ansible will skip it by default unless you configure error handling. Review logs to identify problematic hosts. After completion, perform a spot check on random machines to confirm account existence and correct permissions.
Frequently Asked Questions
How do I delete a user instead of creating them?
Change the
state parameter in the
user module from
present to
absent. This tells Ansible to remove the specified user account from the target systems. You can also choose to remove the home directory by setting
remove: yes.
Can I use Ansible to reset existing user passwords?
Yes, simply update the
password variable in your encrypted vault file and re-run the playbook. The
user module will detect the change in the password hash and update the account accordingly.
What happens if a machine is offline during execution?
Ansible will mark the task as failed for that specific host and continue processing other machines. You can review the failure summary at the end of the run and retry only the failed hosts using the
--limit flag.
Is it safe to store SSH keys in the inventory?
Storing private keys directly in inventory files is not recommended. Instead, configure your SSH client to use key-based authentication via
~/.ssh/config or pass the private key path using the
--private-key argument when running the playbook.
How do I handle different Linux distributions?
The
user module abstracts most differences between RHEL, Debian, and Ubuntu. However, check the default shell settings. Some distributions use
/bin/sh while others use
/bin/bash. Explicitly set the
shell parameter in your task to ensure consistency across all variants.