On Linux every process runs as a particular user and every file and folder is owned by a certain user. Further, access to these files and folders are restricted by users. This shows how important it is to learn how user management is done on Linux as a normal user or an admin. Information about local users can be found in etc/passwd:

[email protected]:~$ tail -9 /etc/passwd
colord:x:121:126:colord colour management daemon,,,:/var/lib/colord:/usr/sbin/nologin
geoclue:x:122:127::/var/lib/geoclue:/usr/sbin/nologin
pulse:x:123:128:PulseAudio daemon,,,:/var/run/pulse:/usr/sbin/nologin
gnome-initial-setup:x:124:65534::/run/gnome-initial-setup/:/bin/false
gdm:x:125:130:Gnome Display Manager:/var/lib/gdm3:/bin/false
eugene:x:1000:1000:Eugene,,,:/home/eugene:/bin/bash
systemd-coredump:x:999:999:systemd Core Dumper:/:/usr/sbin/nologin
mysql:x:126:133:MySQL Server,,,:/nonexistent:/bin/false
redis:x:127:134::/var/lib/redis:/usr/sbin/nologin

The format is interpreted as follows:

username:password:uid:gid:gecos:home/dir:shell

Groups also have ID and every user belongs to a default group, User Private Group (UPG). Users can also have supplementary groups. These supplementary groups help users to have access to permissions for other files and processes. Information on groups is usually found at etc/group:

[email protected]:~$ tail -9 /etc/group
gdm:x:130:
lxd:x:131:eugene
eugene:x:1000:
sambashare:x:132:eugene
systemd-coredump:x:999:
mysql:x:133:
redis:x:134:
vboxusers:x:135:
docker:x:136:

The format is interpreted as follows:

groupname:password:GID:

You have heard of the root user. The root user is the superuser, they have all powers over the system. The root can override all powers over a file and is used to manage the system. Normally we log in as an unprivileged user then use the sudo command to gain root privileges.

As a Linux administrator, we are tasked with various tasks to manage user accounts like adding users, deleting them, etc. These tasks can be easily managed by Ansible. We will go through them using Ansible Playbook. In Ansible the user and group module helps us accomplish user management tasks. This playbook highlights various tasks.

Ansible Group module common options

  • name – name of the group
  • state – (absent/present) ensure a group is present or absent
  • gid – specify group id
  • system – (yes/no) if the group created is a system group or not

Ansible User module common options

  • name – name of the user
  • password – user’s encrypted password. Please note that the password should already been encrypted or use Ansible playbook encryption but hide the password in Ansible vault
  • update_password – (always/on_create) whether to update password or just add it once when user is created
  • uid – specify user id
  • group – specify user primary group
  • groups – add user to supplementary groups
  • append – (no/yes) when adding user to supplementary group do not/or override primary group
  • comment – set GECOS
  • shell – set default shell for the user
  • remove – remove user associated directories and files

Create/Add user and group using Ansible

Playbook, user.yml:

---
- hosts: localhost #change to your hosts
  become: yes

  vars:
    # NOTICE!!!:
    # DO NOT PUT PLAIN TEXT PASSWORDS HERE!
    # use encrypted passwords or put them in Ansible vault
    # but this is just a demo
    vaulted_password: mySecret.

  tasks:
    - name: Add a simple user called janedoe
      user:
        name: janedoe
        comment: Jane Doe

    - name: Add user anita with a password
      user:
        name: anita
        password: "{{ vaulted_password | password_hash('sha512') }}"
        update_password: on_create

    - name: Add a group called developer
      group:
        name: developer
        state: present

    - name: Add a user johndoe and add them to a group developer
      user:
        name: johndoe
        groups: developer
        append: yes

    - name: Add user jSmith and generate for them an SSH key
      user:
        name: jSmith
        generate_ssh_key: yes
        ssh_key_bits: 2048
        ssh_key_file: .ssh/id_rsa

    - name: Add user noHome with no home and set account to expire on certain date
      user:
        name: noHome
        create_home: no
        expires: 1590155615

Running the playbook, do not worry about the warning as I am running the playbook to my Ansible master as a node:

$ ansible-playbook user.yml -K
BECOME password: 
[WARNING]: provided hosts list is empty, only localhost is available. Note that the implicit localhost does not match 'all'

PLAY [localhost] *************************************************************************************************************************************

TASK [Gathering Facts] *******************************************************************************************************************************
ok: [localhost]

TASK [Add a simple user called janedoe] **************************************************************************************************************
changed: [localhost]

TASK [Add user anita with a password] ****************************************************************************************************************
changed: [localhost]

TASK [Add a group called developer] ******************************************************************************************************************
changed: [localhost]

TASK [Add a user johndoe and add them to a group developer] ******************************************************************************************
changed: [localhost]

TASK [Add user jSmith and generate for them an SSH key] **********************************************************************************************
changed: [localhost]

TASK [Add user noHome with no home and set account to expire on certain date] ************************************************************************
changed: [localhost]

PLAY RECAP *******************************************************************************************************************************************
localhost                  : ok=7    changed=6    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

Check users and groups:

[email protected]:~/Projects/Ansible/users$ tail -9 /etc/passwd
eugene:x:1000:1000:Eugene,,,:/home/eugene:/bin/bash
systemd-coredump:x:999:999:systemd Core Dumper:/:/usr/sbin/nologin
mysql:x:126:133:MySQL Server,,,:/nonexistent:/bin/false
redis:x:127:134::/var/lib/redis:/usr/sbin/nologin
janedoe:x:1001:1001:Jane Doe:/home/janedoe:/bin/sh
anita:x:1002:1002::/home/anita:/bin/sh
johndoe:x:1003:1004::/home/johndoe:/bin/sh
jSmith:x:1004:1005::/home/jSmith:/bin/sh
noHome:x:1005:1006::/home/noHome:/bin/sh

[email protected]:~/Projects/Ansible/users$ tail -9 /etc/group
redis:x:134:
vboxusers:x:135:
docker:x:136:
janedoe:x:1001:
anita:x:1002:
developer:x:1003:johndoe
johndoe:x:1004:
jSmith:x:1005:
noHome:x:1006:

Delete/Remove users using Ansible

Playbook, user_delete.yml:

---
- hosts: localhost
  become: yes
  tasks:
    - name: Remove janedoe
      user:
        name: janedoe
        state: absent
        remove: yes

    - name: Remove anita
      user:
        name: anita
        state: absent
        remove: yes

    - name: Remove developer group
      group:
        name: developer
        state: absent

    - name: Remove johndoe
      user:
        name: johndoe
        state: absent
        remove: yes

    - name: Remove jSmith
      user:
        name: jSmith
        state: absent
        remove: yes

    - name: Remove noHome
      user:
        name: noHome
        state: absent
        remove: yes

Playbook run:

[email protected]:~/Projects/Ansible/users$ ansible-playbook user_delete.yml -K
BECOME password: 
[WARNING]: provided hosts list is empty, only localhost is available. Note that the implicit localhost does not match 'all'

PLAY [localhost] *************************************************************************************************************************************

TASK [Gathering Facts] *******************************************************************************************************************************
ok: [localhost]

TASK [Remove janedoe] **************************************************************************************************************
changed: [localhost]

TASK [Remove anita] ****************************************************************************************************************
changed: [localhost]

TASK [Remove developer group] ******************************************************************************************************************
changed: [localhost]

TASK [Remove johndoe] ******************************************************************************************
changed: [localhost]

TASK [Remove jSmith] **********************************************************************************************
changed: [localhost]

TASK [Remove noHome] ************************************************************************
changed: [localhost]

PLAY RECAP *******************************************************************************************************************************************
localhost                  : ok=7    changed=6    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

There are more options for managing users on Ansible I haven’t covered everything but they are available on the Ansible documentation. You can check them out.

That’s all for today, please support us by Buying us Coffee!

More on Ansible:

How To Generate Linux User Encrypted Password for Ansible

Setup Elasticsearch Cluster on CentOS / Ubuntu With Ansible

How To Use Ansible Playbook With Vagrant up