Linux groups are named collections of user accounts that share a common set of permissions. Every file has an associated group, and the group permission bits control what members of that group can do with the file. Groups enable controlled sharing — a file can be readable and writable by specific users (via group membership) without being accessible to everyone. Each user has one primary group and can belong to multiple supplementary groups, each granting access to different resources.
The Middle Ground of Linux Permissions
The Linux permission system gives every file three sets of access controls: one for the file’s owner, one for a specific group, and one for everyone else. The owner and “everyone else” categories are self-explanatory — but groups are where the real power of Linux’s multi-user access control lives.
Groups solve a fundamental problem in multi-user systems: how do you share access to files and resources with a specific set of users, without making those resources available to everyone? The owner-only model is too restrictive — if only the owner can write a file, collaboration requires constant permission changes or copying. The world-readable model is too permissive — making files accessible to all users destroys privacy and security. Groups provide the middle ground: a named, managed set of users who share access to specific resources.
Every practical Linux system uses groups extensively. The sudo group controls who can run administrative commands. The docker group controls who can manage containers. The www-data group controls which processes can read web server files. The audio and video groups control hardware access. Custom groups like developers or accounting organize teams around shared project resources.
This article explains what groups are at a technical level, how primary and supplementary groups work, how group permissions integrate with the file permission system, how to create and manage groups, and the practical patterns for using groups to create sensible, secure multi-user environments.
What Groups Are: The Technical Foundation
Groups as Identity Collections
A group in Linux is, at its simplest, a named list of user accounts identified by a numeric Group ID (GID). When a user belongs to a group, they inherit that group’s access to any files where the group permission bits apply.
Groups are stored in /etc/group. Each line defines one group:
$ cat /etc/group
root:x:0:
daemon:x:1:
...
sudo:x:27:sarah,alice,bob
audio:x:29:sarah,pulse
video:x:44:sarah
docker:x:998:sarah,alice
developers:x:1001:sarah,alice,bob,carol
sarah:x:1000:
Each colon-separated line contains:
- Group name — the human-readable identifier (
developers) - Group password —
xmeans the password is in/etc/gshadow(rarely used; group passwords are an obscure feature) - GID — the numeric Group ID (
1001) - Member list — comma-separated usernames of group members (
sarah,alice,bob,carol)
The GID is what the kernel actually uses — just as UIDs identify users to the kernel, GIDs identify groups. The human-readable names exist for convenience.
The /etc/gshadow File
Just as /etc/shadow stores hashed user passwords, /etc/gshadow stores group passwords and administrative information. In practice, group passwords are almost never used on modern systems, but the file exists for completeness.
$ sudo cat /etc/gshadow | grep developers
developers:!::sarah,alice,bob,carol
The ! indicates no group password is set.
Primary vs. Supplementary Groups
Every user has exactly one primary group and zero or more supplementary groups. These serve different purposes.
Primary Group
The primary group is the group associated with a user’s login session. Its key role is determining the default group ownership of new files:
When you create a new file or directory, it is automatically owned by your current primary group (unless the directory has the SetGID bit set, which overrides this — covered later).
$ id
uid=1000(sarah) gid=1000(sarah) groups=1000(sarah),27(sudo),1001(developers),998(docker)
In this id output:
uid=1000(sarah)— user ID and usernamegid=1000(sarah)— primary group ID and namegroups=...— all groups, including the primary
Sarah’s primary group is sarah (GID 1000) — her personal group. This is the standard Ubuntu/Debian pattern: each user gets a private group with the same name, ensuring that files created by default are not automatically shared with anyone.
On Fedora and RHEL-based systems, the same pattern applies by default (USERGROUPS_ENAB in /etc/login.defs controls this behavior).
Setting the primary group during user creation:
$ sudo useradd -g developers alice # Primary group is developers
Changing an existing user’s primary group:
$ sudo usermod -g developers alice
After this change, files Alice creates will be owned by the developers group by default — immediately shareable with all developers without any permission changes.
Supplementary Groups
Supplementary groups are all the other groups a user belongs to beyond their primary group. They grant access to resources without affecting default file ownership.
When Sarah (primary group sarah) creates a file, it is owned by group sarah. But because she is also a member of sudo, developers, and docker, she can access files with group permissions set for any of those groups.
$ id sarah
uid=1000(sarah) gid=1000(sarah) groups=1000(sarah),27(sudo),1001(developers),998(docker)
Sarah can:
- Run sudo commands (membership in
sudogroup) - Read/write files owned by the
developersgroup with appropriate permissions - Manage Docker containers (membership in
dockergroup)
All of these access rights come from supplementary group memberships.
Adding a user to a supplementary group:
$ sudo usermod -aG developers sarah
The -a (append) flag is essential — without it, the -G option replaces all current supplementary groups rather than adding to them.
Checking all group memberships:
$ groups sarah
sarah : sarah sudo developers docker audio video
$ id sarah
uid=1000(sarah) gid=1000(sarah) groups=1000(sarah),27(sudo),1001(developers),998(docker),29(audio),44(video)
The newgrp Command: Switching Active Groups
Your primary group affects which group owns files you create. If you need to create files for a specific group without changing your permanent primary group, newgrp creates a new shell with a different active group:
$ newgrp developers
Now you are in a subshell where your active group is developers. Files you create in this shell are owned by developers:
$ touch shared_script.sh
$ ls -l shared_script.sh
-rw-r--r-- 1 sarah developers 0 Feb 18 10:15 shared_script.sh
Exit the subshell with exit to return to your original session with your normal primary group.
When newgrp is useful: When working on a project directory where you want everything you create to automatically belong to the project group, without permanently changing your primary group.
How Group Permissions Work with Files
The Group Permission Bits
Recall from the file permissions article: every file has three sets of permission bits — owner, group, and others. The group bits (positions 5–7 in the permission string) determine what members of the file’s associated group can do:
$ ls -la /projects/team/
drwxrwxr-x 3 alice developers 4096 Feb 18 09:00 .
-rw-rw-r-- 1 alice developers 2048 Feb 18 10:15 design.txt
-rwxr-xr-x 1 bob developers 1024 Feb 17 14:30 build.sh
-rw-r--r-- 1 carol developers 512 Feb 16 11:20 notes.txt
For design.txt with permissions -rw-rw-r--:
- Owner (
alice):rw-— can read and write - Group (
developers):rw-— can read and write - Others:
r--— can only read
Any member of the developers group — sarah, alice, bob, carol, or anyone else in the group — can read and write design.txt. Users not in developers can only read it.
For build.sh with permissions -rwxr-xr-x:
- Owner (
bob):rwx— can read, write, and execute - Group (
developers):r-x— can read and execute, but not modify - Others:
r-x— can also read and execute
All developers can run build.sh, but only bob can modify it.
Setting Group Permissions
When creating files for group collaboration, set the group write bit:
$ touch shared_notes.txt
$ chmod g+w shared_notes.txt # Add write permission for group
$ ls -la shared_notes.txt
-rw-rw-r-- 1 sarah developers 0 Feb 18 10:22 shared_notes.txt
Or set permissions numerically:
$ chmod 664 shared_notes.txt # rw-rw-r--
$ chmod 775 shared_script.sh # rwxrwxr-x
Changing a File’s Group
The chgrp command changes which group is associated with a file:
$ chgrp developers shared_notes.txt
Regular users can change a file’s group to any group they belong to. Changing to a group you are not a member of requires root.
Change group recursively for a directory:
$ sudo chgrp -R developers /projects/team/
The umask and Group Permissions
The umask determines default permissions for new files. The default umask of 022 produces:
- Files:
644(rw-r–r–) — group cannot write by default - Directories:
755(rwxr-xr-x) — group cannot write by default
For collaborative group environments where you want group members to be able to edit each other’s files, change the umask to 002:
$ umask 002
With umask 002:
- New files:
664(rw-rw-r–) — group can read and write - New directories:
775(rwxrwxr-x) — group can read, write, and traverse
Add umask 002 to ~/.bashrc to make this permanent for your sessions. Or set it system-wide in /etc/profile or /etc/bash.bashrc.
The SetGID Bit: Enforcing Group Inheritance
One of the most powerful group features is the SetGID (set group ID) bit on directories. When a directory has SetGID set, all files and subdirectories created within it automatically inherit the directory’s group — regardless of the creating user’s primary group.
Why SetGID on Directories Is Essential for Collaboration
Without SetGID, a collaborative directory has a problem: each user creates files owned by their own primary group, not the shared group. Alice creates files owned by alice:alice, Bob creates files owned by bob:bob, and other developers cannot write them without permission changes.
With SetGID on the directory, all files are automatically owned by developers regardless of who created them — immediately accessible to all group members.
Setting Up a Collaborative Directory with SetGID
# Create the shared directory
$ sudo mkdir -p /projects/team_alpha
# Set ownership to a developer and the shared group
$ sudo chown alice:developers /projects/team_alpha
# Set permissions: owner full, group full, others read+traverse
# The 2 prefix sets the SetGID bit
$ sudo chmod 2775 /projects/team_alpha
# Verify
$ ls -la /projects/
drwxrwsr-x 2 alice developers 4096 Feb 18 10:30 team_alpha
The s in the group execute position (rwsr-x) indicates SetGID is set.
Now when any developer creates a file:
$ sudo -u bob touch /projects/team_alpha/bob_notes.txt
$ ls -la /projects/team_alpha/
-rw-r--r-- 1 bob developers 0 Feb 18 10:35 bob_notes.txt
Bob’s file is owned by developers, not bob — immediately readable and (with group write permissions) writable by all developers. No manual chgrp or chmod needed.
The Complete SetGID Collaborative Directory Setup
For a directory where all developers can create, read, modify, and delete each other’s files:
$ sudo mkdir -p /shared/project
$ sudo chown root:developers /shared/project
$ sudo chmod 2775 /shared/project
Developers’ files:
- Automatically owned by
developersgroup (SetGID) - Group-readable and writable (umask 002 or explicit chmod g+w)
This pattern is the standard approach for shared development directories, collaborative work folders, and any resource meant for a specific team.
Creating and Managing Groups
Creating a New Group
$ sudo groupadd groupname
Create with a specific GID:
$ sudo groupadd -g 1500 projectteam
Create a system group (low GID, for services):
$ sudo groupadd --system webapps
Deleting a Group
$ sudo groupdel groupname
Note: You cannot delete a group that is the primary group of any user. Remove or reassign those users’ primary groups first.
Deleting a group does not delete files owned by that group — those files remain but their group field shows the now-orphaned GID number rather than a name. Find and reassign them:
$ sudo find / -gid 1500 -type f 2>/dev/null
Renaming a Group
$ sudo groupmod -n newname oldname
Modifying a Group’s GID
$ sudo groupmod -g 1600 groupname
Warning: Changing a GID means all files previously associated with that group by GID retain the old GID number — they become associated with whatever group (if any) has the new GID, or become orphaned. This is rarely done on production systems.
Managing Group Members with gpasswd
gpasswd manages group membership and can optionally set a group administrator:
$ sudo gpasswd -a username groupname # Add user to group
$ sudo gpasswd -d username groupname # Remove user from group
$ sudo gpasswd -M user1,user2,user3 groupname # Set entire member list
$ sudo gpasswd -A admin_user groupname # Set group administrator
Verifying Group Changes
$ getent group groupname
developers:x:1001:sarah,alice,bob,carol
$ cat /etc/group | grep developers
developers:x:1001:sarah,alice,bob,carol
Important: Group membership changes take effect at next login for the changed user. Existing sessions do not pick up new group memberships automatically. For immediate effect:
$ newgrp developers # Starts a new shell with the new group active
Or have the user log out and back in.
System Groups and Their Purposes
Linux distributions include many system groups pre-configured for specific purposes. Understanding these groups explains how hardware access, system services, and administrative functions are controlled.
Common System Groups on Ubuntu
| Group | GID | Purpose |
|---|---|---|
root |
0 | The root/superuser group |
sudo |
27 | Members can use sudo for full admin access |
adm |
4 | Can read system log files in /var/log |
cdrom |
24 | Can access CD/DVD drives |
audio |
29 | Can access audio devices |
video |
44 | Can access video devices and webcams |
plugdev |
46 | Can access removable storage devices |
lpadmin |
120 | Can manage printers |
docker |
varies | Can manage Docker containers |
www-data |
33 | Web server process group |
ssl-cert |
varies | Can read SSL/TLS private keys |
shadow |
42 | Can read /etc/shadow |
Hardware Access Through Groups
Linux uses groups to control access to hardware devices. Instead of requiring root to use a USB drive or play audio, users in the appropriate group get access automatically:
- Members of
audiocan use/dev/audio,/dev/snd/(sound devices) - Members of
videocan use/dev/video0(webcams),/dev/dri/(GPU) - Members of
plugdevcan mount removable media
When you plug in a USB drive, udev creates the device file with the plugdev group and appropriate permissions. Members of plugdev can mount and access the drive; others cannot.
This is why adding a user to the correct groups matters on multi-user workstations: a new account that is not in audio cannot play sound. Not in video cannot use a webcam.
The docker Group: A Common Example
Adding a user to the docker group is a common task:
$ sudo usermod -aG docker sarah
After logging out and back in, Sarah can run Docker commands without sudo:
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
Without group membership:
$ docker ps
permission denied while trying to connect to the Docker daemon socket
This pattern — a group that grants access to a specific service’s socket or resource — is used by Docker, libvirt (virtual machines), KVM, and many other services.
Practical Group Design Patterns
Pattern 1: Team-Based Collaboration
A software company has three teams: frontend, backend, and devops. Each needs their own shared space, with some cross-team sharing:
# Create team groups
$ sudo groupadd frontend
$ sudo groupadd backend
$ sudo groupadd devops
$ sudo groupadd engineering # Umbrella group for all developers
# Assign users
$ sudo usermod -aG frontend,engineering alice
$ sudo usermod -aG frontend,engineering bob
$ sudo usermod -aG backend,engineering carol
$ sudo usermod -aG backend,engineering dave
$ sudo usermod -aG devops,engineering,sudo eve
# Create shared directories
$ sudo mkdir -p /projects/{frontend,backend,shared}
# Frontend directory: only frontend team
$ sudo chown root:frontend /projects/frontend
$ sudo chmod 2770 /projects/frontend # No access for others
# Backend directory: only backend team
$ sudo chown root:backend /projects/backend
$ sudo chmod 2770 /projects/backend
# Shared directory: all engineering
$ sudo chown root:engineering /projects/shared
$ sudo chmod 2775 /projects/shared # Others can read
Pattern 2: Read-Only Access for Auditors
An auditor needs to review files but not modify them:
$ sudo groupadd auditors
$ sudo usermod -aG auditors frank
# Files group: engineering, permissions: owner rw, group r, others none
$ sudo chmod 640 sensitive_report.txt
$ sudo chgrp engineering sensitive_report.txt
But this does not give Frank (auditors) access. The solution: use ACLs (Access Control Lists) for more granular access, or create a read-only copy owned by the auditors group, or restructure so auditors get read access through a different path.
For simple cases, a dedicated read-only directory:
$ sudo mkdir /audit_files
$ sudo chown root:auditors /audit_files
$ sudo chmod 750 /audit_files # auditors can read and traverse
# Copy files for audit (or link them)
$ sudo cp -r /projects/shared /audit_files/
$ sudo chown -R root:auditors /audit_files/shared/
$ sudo chmod -R 640 /audit_files/shared/ # auditors can read, not write
Pattern 3: Service Account Isolation
A web application runs as webapp user. It needs to read configuration but should not write to it. The database credentials file should only be readable by the web application:
$ sudo groupadd webapp_secrets
$ sudo usermod -aG webapp_secrets webapp
# Only the service account and root can read this
$ sudo chown root:webapp_secrets /etc/myapp/database.conf
$ sudo chmod 640 /etc/myapp/database.conf
# Result: rw-r----- (root can rw, webapp_secrets group can read, others nothing)
Querying Group Information
Listing All Groups
$ cat /etc/group
$ getent group # Includes groups from LDAP/NIS if configured
Finding Groups a User Belongs To
$ groups username
sarah : sarah sudo developers docker audio video
$ id username
uid=1000(sarah) gid=1000(sarah) groups=1000(sarah),27(sudo),1001(developers),998(docker),29(audio),44(video)
Finding Members of a Group
$ getent group developers
developers:x:1001:sarah,alice,bob,carol
$ grep "^developers:" /etc/group
developers:x:1001:sarah,alice,bob,carol
Finding Files Owned by a Group
$ find /projects -group developers -type f
$ find / -gid 1001 -type f 2>/dev/null # Search by GID
Checking If a User Is in a Group
$ id sarah | grep -o "developers"
developers
$ groups sarah | grep -q "developers" && echo "In group" || echo "Not in group"
In group
Quick Reference: Group Management Commands
| Task | Command |
|---|---|
| Create a group | sudo groupadd groupname |
| Delete a group | sudo groupdel groupname |
| Rename a group | sudo groupmod -n newname oldname |
| Add user to group | sudo usermod -aG groupname username |
| Remove user from group | sudo gpasswd -d username groupname |
| Set full member list | sudo gpasswd -M user1,user2 groupname |
| View group members | getent group groupname |
| View user’s groups | groups username or id username |
| Change file’s group | chgrp groupname filename |
| Change file’s group (recursive) | sudo chgrp -R groupname directory/ |
| Set SetGID on directory | sudo chmod g+s directory/ or sudo chmod 2775 directory/ |
| Find files by group | find /path -group groupname |
| Switch active group | newgrp groupname |
| Check group info | getent group groupname |
Conclusion: Groups as the Architecture of Sharing
Groups are the mechanism by which Linux transforms from a system where files are either private or universally accessible into one where precise, controlled sharing is possible. By thoughtfully creating groups, assigning users to appropriate groups, and configuring file and directory permissions around those groups, you create an access control architecture that reflects the actual structure of your organization or project — who needs access to what, and at what level.
The patterns are consistent across all Linux systems: teams get groups, shared resources get group ownership, SetGID directories enforce group inheritance, and the umask or explicit chmod controls whether group members can write to each other’s files. Master these patterns and you have mastered one of Linux’s most powerful collaboration mechanisms.
Whether you are setting up a small home server shared between family members, a development workstation shared by a team, or administering user access on a production Linux server, groups are the tool that makes sensible, secure sharing possible. They are simple enough to understand quickly, powerful enough to handle complex access control requirements, and universal enough that the same concepts apply across every Linux distribution you will ever encounter.




