Linux Users and Groups: useradd, usermod, groupadd

Linux is inherently a multi-user operating system. Every process, file, and resource is associated with a user and group, making user management the foundation of system security and access control....

Key Insights

  • User management is fundamental to Linux security—every process runs as a user, and proper account configuration prevents unauthorized access and limits damage from compromised accounts.
  • The useradd, usermod, and groupadd commands form the core toolkit for user administration, but they require careful attention to options like home directories, shells, and group memberships to avoid common misconfigurations.
  • Groups are the primary mechanism for collaborative permission management—understanding primary versus supplementary groups is essential for implementing least-privilege access control in production environments.

Introduction to Linux User Management

Linux is inherently a multi-user operating system. Every process, file, and resource is associated with a user and group, making user management the foundation of system security and access control. Whether you’re running a single-user workstation or managing a fleet of production servers, understanding how to properly create and manage users and groups is non-negotiable.

Linux distinguishes between regular users (typically UID 1000+) and system users (UID < 1000). System users run services and daemons—think www-data for web servers or mysql for database processes. Regular users are for humans who need interactive shell access. This separation ensures that compromised services don’t automatically grant shell access.

Let’s check your current user context:

# Display current username
whoami

# Show user ID, group ID, and group memberships
id

# Output: uid=1000(john) gid=1000(john) groups=1000(john),27(sudo),999(docker)

User information is stored in /etc/passwd, while group data lives in /etc/group:

# View all users (system and regular)
cat /etc/passwd

# Example line: john:x:1000:1000:John Doe:/home/john:/bin/bash
# Format: username:password:UID:GID:comment:home:shell

# View all groups
cat /etc/group

# Example line: developers:x:1001:john,jane,bob
# Format: groupname:password:GID:members

The x in the password field indicates that encrypted passwords are stored in /etc/shadow, which is only readable by root.

Creating Users with useradd

The useradd command creates new user accounts. Unlike the more user-friendly adduser (a Perl script wrapper available on Debian-based systems), useradd is the low-level binary available on all Linux distributions, making it the portable choice for scripts and automation.

Basic user creation is deceptively simple but often wrong:

# This creates a user but NO home directory and NO usable shell
sudo useradd john

# Verify - notice the missing home directory
id john
# uid=1001(john) gid=1001(john) groups=1001(john)

This user can’t log in interactively because they lack a home directory and have /bin/sh or /sbin/nologin as their shell by default (depending on distribution). Here’s the correct approach:

# Create user with home directory and bash shell
sudo useradd -m -s /bin/bash jane

# -m creates /home/jane and copies files from /etc/skel
# -s sets the login shell

Now set a password, or the account remains locked:

sudo passwd jane
# Enter password twice when prompted

For more control, specify UID, primary group, and additional groups:

# Create user with specific UID and primary group
sudo useradd -u 1500 -g developers -m -s /bin/bash bob

# Create user and add to multiple supplementary groups
sudo useradd -m -s /bin/bash -G sudo,docker,developers alice

The -G flag sets supplementary groups (comma-separated, no spaces). The -g flag sets the primary group. If you omit -g, useradd creates a new group matching the username.

For service accounts that shouldn’t have interactive login:

# Create system user for running applications
sudo useradd -r -s /sbin/nologin -d /opt/appname appuser

# -r creates a system user (UID < 1000)
# -s /sbin/nologin prevents interactive login
# -d sets home directory without creating it

Modifying Users with usermod

User requirements change. Someone needs database access, or you’re moving home directories to a new partition. The usermod command handles all post-creation modifications.

Changing the primary group:

# Change bob's primary group to admins
sudo usermod -g admins bob

# Verify
id bob

Adding supplementary groups is where mistakes happen. The -G flag replaces all supplementary groups:

# WRONG: This removes bob from all other groups
sudo usermod -G docker bob

# CORRECT: Use -aG to append groups
sudo usermod -aG docker bob

# Add multiple groups at once
sudo usermod -aG sudo,developers,docker bob

The -a (append) flag only works with -G. Without it, you’ll accidentally remove users from groups they need, potentially breaking sudo access or application permissions.

Moving a user’s home directory:

# Move jane's home from /home/jane to /data/home/jane
sudo usermod -d /data/home/jane -m jane

# -d specifies new home directory
# -m moves contents from old to new location

Changing the login shell:

# Switch alice to zsh
sudo usermod -s /bin/zsh alice

Locking and unlocking accounts (useful for temporary access suspension):

# Lock account - prepends ! to password hash in /etc/shadow
sudo usermod -L bob

# User cannot log in with password, but SSH keys still work!
# To completely disable, also expire the account:
sudo usermod -e 1 bob

# Unlock account
sudo usermod -U bob

# Remove expiration
sudo usermod -e "" bob

Renaming a user requires changing both the username and home directory:

# Rename user john to john.smith
sudo usermod -l john.smith john

# Update home directory to match
sudo usermod -d /home/john.smith -m john.smith

Managing Groups with groupadd

Groups are Linux’s mechanism for collaborative access control. Instead of granting permissions to individual users, you assign permissions to groups and add users as members. When you need to grant database access to a new developer, you add them to the database group rather than modifying file permissions.

Creating a group is straightforward:

# Create a new group
sudo groupadd developers

# Create group with specific GID
sudo groupadd -g 2000 admins

Specifying GIDs is important when synchronizing users across multiple systems or working with networked file systems like NFS, where numeric IDs must match.

Check a user’s group memberships:

# View groups for specific user
groups jane

# View with numeric IDs
id jane

Renaming a group:

# Rename group from oldname to newname
sudo groupmod -n developers-team developers

Deleting a group (only if it’s not any user’s primary group):

sudo groupdel developers-team

Adding users to groups is done with usermod, not groupadd:

# Add multiple users to developers group
sudo usermod -aG developers alice
sudo usermod -aG developers bob
sudo usermod -aG developers charlie

Practical Use Cases and Workflows

Scenario 1: Creating a deployment user for web applications

# Create system user for running Node.js app
sudo useradd -r -m -s /bin/bash -d /opt/myapp deployuser

# Create deployment group
sudo groupadd deployment

# Add deployuser to deployment group
sudo usermod -aG deployment deployuser

# Create application directory with group ownership
sudo mkdir -p /opt/myapp
sudo chown deployuser:deployment /opt/myapp
sudo chmod 2775 /opt/myapp  # setgid bit ensures new files inherit group

# Add developers to deployment group for access
sudo usermod -aG deployment alice
sudo usermod -aG deployment bob

Scenario 2: Shared project directory with group permissions

# Create project group
sudo groupadd project-alpha

# Add team members
sudo usermod -aG project-alpha alice
sudo usermod -aG project-alpha bob
sudo usermod -aG project-alpha charlie

# Create shared directory
sudo mkdir /srv/project-alpha
sudo chgrp project-alpha /srv/project-alpha
sudo chmod 2775 /srv/project-alpha

# Set default ACLs so new files are group-writable
sudo setfacl -d -m g::rwx /srv/project-alpha

Scenario 3: User onboarding script

#!/bin/bash
# onboard-user.sh - Create new developer account

USERNAME=$1
FULLNAME=$2

if [ -z "$USERNAME" ] || [ -z "$FULLNAME" ]; then
    echo "Usage: $0 <username> <fullname>"
    exit 1
fi

# Create user with home directory
sudo useradd -m -s /bin/bash -c "$FULLNAME" "$USERNAME"

# Add to standard developer groups
sudo usermod -aG developers,docker,sudo "$USERNAME"

# Set initial password (user must change on first login)
echo "Setting password for $USERNAME"
sudo passwd "$USERNAME"
sudo chage -d 0 "$USERNAME"  # Force password change at next login

echo "User $USERNAME created successfully"
echo "Groups: $(groups $USERNAME)"

Best Practices and Security Considerations

1. Always create home directories for interactive users. Without -m, users lack a place for configuration files and SSH keys.

2. Use -aG when adding supplementary groups. The most common usermod mistake is using -G alone and accidentally removing users from critical groups like sudo.

3. Implement password aging policies:

# Check password aging for user
sudo chage -l alice

# Set password to expire after 90 days
sudo chage -M 90 alice

# Force password change at next login
sudo chage -d 0 alice

4. Review sudo access regularly:

# Check what sudo commands a user can run
sudo -l -U alice

# List all users in sudo group
getent group sudo

5. Audit user permissions periodically:

#!/bin/bash
# audit-users.sh - Find users with sudo access

echo "Users with sudo access:"
getent group sudo | cut -d: -f4 | tr ',' '\n'

echo -e "\nUsers with UID 0 (root equivalent):"
awk -F: '$3 == 0 {print $1}' /etc/passwd

echo -e "\nUsers with login shells:"
awk -F: '$7 !~ /(nologin|false)/ && $3 >= 1000 {print $1, $7}' /etc/passwd

6. Disable unused accounts rather than deleting them to preserve UID ownership:

# Lock account and expire it
sudo usermod -L -e 1 oldemployee

7. Use system users for services. Never run applications as root or regular users:

# Create dedicated user for each service
sudo useradd -r -s /sbin/nologin -d /opt/nginx nginx

8. Document group purposes. Maintain a reference of what each group controls:

# developers: Access to /srv/projects, docker, development databases
# deployment: Can deploy applications to production
# monitoring: Read-only access to logs and metrics

Proper user and group management isn’t glamorous, but it’s the bedrock of Linux security. Master these commands, understand the implications of each flag, and you’ll prevent countless security issues and access control headaches down the road.

Liked this? There's more.

Every week: one practical technique, explained simply, with code you can use immediately.