While the earlier tutorial in this series covered the core useradd, usermod, and userdel tools for user lifecycle management, this guide goes deeper into the full toolkit for managing users and groups at scale on RHEL 9: bulk creation, password management with chpasswd, group administration with gpasswd, per-user resource limits with ulimit and /etc/security/limits.conf, user account locking and expiry workflows, and auditing all accounts on the system. Real-world server environments often require onboarding dozens of users at once, managing department-level group permissions, and ensuring consistent password policies enforced at the OS level.

Prerequisites

  • RHEL 9 server with root or sudo access

Step 1 — Review Key Commands

Quick reference of all user and group commands:

# User commands
useradd     # Create a user
usermod     # Modify a user
userdel     # Delete a user
passwd      # Set or change password
chage       # Manage password aging
id          # Show user identity

# Group commands
groupadd    # Create a group
groupmod    # Modify a group
groupdel    # Delete a group
gpasswd     # Administer group passwords and membership
newgrp      # Log in to a new group (change effective GID)
groups      # Show groups a user belongs to
getent      # Query name service databases

Step 2 — Create Users with useradd Defaults

View the current defaults for useradd:

useradd --defaults
# or
cat /etc/default/useradd

Customise defaults for your environment:

vi /etc/default/useradd
GROUP=100
HOME=/home
INACTIVE=-1
EXPIRE=
SHELL=/bin/bash
SKEL=/etc/skel
CREATE_MAIL_SPOOL=no

The /etc/skel directory contains files copied to each new user’s home directory. Add standard configuration files here:

ls -la /etc/skel/
# Copy a standard .vimrc for all new users
cp /root/.vimrc /etc/skel/.vimrc

Step 3 — Bulk User Creation from a CSV

vi /tmp/new-users.csv
alice,Alice Johnson,developers,[email protected]
bob,Bob Smith,developers,[email protected]
charlie,Charlie Brown,operations,[email protected]
diana,Diana Prince,operations,[email protected]
#!/bin/bash
# bulk-create-users.sh
while IFS=, read -r username fullname group email; do
    # Create group if it does not exist
    getent group "$group" || groupadd "$group"

    # Create user
    useradd -m -s /bin/bash -c "$fullname" -G "$group" "$username"

    # Set a temporary password (username + ! = force change on first login)
    echo "$username:TempPass!2026" | chpasswd
    chage -d 0 "$username"   # Force password reset at first login

    # Add email comment to passwd GECOS
    usermod -c "$fullname " "$username"

    echo "Created: $username ($fullname) in group $group"
done < /tmp/new-users.csv
bash /tmp/bulk-create-users.sh

Step 4 — Set Passwords for Multiple Users with chpasswd

chpasswd reads username:password pairs from stdin, making it ideal for bulk password setting:

# Set passwords for multiple users at once
echo -e "alice:SecurePass1!nbob:SecurePass2!" | chpasswd

# Or from a file (ensure this file is deleted afterwards)
cat /tmp/passwords.txt | chpasswd
shred -u /tmp/passwords.txt    # Securely delete the password file

Generate a strong random password for a new user:

PASS=$(openssl rand -base64 16)
echo "alice:$PASS" | chpasswd
echo "Generated password for alice: $PASS"   # Show once then discard

Step 5 — Manage Group Membership with gpasswd

gpasswd provides group administration including the ability to designate group administrators:

# Add a user to a group
gpasswd -a alice developers

# Remove a user from a group
gpasswd -d alice developers

# Set the list of group members (replaces existing)
gpasswd -M alice,bob,charlie developers

# Designate a group administrator (who can add/remove members without root)
gpasswd -A alice developers

View group membership:

getent group developers
cat /etc/group | grep developers

Step 6 — Configure Per-User Resource Limits

The /etc/security/limits.conf file (enforced by PAM via pam_limits) sets resource limits per user or group:

vi /etc/security/limits.conf
# Format: domain  type  item  value
# domain: username, @groupname, or * (all users)
# type: soft (warning, can be raised up to hard limit) or hard (absolute maximum)
# item: nofile, nproc, memlock, stack, cpu, etc.

# Prevent fork bombs — limit processes per user
@developers  hard  nproc  1000
@developers  soft  nproc  500

# Increase open file limit for web server processes
nginx        hard  nofile  65536
nginx        soft  nofile  65536

# Prevent a single user from using more than 4 GB of locked memory
@operations  hard  memlock  4194304

# Limit CPU time (in minutes)
# charlie  hard  cpu  60

Limits take effect on next login. Check current limits:

ulimit -a           # Show all current limits for the current session
ulimit -n           # Show open file limit
ulimit -u           # Show process limit

Step 7 — Account Locking and Expiry Workflows

# Lock an account immediately (adds ! to password hash in /etc/shadow)
usermod -L charlie

# Unlock
usermod -U charlie

# Set account expiry date (YYYY-MM-DD)
usermod -e 2026-12-31 charlie

# Set account expiry for a contractor (90 days from today)
usermod -e $(date -d "+90 days" +%Y-%m-%d) contractor1

# List all accounts with their expiry dates
for user in $(getent passwd | awk -F: '$3>=1000 {print $1}'); do
    echo "$user: $(chage -l $user | grep 'Account expires')"
done

Step 8 — Audit User Accounts on the System

# List all accounts with UID >= 1000 (human accounts)
awk -F: '$3>=1000 && $31 && $5!="**Never" {print}' | awk '{ cmd="date -d ""$5" "$6" "$7" "$8"" +%s 2>/dev/null"; cmd | getline ts; close(cmd); if (ts && (systime()-ts) > 7776000) print $1, "last login:", $5, $6, $7, $8 }'

# Simpler: users who have never logged in
lastlog | grep "Never logged in"

Step 9 — Configure Password Quality with PAM

In addition to /etc/security/pwquality.conf, configure the PAM password stacking for RHEL 9:

cat /etc/pam.d/system-auth | grep pam_pwquality

The line should include pam_pwquality.so with retry=3. If customising the PAM stack, use authselect:

# View current authselect profile
authselect current

# List available profiles
authselect list

# Enable password quality enforcement
authselect select sssd with-pwquality --force

Verification Checklist

# All users
getent passwd

# All groups
getent group

# Specific user details
id alice
chage -l alice

# Group members
getent group developers

# Current resource limits
su - alice -c 'ulimit -a'

Conclusion

You now have a complete toolkit for managing users and groups at scale on RHEL 9: bulk creation from CSV files, secure bulk password setting with chpasswd, group administration with gpasswd, per-user resource limits via limits.conf, account locking and time-limited contractor accounts, and comprehensive audit queries to identify security risks in the account database.

Next steps: How to Configure DNS Resolution on RHEL 9, How to Configure sudo and Sudoers on RHEL 9, and How to Perform a Security Audit with auditd on RHEL 9.