Signal9Signal9 — home
online
all lessons

Users & Groups: Account Management

Beginner35 min7 steps
What you'll learn
  • 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
  1. 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/passwd
    uid=1000(alice) gid=1000(alice) groups=1000(alice),10(wheel)
    alice:x:1000:1000:Alice Smith:/home/alice:/bin/bash
    id shows the UID, primary group (gid), and all groups. The /etc/passwd line is the account record: name:x:UID:GID:comment:home:shell. The x means the password hash lives elsewhere — in /etc/shadow (readable only by root).
  2. Create a user

    Make an account that can actually log in.

    useradd creates 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/group records, copies /etc/skel into 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.defs says.
    • `-d <path>` — the home directory written into /etc/passwd. Without it you get /home/<name>; services usually live under /srv or /var/lib. -d only records the path.
    • `-m` creates that directory (copying /etc/skel into it); `-M` says explicitly don't. You need -M mainly on RHEL, where CREATE_HOME yes in /etc/login.defs gives 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 reportd
    reportd: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 passwd reads 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 are name:x:UID:GID:comment:home:shell: a UID under 1000 (useradd -r takes the highest free one, so the number differs from box to box), home /srv/reportd, shell /usr/sbin/nologin. stat confirms -m made the directory and gave it to reportd. userdel -r removes the account, its group and its home; the mail spool ... not found line is harmless, because a system account never gets a mailbox. Drop -r and use /bin/bash as the shell, and the same -m -d -s trio gives a regular user a home outside /home in 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?

  3. 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 alice
    Changing 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.
    passwd sets the hash in /etc/shadow; -S reports 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 alice
    Last 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.
    chage manages password aging (all stored in /etc/shadow). -M 90 is the common policy knob; chage -d 0 alice is the tidy way to force a reset on first login. (passwd -e does the same thing.)

    Check yourself

    Which command disables password login for an account without deleting it or its files?

  4. 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. wheel for sudo or docker to use containers.

    id shows 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.
    groupadd makes a group; usermod -aG adds 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?

  5. 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. wheel is 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 wheel doesn't hand her powers — it puts her on the left-hand side of that rule. The distro split is the same story: wheel vs sudo differ 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: %wheel means 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 %developers example and developers becomes exactly as privileged as wheel; delete the %wheel line and wheel grants nothing at all. Always edit sudoers only with `visudo`, which syntax-checks before saving; put custom rules in a drop-in with sudo visudo -f /etc/sudoers.d/developers.

    Example — not runnable on your lab box

    sudo usermod -aG wheel alice
    Now the shortcut makes sense: this puts alice on the left-hand side of the %wheel rule, so she can run commands with sudo (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 %wheel line is unchanged. Where do you look to find what's still granting her that?

  6. The other 'wheel': who may su to root

    Know that gating su to root is a separate PAM decision, invisible from sudoers.

    wheel has an older, second meaning that predates sudo and has nothing to do with it. Historically the point of the wheel group 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/sudoers tells 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 and su to root is restricted to members of the wheel group — the classic 'wheel gate.' Note this is su'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_uid checks 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?

  7. 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 tuser
    Create 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 wheel
    Before you grant anything, find out which admin group THIS box uses. RHEL and Fedora ship wheel; Debian and Ubuntu ship sudo — a given box has one of them, not both. getent prints 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 how usermod: group 'wheel' does not exist happens.
    groupadd devs; if getent group sudo >/dev/null; then admin=sudo; else admin=wheel; fi; usermod -aG devs,$admin tuser; id tuser
    The same grant, with the admin group read off the box instead of hard-coded. The if sets $admin to whichever group the last block found — sudo on this lab image, wheel on a RHEL box — then usermod -aG appends tuser to devs AND that group (note -aG), and id verifies 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 -4
    Check password status (locked until set), set a 60-day max age, and read the aging back. Run passwd tuser to set a password and watch the status flip to PS.
Recap
  • 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) ALL line 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 may su to 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
TaskCommand
Create user with homeuseradd -m -s /bin/bash alice
Create a service accountuseradd -r -m -d /srv/app -s /usr/sbin/nologin app
Set / require passwordpasswd alice · chage -d 0 alice
Add to group (append!)usermod -aG wheel alice
Set primary groupusermod -g devs alice
Lock / unlockpasswd -l alice · passwd -u alice
Delete with homeuserdel -r alice
Grant sudo / edit rulesadd to wheel · visudo