Domain 10 · Users & groups

Manage users
and groups

Create and manage local user accounts and groups, configure password aging policies, grant superuser access with sudo, and understand the authentication file format on RHEL 9.

9objectives
6topic areas
8quiz questions
useraddprimary tool

Objectives

What the exam tests

  • Create, delete, and modify local user accounts
  • Change passwords and configure password aging policies with chage
  • Create, delete, and modify local groups and group memberships
  • Configure superuser access using sudo and visudo
  • Understand and interpret /etc/passwd, /etc/shadow, /etc/group
  • Set UID, GID, home directory, shell, and account expiry at creation
  • Lock and unlock user accounts
  • Create system accounts for services (no login shell, no home)
  • Configure default values for new user creation via /etc/login.defs

User and group management appears on every RHCSA exam. Expect multi-step tasks: create a user, set a password, assign to a group, configure aging, and grant sudo — all in one scenario.

Coverage weight by topic

User creation / modification
Critical
Password & aging policy
Very high
sudo configuration
Very high
Group management
High
Config file knowledge
Medium
login.defs defaults
Low

Configuration files

/etc/passwd — user account database

Seven colon-separated fields. World-readable — passwords are not stored here.

aliceusername
xpassword
1001UID
1001GID
Alice SmithGECOS
/home/alicehome dir
/bin/bashshell
FieldMeaningNotes
UsernameLogin nameMax 32 chars; lowercase recommended
Passwordx = stored in /etc/shadowNever a real password here
UIDUser ID number0=root; 1–999=system; 1000+=regular users
GIDPrimary group IDReferences /etc/group
GECOSFull name / commentDisplayed by finger, set with -c
Home dirUser's home directory pathCreated by useradd -m
ShellLogin shell/sbin/nologin or /bin/false disables login

/etc/shadow — password and aging database

Nine colon-separated fields. Readable only by root. This is where hashed passwords and aging policy are stored.

# /etc/shadow format: alice:$6$rounds=...:19800:0:99999:7::: # user: hash : lastchange : min : max : warn : inactive : expire : reserved
Field #MeaningSet with
1 — UsernameLogin name (matches /etc/passwd)
2 — HashHashed password. ! = locked; !! = never setpasswd
3 — Last changeDays since epoch when password was last changedchage -d
4 — Min daysMinimum days between password changeschage -m
5 — Max daysMaximum days before password must changechage -M
6 — Warn daysDays of warning before password expireschage -W
7 — InactiveDays after expiry before account is disabledchage -I
8 — ExpireDate (days since epoch) when account expireschage -E
9 — ReservedUnused

/etc/group and /etc/gshadow

# /etc/group — four colon-separated fields devs:x:2001:alice,bob,carol # name : password : GID : member_list # /etc/gshadow — group passwords (rarely used) devs::2001:alice,bob,carol
FieldMeaning
Group nameName of the group
Passwordx = stored in /etc/gshadow (group passwords are rarely used)
GIDGroup ID number. System groups: 0–999; user groups: 1000+
Member listComma-separated list of supplementary members. Primary group members are NOT listed here.

A user's primary group is set in /etc/passwd field 4 (GID). The user is NOT listed in /etc/group for their primary group — only supplementary memberships appear there.

/etc/login.defs — new account defaults

# Key settings that affect new accounts created with useradd PASS_MAX_DAYS 99999 # max days before password must change PASS_MIN_DAYS 0 # min days between password changes PASS_WARN_AGE 7 # days of warning before password expires UID_MIN 1000 # minimum UID for regular users UID_MAX 60000 # maximum UID for regular users GID_MIN 1000 # minimum GID for user groups GID_MAX 60000 # maximum GID for user groups SYS_UID_MIN 201 # minimum UID for system accounts SYS_UID_MAX 999 # maximum UID for system accounts CREATE_HOME yes # create home directory by default ENCRYPT_METHOD SHA512 # hashing algorithm for passwords

Changes to /etc/login.defs only affect newly created accounts. Existing accounts are not retroactively updated.

/etc/skel — new user home template

# Files in /etc/skel/ are copied into every new user's home directory ls -la /etc/skel/ # Typical contents: # .bash_logout .bash_profile .bashrc # Add custom files that all new users should have cp company-motd.txt /etc/skel/README.txt mkdir /etc/skel/projects # Copy skel to an existing user's home manually cp -r /etc/skel/. /home/alice/ chown -R alice:alice /home/alice/

User account management

useradd — creating accounts

── BASIC CREATION ──────────────────────────────────────────── useradd alice # create with system defaults useradd -m alice # explicitly create home directory useradd -m -s /bin/bash alice # with bash shell (recommended) ── COMMON OPTIONS ──────────────────────────────────────────── useradd -u 1500 alice # specify UID useradd -g devs alice # primary group (by name or GID) useradd -G wheel,ops alice # supplementary groups useradd -d /data/alice alice # custom home directory path useradd -s /bin/bash alice # login shell useradd -c "Alice Smith" alice # comment / full name (GECOS) useradd -e "2026-12-31" alice # account expiry date (YYYY-MM-DD) useradd -f 30 alice # inactive days after password expiry ── COMBINED EXAMPLE ────────────────────────────────────────── useradd \ -u 1500 \ -g devs \ -G wheel \ -m \ -d /home/alice \ -s /bin/bash \ -c "Alice Smith" \ alice ── SYSTEM ACCOUNTS (services, no login) ───────────────────── useradd -r -s /sbin/nologin myservice # system account useradd -r -M -s /sbin/nologin daemon2 # -M = no home dir

After creating a user, always set a password with passwd username. An account without a password has !! in /etc/shadow and cannot log in at all.

usermod — modifying accounts

── MOST IMPORTANT: adding to groups ───────────────────────── usermod -aG wheel alice # APPEND to supplementary groups usermod -aG wheel,ops alice # append to multiple groups # WARNING: usermod -G wheel alice (no -a) REPLACES all supplementary groups! ── CHANGE VARIOUS ATTRIBUTES ───────────────────────────────── usermod -g newgroup alice # change primary group usermod -d /newhome alice # change home dir (does not move files) usermod -d /newhome -m alice # change home dir AND move contents usermod -s /bin/zsh alice # change shell usermod -c "New Name" alice # change GECOS comment usermod -l newname alice # rename login (does not rename home!) usermod -u 1600 alice # change UID usermod -e "2027-01-01" alice # set expiry date usermod -e "" alice # remove expiry (account never expires) ── LOCK / UNLOCK ───────────────────────────────────────────── usermod -L alice # Lock — prepends ! to password hash usermod -U alice # Unlock — removes the ! prefix passwd -l alice # Lock (alternative) passwd -u alice # Unlock (alternative) ── DISABLE SHELL (prevent interactive login) ───────────────── usermod -s /sbin/nologin alice # still allows SSH key login for services usermod -s /bin/false alice # truly blocks everything
Never use usermod -G groups user without -a. It silently replaces all supplementary group memberships. Always use usermod -aG groups user.

userdel — removing accounts

# Remove user account (keeps home directory and mail spool) userdel alice # Remove user AND home directory AND mail spool userdel -r alice # Force removal even if user is logged in userdel -f alice # After deletion, find orphaned files (owned by old UID) find / -nouser -ls 2>/dev/null find / -uid 1500 -ls 2>/dev/null # if you know the old UID

Always verify whether you should preserve or remove the home directory. On the exam, read the task carefully — it may say "remove the user's home directory" or "preserve the user's files."

Querying user information

# Show user ID and group memberships id alice id # current user # Output: uid=1001(alice) gid=1001(alice) groups=1001(alice),10(wheel),2001(devs) # Show group names only groups alice # Look up user in /etc/passwd via NSS getent passwd alice getent passwd # all users # Look up group getent group devs getent group # all groups # Show who is currently logged in who w last # login history last alice # history for a specific user

Passwords and aging

passwd — setting and managing passwords

# Set password interactively passwd alice # prompts for new password twice passwd # change your own password # Non-interactive (for scripts) echo "NewP@ss1" | passwd --stdin alice # Generate a hashed password for /etc/shadow or Kickstart openssl passwd -6 "MyPassword" # SHA-512 hash python3 -c "import crypt; print(crypt.crypt('MyP@ss', crypt.mksalt(crypt.METHOD_SHA512)))" # passwd status flags passwd -l alice # Lock account passwd -u alice # Unlock account passwd -e alice # Expire password — force change at next login passwd -n 7 alice # min days between changes passwd -x 90 alice # max days before change required passwd -w 14 alice # warn days before expiry passwd -S alice # show password status

chage — full aging policy control

# View all aging information for a user chage -l alice # Output shows: Last password change, Password expires, # Password inactive, Account expires, # Min/Max/Warning days between changes ── SET AGING PARAMETERS ────────────────────────────────────── chage -m 7 alice # min 7 days between changes chage -M 90 alice # max 90 days — password expires chage -W 14 alice # warn 14 days before expiry chage -I 30 alice # inactive 30 days after expiry then lock chage -E "2027-06-30" alice # account expires on date chage -E -1 alice # remove expiry (never expires) ── FORCE IMMEDIATE PASSWORD CHANGE ────────────────────────── chage -d 0 alice # sets last change to epoch — must change now passwd -e alice # equivalent — expire the password ── INTERACTIVE MODE ────────────────────────────────────────── chage alice # prompts for each value interactively
chage flagshadow fieldEffect
-d DAYSField 3Set last change date (0 = force change on next login)
-m DAYSField 4Minimum days between password changes
-M DAYSField 5Maximum days before password must change
-W DAYSField 6Warning days before password expires
-I DAYSField 7Inactive days — lock account after this many days past expiry
-E DATEField 8Account expiry date (YYYY-MM-DD or -1 for never)
-lAllList (display) all aging information

Password hash formats in /etc/shadow

# Hash format: $algorithm$salt$hash $1$...$... # MD5 (very old, insecure) $5$...$... # SHA-256 $6$...$... # SHA-512 (RHEL 9 default) $y$...$... # yescrypt (newer, more secure) # Special values in field 2: !! # password never set — account cannot log in !$6$... # locked — ! prefix prevents authentication * # disabled — typically for system accounts # empty — no password required (insecure)

Group management

groupadd, groupmod, groupdel

── CREATE ──────────────────────────────────────────────────── groupadd devs # create with next available GID groupadd -g 2001 devs # specify GID groupadd -r svcgrp # system group (GID < 1000) ── MODIFY ──────────────────────────────────────────────────── groupmod -n developers devs # rename group groupmod -g 2100 devs # change GID ── DELETE ──────────────────────────────────────────────────── groupdel devs # cannot delete a group that is a primary group ── ADD MEMBERS ─────────────────────────────────────────────── usermod -aG devs alice # add alice to devs (recommended) gpasswd -a alice devs # alternative: add alice to devs gpasswd -d alice devs # remove alice from devs gpasswd -M alice,bob,carol devs # set member list (replaces existing) ── QUERY ───────────────────────────────────────────────────── getent group devs # show group info and members getent group | grep alice # find all groups alice is in id alice # show all groups for a user groups alice # group names only

Primary vs supplementary groups

Primary group

  • Every user has exactly one primary group
  • Stored in /etc/passwd field 4 (GID)
  • New files created by user are owned by this group
  • User is NOT listed in /etc/group for primary group
  • Change with usermod -g groupname user
  • Switch for session with newgrp groupname

Supplementary groups

  • A user can belong to many supplementary groups
  • Stored in /etc/group member list field 4
  • Grant additional resource access
  • Add with usermod -aG group user (use -a!)
  • Remove with gpasswd -d user group
  • Changes take effect at next login

After adding a user to a supplementary group, they must log out and back in (or run newgrp groupname) for the change to take effect in their current session.

newgrp — switch active group in session

# Temporarily switch primary group for the current shell session newgrp devs # opens sub-shell with devs as primary group # Files created now will be owned by group devs # Type 'exit' to return to the original shell/group # Useful immediately after being added to a group (no re-login needed) # Verify with: id # should show devs as gid

sudo configuration

sudo overview and visudo

sudo allows authorized users to run commands as root (or another user) without knowing the root password. Configuration lives in /etc/sudoers — always edited with visudo to prevent syntax errors.

# Always edit sudoers with visudo — it validates syntax before saving visudo # edits /etc/sudoers in $EDITOR visudo -f /etc/sudoers.d/myfile # edit a drop-in file visudo -c # check syntax without editing # NEVER use a regular text editor — a syntax error locks everyone out

A syntax error in /etc/sudoers can prevent any user from using sudo, including root. Always use visudo. If you do break it, boot to rescue mode and fix the file.

sudoers rule syntax

# Rule format: # who where=(run_as) [NOPASSWD:] what ── USER RULES ──────────────────────────────────────────────── alice ALL=(ALL) ALL # alice: full sudo everywhere alice ALL=(ALL) NOPASSWD: ALL # no password prompt bob ALL=(ALL) /usr/bin/systemctl restart httpd # single command carol ALL=(ALL) /usr/bin/dnf install * # wildcard dave ALL=(root) /sbin/fdisk -l # specific run_as ── GROUP RULES (prefix with %) ─────────────────────────────── %wheel ALL=(ALL) ALL # wheel group: full sudo (RHEL default) %devs ALL=(ALL) NOPASSWD: /usr/bin/systemctl * httpd ── ALIASES (for reuse) ─────────────────────────────────────── User_Alias ADMINS = alice, bob Cmnd_Alias SERVICES = /usr/bin/systemctl start *, /usr/bin/systemctl stop * Host_Alias SERVERS = server1, server2 ADMINS SERVERS=(ALL) SERVICES # combine aliases

/etc/sudoers.d/ — drop-in files

# Drop-in directory (preferred over editing /etc/sudoers directly) ls /etc/sudoers.d/ # Create a drop-in rule for alice echo "alice ALL=(ALL) NOPASSWD: ALL" | tee /etc/sudoers.d/alice chmod 0440 /etc/sudoers.d/alice # must be 0440 or 0400 # Validate with visudo visudo -c -f /etc/sudoers.d/alice # The /etc/sudoers file includes all files in this directory: # #includedir /etc/sudoers.d # Files with ~ or . in name are ignored by includedir

Drop-in files in /etc/sudoers.d/ survive package updates to /etc/sudoers. They must have permissions 0440 (or stricter) and filenames must not contain ~ or . to be included.

The wheel group — quickest sudo grant

# RHEL 9 ships with this line enabled in /etc/sudoers: %wheel ALL=(ALL) ALL # So the fastest way to grant full sudo to a user is: usermod -aG wheel alice # Verify membership id alice groups alice # Test sudo works (as alice) sudo -l # list alice's allowed sudo commands sudo whoami # should output: root # Require no password for wheel (edit sudoers): # %wheel ALL=(ALL) NOPASSWD: ALL

su vs sudo — when to use each

CommandRequiresEffectAudit trail
su -Root passwordFull root login shell (new session)Only login recorded
su - alicealice's password (or root)Full login shell as aliceOnly login recorded
sudo commandUser's own password + sudoers ruleRun single command as rootFull command logged
sudo -iUser's own password + sudoers ruleInteractive root shell via sudoAll commands logged
sudo -lUser's own passwordList allowed sudo commands

Prefer sudo over su in production environments — every sudo invocation is logged to /var/log/secure with the username and full command, creating an auditable trail.

Cheat sheet

Most-tested commands — quick reference

Create user with home+bash
useradd -m -s /bin/bash alice
Create user with UID+groups
useradd -u 1500 -G wheel alice
Create system account
useradd -r -s /sbin/nologin svc
Set password
passwd alice
Non-interactive password
echo "Pass1" | passwd --stdin alice
Expire password (force change)
chage -d 0 alice
Set max password age
chage -M 90 alice
Set account expiry
chage -E "2027-01-01" alice
View aging info
chage -l alice
Lock account
usermod -L alice
Unlock account
usermod -U alice
Disable shell
usermod -s /sbin/nologin alice
Add to group (safe)
usermod -aG wheel alice
Change primary group
usermod -g devs alice
Rename login
usermod -l newname alice
Delete user + home
userdel -r alice
View user info
id alice
Query /etc/passwd
getent passwd alice
Create group
groupadd -g 2001 devs
Add user to group
gpasswd -a alice devs
Remove user from group
gpasswd -d alice devs
Query group members
getent group devs
Edit sudoers safely
visudo
Grant full sudo (easiest)
usermod -aG wheel alice
List sudo privileges
sudo -l
Drop-in sudo file
echo "alice ALL=(ALL) NOPASSWD: ALL" > /etc/sudoers.d/alice

useradd / usermod flag comparison

Flaguseradd meaningusermod meaning
-u UIDSet UID for new accountChange existing UID
-g groupSet primary groupChange primary group
-G groupsSet supplementary groupsReplaces all supplementary groups
-aN/AAppend — must combine with -G
-aG groupsN/AAppends to supplementary groups
-s shellSet login shellChange login shell
-d dirSet home directory pathChange home path (use -m to move)
-mCreate home if missingMove home directory contents
-c textSet GECOS commentChange GECOS comment
-e dateSet account expiryChange account expiry
-rSystem account (low UID)N/A
-MDo not create home dirN/A
-LN/ALock account (add ! to hash)
-UN/AUnlock account (remove !)
-l nameN/ARename login name

Full user setup — exam template

Create the user with all required attributes
useradd -u 1500 -g devs -G wheel -m -s /bin/bash -c "Alice Smith" alice
Set the password
passwd alice
Configure password aging
chage -M 90 -m 7 -W 14 alice
Grant sudo if required
usermod -aG wheel alice
Verify everything
id alice chage -l alice getent passwd alice

Practice quiz

Question 1 of 8

User alice is in groups alice, devs, and ops. You run usermod -G wheel alice. What is the result?

usermod -G wheel alice without -a replaces all supplementary group memberships with just wheel. Alice loses membership in devs and ops. Her primary group (alice) is unaffected. Always use usermod -aG wheel alice to append safely.

Question 2 of 8

You need user bob to change his password the next time he logs in, but not force it today. Which command achieves this?

chage -d 0 bob sets the "last password change" date to day 0 (January 1, 1970), making the password immediately expired. On next login the system will require bob to set a new password before proceeding. chage -M 0 sets max days to 0 which means the password is always instantly expired — similar effect but a different field. usermod -L locks the account, preventing login entirely. chage -e 0 would expire the account itself.

Question 3 of 8

Which file stores hashed passwords and password aging policy?

/etc/shadow stores the hashed password (field 2) and all aging fields (min days, max days, warn days, inactive days, expiry date). It is readable only by root. /etc/passwd contains account metadata but stores only x for the password field. /etc/login.defs stores aging defaults for new accounts, not per-user data.

Question 4 of 8

You create a drop-in sudo rule file at /etc/sudoers.d/alice. The file has permissions 0644. What happens when alice tries to use sudo?

sudo requires sudoers files to have permissions of 0440 or stricter (e.g., 0400). A file with world-readable permissions (0644) is considered insecure and sudo will refuse to parse it with an error like "sudo: /etc/sudoers.d/alice is world-readable". Always set chmod 0440 /etc/sudoers.d/filename.

Question 5 of 8

What does !! in the password field of /etc/shadow indicate?

!! in the shadow password field means no password has ever been set — the account was created but passwd was never run for it. The account cannot be used for password-based login. A single ! prefix on an existing hash (like !$6$...) means the account is administratively locked by usermod -L or passwd -l.

Question 6 of 8

Which command creates a system account named webservice that cannot log in interactively and has no home directory?

useradd -r -M -s /sbin/nologin webservice: -r creates a system account (UID below 1000), -M suppresses home directory creation, -s /sbin/nologin sets a shell that prints a message and exits cleanly when anyone tries to log in. Option A creates a regular user account. Option C uses -L which is not a valid useradd flag (it's a usermod flag).

Question 7 of 8

User carol's primary group is carol. She creates a file in a directory with SGID set and owned by group devs. What group owns the new file?

When the SGID bit is set on a directory, new files created inside inherit the group of the directory rather than the creating user's primary group. This is the primary purpose of SGID on directories — ensuring all files in a shared workspace belong to the same group. The new file would be owned by group devs.

Question 8 of 8

You see the line alice:x:1001:1001:Alice Smith:/home/alice:/bin/bash in /etc/passwd. What does the first 1001 represent?

The seven fields in /etc/passwd are: username : password : UID : GID : GECOS : home : shell. The third field (first 1001) is the UID. The fourth field (second 1001) is the primary GID. In this case they happen to match — alice's UID and private group GID are both 1001, which is typical when a user is created with a user private group (the default on RHEL).