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.