Skip to main content

Ansible User Modules

Introduction

When managing systems at scale, one of the most common administrative tasks is user management. Creating users, assigning them to groups, managing their access, and removing accounts are essential operations for system administrators. Ansible, a powerful automation tool, offers dedicated modules specifically designed for user management that make these tasks efficient and consistent across your infrastructure.

In this guide, we'll explore the primary Ansible modules for user management:

  • user - For creating, modifying, and removing user accounts
  • group - For managing user groups
  • authorized_key - For deploying SSH public keys

These modules enable you to implement secure, consistent user management across all your systems through automation.

The user Module

The user module is the primary module for managing user accounts on remote systems. It handles creating new users, updating existing users, and removing user accounts.

Basic Syntax

yaml
- name: Create a user
user:
name: username
state: present

Key Parameters

The user module supports many parameters to define user properties:

ParameterDescription
nameUsername for the account (required)
stateWhether the account should exist or not (present or absent)
commentUser's full name or description
uidUser ID number
groupPrimary group for the user
groupsList of supplementary groups
appendWhether to add groups to user's existing groups (yes/no)
shellUser's login shell
homeHome directory path
passwordEncrypted password string
systemCreate a system account (yes/no)
create_homeWhether to create the user's home directory (yes/no)
removeRemove home directory when deleting user (yes/no)
update_passwordWhen to update passwords (always or on_create)

Practical Examples

Creating a Basic User

yaml
- name: Add user john
user:
name: john
comment: "John Smith"
shell: /bin/bash
groups: admins,developers
append: yes

This task creates a user named "john" with the full name "John Smith," assigns /bin/bash as the login shell, and adds the user to both the "admins" and "developers" groups without removing any existing group assignments.

Creating a System User

yaml
- name: Add application user
user:
name: app_user
system: yes
shell: /bin/false
home: /opt/application
create_home: yes

This example creates a system user account for running an application. System users typically have UIDs in a lower range and are not meant for login.

Setting a Password

yaml
- name: Add user with password
user:
name: secure_user
password: "{{ encrypted_password }}"

Important: Never store passwords in plaintext. The password parameter expects an already encrypted string. You can generate this using:

yaml
- name: Generate encrypted password
command: openssl passwd -salt somestring -1 "{{ user_password }}"
delegate_to: localhost
register: encrypted_pass
no_log: yes # Prevents password from being shown in logs

Removing a User

yaml
- name: Remove user
user:
name: former_employee
state: absent
remove: yes # Removes home directory

Managing Multiple Users

yaml
- name: Manage multiple users
user:
name: "{{ item.name }}"
state: present
groups: "{{ item.groups | default(omit) }}"
shell: "{{ item.shell | default('/bin/bash') }}"
loop:
- name: alice
groups: developers,testers
- name: bob
groups: developers
shell: /bin/zsh
- name: charlie

The group Module

The group module manages user groups on remote systems. While the user module can create groups implicitly, the group module offers more control over group properties.

Basic Syntax

yaml
- name: Create a group
group:
name: groupname
state: present

Key Parameters

ParameterDescription
nameGroup name (required)
stateWhether the group should exist (present or absent)
gidGroup ID
systemCreate a system group (yes/no)

Practical Examples

Creating a Basic Group

yaml
- name: Create developers group
group:
name: developers
state: present

Creating a System Group with Specific GID

yaml
- name: Create app group
group:
name: appgroup
gid: 800
system: yes

Managing Multiple Groups

yaml
- name: Set up project groups
group:
name: "{{ item }}"
state: present
loop:
- developers
- testers
- operations
- security

The authorized_key Module

The authorized_key module manages SSH authorized keys for user authentication, allowing you to control SSH access across your infrastructure.

Basic Syntax

yaml
- name: Add SSH key for user
authorized_key:
user: username
key: ssh-rsa AAAA...
state: present

Key Parameters

ParameterDescription
userUsername to add key to (required)
keySSH public key string or URL (required)
pathCustom location for the authorized_keys file
manage_dirWhether to create the .ssh directory if missing
stateWhether key should be present or absent
exclusiveRemove all other keys from the authorized_keys file

Practical Examples

Adding SSH Key from a String

yaml
- name: Add deploy key
authorized_key:
user: deployer
state: present
key: "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC... [email protected]"

Adding SSH Key from a File

yaml
- name: Add admin keys
authorized_key:
user: "{{ item }}"
state: present
key: "{{ lookup('file', '/path/to/public_keys/admin.pub') }}"
loop:
- admin
- ops

Exclusive Key Access

yaml
- name: Ensure only authorized keys are present
authorized_key:
user: secure_user
state: present
exclusive: yes
key: "{{ lookup('file', '/path/to/public_keys/secure_key.pub') }}"

This removes all other keys, ensuring only the specified key provides access.

Real-World Example: User Onboarding Playbook

Let's create a complete playbook for onboarding new team members:

yaml
---
# onboard_user.yml
- name: Onboard new team member
hosts: all
become: yes
vars_prompt:
- name: username
prompt: Enter username
private: no

- name: fullname
prompt: Enter full name
private: no

- name: team
prompt: Enter team (dev, ops, or security)
private: no

tasks:
- name: Ensure team groups exist
group:
name: "{{ item }}"
state: present
loop:
- developers
- operations
- security
- shared

- name: Set groups based on team
set_fact:
user_groups:
dev: "developers,shared"
ops: "operations,shared"
security: "security,shared"

- name: Create user account
user:
name: "{{ username }}"
comment: "{{ fullname }}"
groups: "{{ user_groups[team] }}"
shell: /bin/bash
generate_ssh_key: yes
ssh_key_bits: 4096
register: user_info

- name: Add authorized SSH key
authorized_key:
user: "{{ username }}"
key: "{{ lookup('file', 'files/ssh_keys/{{ username }}.pub') }}"
state: present
when: username in lookup('fileglob', 'files/ssh_keys/*.pub') | map('basename') | map('splitext') | map('first') | list

- name: Apply sudo privileges for ops team
copy:
dest: "/etc/sudoers.d/{{ username }}"
content: "{{ username }} ALL=(ALL) ALL"
validate: /usr/sbin/visudo -cf %s
when: team == "ops"

- name: Send welcome email
delegate_to: localhost
mail:
host: smtp.example.com
port: 25
to: "{{ fullname }} <{{ username }}@example.com>"
subject: "Welcome to the team!"
body: |
Hi {{ fullname }},

Your account has been created on our systems.
Username: {{ username }}

Your SSH key is available at: {{ user_info.ssh_key_file }}

Welcome aboard!

The IT Team

To use this playbook:

  1. Create a files/ssh_keys directory with public keys named after the users
  2. Run the playbook: ansible-playbook onboard_user.yml
  3. Enter the prompted information

Understanding User Management Workflow

The following diagram illustrates how Ansible user modules interact with the system:

Advanced Concepts

Idempotency in User Management

Ansible modules are designed to be idempotent, meaning they only make changes if necessary. For example, if you run a task to create a user that already exists, Ansible will not create a duplicate or error—it will simply verify the user exists and move on.

Managing User Passwords Securely

For secure password management, consider using Ansible Vault to encrypt sensitive variables:

bash
# Encrypt the password
ansible-vault encrypt_string 'secretpassword' --name 'user_password'

Then in your playbook:

yaml
- name: Create user with vault-encrypted password
user:
name: secure_user
password: "{{ user_password | password_hash('sha512') }}"

Temporary Access with expires Parameter

You can set an expiration date for user accounts:

yaml
- name: Create temporary contractor account
user:
name: contractor
expires: "{{ (ansible_date_time.date | to_datetime('%Y-%m-%d') + datetime.timedelta(days=30)).strftime('%Y-%m-%d') }}"

Summary

Ansible's user modules provide powerful tools for managing users and access control across your infrastructure:

  • The user module handles creating, modifying, and removing user accounts
  • The group module manages user groups
  • The authorized_key module controls SSH key-based authentication

With these modules, you can automate user management, ensure consistency, and implement security best practices across all your systems.

Exercises

  1. Create a playbook that adds three users (dev, admin, guest) with appropriate groups and permissions
  2. Modify your playbook to make it work for both Linux and BSD systems (hint: check the Ansible documentation for OS-specific parameters)
  3. Create a "user offboarding" playbook that safely removes a user account while archiving their home directory
  4. Extend the onboarding example to include additional security measures such as password complexity requirements and account expiration

Additional Resources



If you spot any mistakes on this website, please let me know at [email protected]. I’d greatly appreciate your feedback! :)