Introduction
The ansible.builtin.group module creates, modifies, and deletes groups on Linux systems. Every server needs groups for permission management — application service accounts, deployment users, database administrators. This module handles group creation idempotently: it only makes changes when the group doesn't exist or its properties differ.
Parameters
| Parameter | Required | Default | Description |
|---|---|---|---|
name | ✅ | — | Group name |
state | ❌ | present | present to create, absent to delete |
gid | ❌ | — | Specific GID (group ID number) |
system | ❌ | false | Create as a system group (GID < 1000) |
local | ❌ | false | Use lgroupadd/lgroupmod (for local groups when using LDAP) |
non_unique | ❌ | false | Allow duplicate GIDs |
Create a Group
---
- name: Manage groups
hosts: all
become: true
tasks:
- name: Create application group
ansible.builtin.group:
name: myapp
state: present
- name: Create group with specific GID
ansible.builtin.group:
name: deploy
gid: 2000
state: present
- name: Create system group
ansible.builtin.group:
name: monitoring
system: true
state: present
Create Multiple Groups
---
- name: Create standard groups
hosts: all
become: true
vars:
groups:
- { name: "developers", gid: 2001 }
- { name: "dbadmins", gid: 2002 }
- { name: "webmasters", gid: 2003 }
- { name: "deployers", gid: 2004 }
- { name: "monitoring", system: true }
tasks:
- name: Create all groups
ansible.builtin.group:
name: "{{ item.name }}"
gid: "{{ item.gid | default(omit) }}"
system: "{{ item.system | default(false) }}"
state: present
loop: "{{ groups }}"
Delete a Group
- name: Remove obsolete group
ansible.builtin.group:
name: oldteam
state: absent
⚠️ You cannot delete a group that is any user's primary group. Remove or reassign users first.
Add Users to Groups
The group module only manages the group itself. To add users to groups, use the ansible.builtin.user module:
---
- name: Create groups and assign users
hosts: all
become: true
tasks:
- name: Create the groups
ansible.builtin.group:
name: "{{ item }}"
state: present
loop:
- developers
- docker
- sudo
- name: Create user and add to groups
ansible.builtin.user:
name: alice
groups: developers,docker
append: true # Add to groups without removing from others
- name: Add existing user to additional group
ansible.builtin.user:
name: bob
groups: docker
append: true # CRITICAL — without append, removes from all other groups!
⚠️ The append Trap
# DANGEROUS — replaces ALL secondary groups with just "docker"
- ansible.builtin.user:
name: bob
groups: docker
# append: false (default!)
# SAFE — adds "docker" to existing groups
- ansible.builtin.user:
name: bob
groups: docker
append: true
Practical Patterns
Application Service Account
---
- name: Set up application service account
hosts: appservers
become: true
tasks:
- name: Create application group
ansible.builtin.group:
name: myapp
gid: 3000
state: present
- name: Create service user
ansible.builtin.user:
name: myapp
group: myapp
system: true
shell: /usr/sbin/nologin
home: /opt/myapp
create_home: true
- name: Set directory ownership
ansible.builtin.file:
path: /opt/myapp
state: directory
owner: myapp
group: myapp
mode: "0755"
Shared Directory with Group Access
---
- name: Set up shared project directory
hosts: devservers
become: true
tasks:
- name: Create project group
ansible.builtin.group:
name: project-alpha
state: present
- name: Add developers to the group
ansible.builtin.user:
name: "{{ item }}"
groups: project-alpha
append: true
loop:
- alice
- bob
- charlie
- name: Create shared directory with setgid
ansible.builtin.file:
path: /srv/projects/alpha
state: directory
group: project-alpha
mode: "2775" # setgid — new files inherit group
Standard Server Groups
---
- name: Create standard groups on all servers
hosts: all
become: true
tasks:
- name: Ensure standard groups exist
ansible.builtin.group:
name: "{{ item.name }}"
gid: "{{ item.gid }}"
system: "{{ item.system | default(false) }}"
state: present
loop:
- { name: "sshusers", gid: 5000 }
- { name: "sudousers", gid: 5001 }
- { name: "appdeployers", gid: 5002 }
- { name: "dbaccess", gid: 5003 }
- { name: "monitoring", gid: 5004, system: true }
- name: Restrict SSH to sshusers group
ansible.builtin.lineinfile:
path: /etc/ssh/sshd_config
regexp: "^AllowGroups"
line: "AllowGroups sshusers"
notify: Restart sshd
handlers:
- name: Restart sshd
ansible.builtin.service:
name: sshd
state: restarted
Verify Group Exists
- name: Get group info
ansible.builtin.getent:
database: group
key: docker
register: group_info
ignore_errors: true
- name: Report
ansible.builtin.debug:
msg: "{{ 'docker group exists' if group_info is succeeded else 'docker group missing' }}"
group vs user Module
| Task | Module |
|---|---|
| Create/delete a group | ansible.builtin.group |
| Set a user's primary group | ansible.builtin.user (group:) |
| Add user to secondary groups | ansible.builtin.user (groups: + append: true) |
| Check if group exists | ansible.builtin.getent |
Troubleshooting
"groupdel: cannot remove the primary group of user"
A user has this group as their primary group. Change the user's primary group first:
- name: Change user's primary group
ansible.builtin.user:
name: alice
group: users # New primary group
- name: Now delete the old group
ansible.builtin.group:
name: oldgroup
state: absent
"GID already exists"
Another group uses that GID. Either use a different GID or set non_unique: true (not recommended):
- name: Check existing GIDs
ansible.builtin.command: getent group
register: all_groups
- name: Create group with unique GID
ansible.builtin.group:
name: newgroup
gid: 3001
state: present
Group Created But User Not a Member
The group module doesn't add users. Use user with append: true:
# This ONLY creates the group — doesn't add anyone
- ansible.builtin.group:
name: docker
# This adds the user to the group
- ansible.builtin.user:
name: deploy
groups: docker
append: true
Related Articles
- Ansible user Module
- Automate Linux User Management
- File Permissions Guide
- Create Directories
- Ansible Best Practices
Conclusion
ansible.builtin.group manages group creation (state: present), deletion (state: absent), and GID assignment. Use system: true for service account groups. To add users to groups, use ansible.builtin.user with groups: and always set append: true to avoid removing the user from existing groups. The most common pattern: create a group → create a service user with that group → set directory ownership to the group.