Users & Groups: Account Management
- Explain how Linux identifies users (UID) and where account data lives
- Create, modify, and delete users and groups with the standard tools
- Manage passwords and password aging, and lock/unlock accounts
- Tell primary from supplementary groups, and grant sudo safely
Why users and groups exist
Understand that the system identifies users by number, not name.
Every process runs as a user and every file is owned by one — that's how Linux decides who may do what. But the system doesn't actually care about your name; internally it uses a number, the UID. The username is just a friendly label that maps to a UID.
Think of it like an employee ID number: HR's systems key off the number, and the name on your badge is cosmetic. Rename a user and their files still belong to them, because the files store the UID, not the name.
UIDs fall into three ranges:
- 0 —
root, the superuser (can do anything; SELinux/permissions don't constrain it). - 1–999 — system accounts for services (no real login).
- 1000+ — regular human users.
Example — not runnable on your lab box
id alice; grep alice /etc/passwduid=1000(alice) gid=1000(alice) groups=1000(alice),10(wheel) alice:x:1000:1000:Alice Smith:/home/alice:/bin/bash
idshows the UID, primary group (gid), and all groups. The/etc/passwdline is the account record:name:x:UID:GID:comment:home:shell. Thexmeans the password hash lives elsewhere — in/etc/shadow(readable only by root).- 0 —
Create a user
Make an account that can actually log in.
useraddcreates the account. The bare form does the minimum; in practice you almost always want a home directory and a login shell.sudo useradd -m -s /bin/bash -c "Alice Smith" alice- -m
- Create the home directory (/home/alice) from /etc/skel.
- -d
- Home directory path (default /home/<name>). Records the path; -m is what creates it.
- -s
- Login shell (/bin/bash).
- -c
- Comment / full name (the GECOS field).
- -u
- Force a specific UID.
- -G
- Supplementary groups, comma-separated (covered next).
This writes the /etc/passwd+/etc/shadow+/etc/grouprecords, copies/etc/skelinto the new home, and sets ownership. On RHEL a matching user-private group (alice) is created as the primary group.Service accounts are the other kind of user you create: an identity for a daemon (a web app, a backup job, a report worker) so it does not run as root and owns only its own files. Nobody logs in as it. Four flags make one:
- `-r` — a system account: a UID from the system range below 1000, and no home directory unless you ask for one, whatever
/etc/login.defssays. - `-d <path>` — the home directory written into
/etc/passwd. Without it you get/home/<name>; services usually live under/srvor/var/lib.-donly records the path. - `-m` creates that directory (copying
/etc/skelinto it); `-M` says explicitly don't. You need-Mmainly on RHEL, whereCREATE_HOME yesin/etc/login.defsgives regular accounts a home even without-m; Ubuntu creates none unless you pass-m. - `-s /usr/sbin/nologin` — a shell that prints
This account is currently not available.and exits, so even with a password or a key nobody gets a shell as this user.
useradd -r -m -d /srv/reportd -s /usr/sbin/nologin reportd getent passwd reportd stat -c '%U %F' /srv/reportd userdel -r reportdreportd:x:999:999::/srv/reportd:/usr/sbin/nologin reportd directory userdel: reportd mail spool (/var/mail/reportd) not found
- -r
- System account: UID below 1000, no home unless -m.
- -m / -M
- Create the home directory / explicitly don't.
- -d
- Home directory path stored in /etc/passwd.
- -s
- Login shell; /usr/sbin/nologin refuses interactive logins.
Create the account, read its record back, check the home, then remove it so the box is as you found it. getent passwdreads the account the way the system resolves it (local files, plus LDAP or SSSD if the box uses them), so it is the honest check, better than grepping/etc/passwd. The fields arename:x:UID:GID:comment:home:shell: a UID under 1000 (useradd -rtakes the highest free one, so the number differs from box to box), home/srv/reportd, shell/usr/sbin/nologin.statconfirms-mmade the directory and gave it toreportd.userdel -rremoves the account, its group and its home; themail spool ... not foundline is harmless, because a system account never gets a mailbox. Drop-rand use/bin/bashas the shell, and the same-m -d -strio gives a regular user a home outside/homein one command.Check yourself
Which useradd flag creates the user's home directory?
Check yourself
You run
useradd -r -d /srv/app -s /usr/sbin/nologin app. getent shows home /srv/app, but the directory doesn't exist. Which flag did you leave out?Passwords and aging
Set, inspect, lock, and expire passwords.
A brand-new account exists but can't log in until it has a password — and passwords aren't just set-and-forget. In any managed environment they also have a lifecycle: they expire, they get force-reset, and accounts get temporarily disabled without being deleted. Two tools own this: `passwd` sets and locks the password itself, and `chage` (change age) manages the timing rules. Both ultimately write to
/etc/shadow; the commands are just the safe front door to that file.sudo passwd alice; sudo passwd -S aliceChanging password for user alice. New password: Retype new password: passwd: all authentication tokens updated successfully. alice PS 2026-06-23 0 99999 7 -1 (Password set, SHA512 crypt.)
- -S
- Status: PS = set, LK = locked, NP = no password.
- -l
- Lock the account (prepends ! to the hash).
- -u
- Unlock it.
- -e
- Expire now — force a change at next login.
passwdsets the hash in/etc/shadow;-Sreports state. Locking (passwd -l) puts a!in front of the stored hash so no entered password can ever match — a reversible disable that keeps the account and its files intact.sudo chage -l alice; sudo chage -M 90 aliceLast password change : Jun 23, 2026 Password expires : never Password inactive : never Account expires : never Maximum number of days between password change : 99999
- -l
- List aging info (last change, max/min days, expiry).
- -M 90
- Max password age — force a change every 90 days.
- -E 2026-12-31
- Account expiration date.
- -d 0
- Force a password change at next login.
chagemanages password aging (all stored in/etc/shadow).-M 90is the common policy knob;chage -d 0 aliceis the tidy way to force a reset on first login. (passwd -edoes the same thing.)Check yourself
Which command disables password login for an account without deleting it or its files?
Groups: primary vs supplementary
Master the one group distinction that trips everyone up.
A user has exactly one primary group and any number of supplementary groups.
- Primary group — the group stamped on new files you create (your default team).
- Supplementary groups — extra memberships that grant access to other things (extra rooms you can enter), e.g.
wheelfor sudo ordockerto use containers.
idshows both:gid=is primary,groups=lists them all.Why the distinction matters in practice: when alice creates a file, it's owned by her primary group, so that's who else gets group access to it by default. Her supplementary groups don't change what she creates — they change what she can reach that others made. Mixing these up is why 'I added them to the shared group but they still can't write the file' happens: the group is supplementary, but the file was stamped with someone's primary group.
Example — not runnable on your lab box
sudo groupadd developers; sudo usermod -aG developers,docker alice- -a
- APPEND to the user's supplementary groups.
- -G
- The supplementary group list.
- -g
- (lowercase) set the PRIMARY group instead.
groupaddmakes a group;usermod -aGadds the user to supplementary groups. New group membership takes effect on the user's next login (their current shell keeps the old set until they re-log).Check yourself
Which usermod invocation adds alice to the wheel group WITHOUT removing her existing groups?
Grant admin rights with sudo
Give a user root powers safely — and understand what actually grants them.
Rather than hand out the root password, you grant sudo. You'll hear the shortcut "add them to the `wheel` group on RHEL/Fedora (the `sudo` group on Debian/Ubuntu)" — and it works — but it's worth understanding why that group grants anything, because the group itself is powerless.
wheelis an ordinary Unix group. What makes it privileged is one line of policy, shipped in the sudoers file:`%wheel ALL=(ALL) ALL
`That line is the whole mechanism. Adding alice to
wheeldoesn't hand her powers — it puts her on the left-hand side of that rule. The distro split is the same story:wheelvssudodiffer only because the shipped sudoers policy names a different group, not because the kernel treats either group specially.Example — not runnable on your lab box
sudo visudo## Allow members of group wheel to run any command %wheel ALL=(ALL) ALL # Examples you might add: # bob ALL=(ALL) NOPASSWD: ALL # carol ALL=(ALL) /usr/bin/systemctl restart nginx # %developers ALL=(ALL) /usr/bin/docker
This is the policy the shortcut relies on. A rule is who WHERE=(AS-WHOM) WHAT:%wheelmeans the group,(ALL)any target user, and the last field the allowed commands (restrict it to specific binaries for least privilege). Read it as: this `%wheel` line is the reason the group matters. Uncomment the%developersexample anddevelopersbecomes exactly as privileged aswheel; delete the%wheelline andwheelgrants nothing at all. Always edit sudoers only with `visudo`, which syntax-checks before saving; put custom rules in a drop-in withsudo visudo -f /etc/sudoers.d/developers.Example — not runnable on your lab box
sudo usermod -aG wheel aliceNow the shortcut makes sense: this puts alice on the left-hand side of the %wheelrule, so she can run commands withsudo(entering her own password, not root's). Group membership is the auditable, easily-revoked way to grant it. She must log out and back in for the new group to take effect.Check yourself
You remove alice from the wheel group, but she can still run
sudo systemctl restart nginx. The%wheelline is unchanged. Where do you look to find what's still granting her that?The other 'wheel': who may su to root
Know that gating su to root is a separate PAM decision, invisible from sudoers.
wheelhas an older, second meaning that predates sudo and has nothing to do with it. Historically the point of thewheelgroup was to control who was even allowed to run `su` and become root — a locked door, not a permission list. That gate still exists on Linux, but it lives in PAM (Pluggable Authentication Modules), configured in/etc/pam.d/su— a completely different place from sudoers. Reading/etc/sudoerstells you nothing about it, which is exactly why it's easy to miss.Example — not runnable on your lab box
grep pam_wheel /etc/pam.d/su# auth required pam_wheel.so use_uid
Most distros ship this line commented out, so by default anyone who knows the root password can su. Uncomment it andsuto root is restricted to members of thewheelgroup — the classic 'wheel gate.' Note this issu's config, not sudo's:su(1)from util-linux states plainly that 'support for a wheel group has to be configured via PAM,' so it's invisible if you only ever read/etc/sudoers. (use_uidchecks the caller's real UID rather than the name they logged in under.)Check yourself
A box lets any user with the root password run
su, but you want only wheel members to be able to. Which file do you edit — /etc/sudoers or /etc/pam.d/su?Practice in your live terminal
Do it, don't just read it — these run on the real sandbox to your right.
You have a real root shell. Create a user end-to-end, add them to a group the right way, and verify — the exact loop a "create the account and grant access" lab grades.
useradd -m -s /bin/bash -c 'Test User' tuser; id tuserCreate the account with a home and shell, then confirm its UID and primary group. (No sudo needed — you're already root in the lab.) getent group sudo || getent group wheelBefore you grant anything, find out which admin group THIS box uses. RHEL and Fedora ship wheel; Debian and Ubuntu shipsudo— a given box has one of them, not both.getentprints the group's line if it exists and nothing if it doesn't, so whichever line comes back is the name you want. Checking first is the habit; assuming is howusermod: group 'wheel' does not existhappens.groupadd devs; if getent group sudo >/dev/null; then admin=sudo; else admin=wheel; fi; usermod -aG devs,$admin tuser; id tuserThe same grant, with the admin group read off the box instead of hard-coded. The ifsets$adminto whichever group the last block found —sudoon this lab image,wheelon a RHEL box — thenusermod -aGappends tuser to devs AND that group (note-aG), andidverifies both now appear. Written this way the command is correct on either distro, which is exactly why you looked the group up first.passwd -S tuser; chage -M 60 tuser; chage -l tuser | head -4Check password status (locked until set), set a 60-day max age, and read the aging back. Run passwd tuserto set a password and watch the status flip to PS.
- Linux identifies users by UID, not name (0 = root, 1–999 system, 1000+ regular); accounts live in /etc/passwd, hashes/aging in /etc/shadow, groups in /etc/group.
- useradd -m -s creates a usable account, but it's LOCKED until you run passwd. A service account is useradd -r -d <home> -s /usr/sbin/nologin (add -m to create the home; -d only records it) — confirm with getent passwd. userdel -r removes the home too.
- One primary group (stamps new files) + many supplementary (extra access). usermod -aG appends — drop the -a and you REPLACE the whole set.
- Grant admin by adding to wheel (RHEL) / sudo (Debian) — but the privilege is the
%wheel ALL=(ALL) ALLline in sudoers, not the group name; delete the line and the group is powerless. Edit rules only with visudo, and audit /etc/sudoers.d/ too. Gating who maysuto root is a separate PAM decision (pam_wheel in /etc/pam.d/su), invisible from sudoers. chage manages password aging; passwd -l/-u lock/unlock.
| Task | Command |
|---|---|
| Create user with home | useradd -m -s /bin/bash alice |
| Create a service account | useradd -r -m -d /srv/app -s /usr/sbin/nologin app |
| Set / require password | passwd alice · chage -d 0 alice |
| Add to group (append!) | usermod -aG wheel alice |
| Set primary group | usermod -g devs alice |
| Lock / unlock | passwd -l alice · passwd -u alice |
| Delete with home | userdel -r alice |
| Grant sudo / edit rules | add to wheel · visudo |
