Introduction
The chgrp failed: failed to look up group error occurs when Ansible tries to set a file's group ownership to a group that doesn't exist on the remote host. This commonly happens with the file, copy, template, and unarchive modules.
The Error
- name: Create config file
ansible.builtin.copy:
src: app.conf
dest: /etc/myapp/app.conf
owner: myapp
group: myapp
fatal: [web01]: FAILED! => {"changed": false, "msg": "chgrp failed: failed to
look up group myapp", "path": "/etc/myapp/app.conf"}
Root Cause
Ansible runs chgrp on the remote host to set file group ownership. The error means the specified group doesn't exist on that host. Common causes:
| Cause | Example |
|---|---|
| Group not created yet | Playbook sets file group before creating the group |
| Typo in group name | group: wwww-data instead of www-data |
| Different group names across distros | apache (RHEL) vs www-data (Debian) |
| NIS/LDAP not configured | Centralized group not available on this host |
| User created without matching group | useradd -N skips creating private group |
Fix 1: Create the Group First
- name: Create application group
ansible.builtin.group:
name: myapp
state: present
- name: Create application user
ansible.builtin.user:
name: myapp
group: myapp
system: true
- name: Create config file
ansible.builtin.copy:
src: app.conf
dest: /etc/myapp/app.conf
owner: myapp
group: myapp
Task order matters — always create groups/users before setting file ownership.
Fix 2: Verify Group Exists
- name: Check if group exists
ansible.builtin.command: getent group myapp
register: group_check
failed_when: false
changed_when: false
- name: Create group if missing
ansible.builtin.group:
name: myapp
state: present
when: group_check.rc != 0
Manual Verification on Remote Host
# Check if group exists
getent group myapp
# myapp:x:1001:
# List all groups
cat /etc/group | grep myapp
# Check user's groups
groups myapp
# myapp : myapp wheel
# Detailed user info
id myapp
# uid=1001(myapp) gid=1001(myapp) groups=1001(myapp),10(wheel)
Fix 3: Handle Cross-Platform Group Names
- name: Set platform-specific group
ansible.builtin.set_fact:
web_group: "{{ 'www-data' if ansible_os_family == 'Debian' else 'apache' }}"
- name: Deploy web config
ansible.builtin.template:
src: vhost.conf.j2
dest: /etc/httpd/conf.d/mysite.conf
owner: root
group: "{{ web_group }}"
mode: '0644'
Common Group Name Differences
| Service | RHEL/CentOS | Debian/Ubuntu |
|---|---|---|
| Apache | apache | www-data |
| Nginx | nginx | www-data |
| PostgreSQL | postgres | postgres |
| Docker | docker | docker |
| Nobody | nobody | nogroup |
Fix 4: Add Users to Groups
# Add user to existing group
sudo usermod -a -G wheel devops
# Verify
groups devops
# devops : devops wheel
id devops
# uid=1001(devops) gid=1001(devops) groups=1001(devops),10(wheel)
With Ansible:
- name: Add deploy user to docker group
ansible.builtin.user:
name: deploy
groups: docker
append: true # Don't remove from existing groups
Complete Example: Application Deployment
---
- name: Deploy application with proper ownership
hosts: app_servers
become: true
vars:
app_user: myapp
app_group: myapp
app_dir: /opt/myapp
tasks:
- name: Create application group
ansible.builtin.group:
name: "{{ app_group }}"
system: true
- name: Create application user
ansible.builtin.user:
name: "{{ app_user }}"
group: "{{ app_group }}"
system: true
home: "{{ app_dir }}"
shell: /sbin/nologin
- name: Create application directories
ansible.builtin.file:
path: "{{ item }}"
state: directory
owner: "{{ app_user }}"
group: "{{ app_group }}"
mode: '0755'
loop:
- "{{ app_dir }}"
- "{{ app_dir }}/config"
- "{{ app_dir }}/logs"
- "{{ app_dir }}/data"
- name: Deploy configuration
ansible.builtin.template:
src: app.conf.j2
dest: "{{ app_dir }}/config/app.conf"
owner: "{{ app_user }}"
group: "{{ app_group }}"
mode: '0640'
notify: restart myapp
handlers:
- name: restart myapp
ansible.builtin.systemd:
name: myapp
state: restarted
Debugging Checklist
- Does the group exist? →
getent group <name>on remote host - Typo? → Compare group name in playbook vs
/etc/group - Task order? → Group creation must come before file operations
- Cross-platform? → Use
ansible_os_familyfor conditional group names - LDAP/NIS? → Check
nsswitch.confand network connectivity - SELinux? → Check
ls -laZfor SELinux context issues
Related Articles
- Change File Permissions: file Module
- Copy Files to Remote: copy Module
- Ansible Privilege Escalation
- Ansible Best Practices Guide
Conclusion
The chgrp failed error means the group doesn't exist on the remote host. Fix it by creating the group with ansible.builtin.group before any file operations, verify with getent group, and handle cross-platform differences with ansible_os_family conditionals. Always structure playbooks with group/user creation tasks before file ownership tasks.