useradd, one account per page
Twenty-eight lessons on Linux user accounts, one command or one concept per page: what a user account actually is, the uid and the name; the seven fields of /etc/passwd; useradd and its honest flags; the home directory and /etc/skel; why the hashes moved to /etc/shadow; passwd the command and aging with chage; usermod and renaming honestly; userdel and the orphaned home; locking an account; groups, /etc/group and gshadow; su and sudo; the sudoers grammar; root as uid 0; one service account built safely; the login audit trail; the honest limits; and teaching a friend the passwd file in one sitting.
One account, one page, one real capture. That's the rhythm.
useradd, one account per page
Twenty-eight lessons on Linux user accounts, one command or one concept per page: what a user account actually is, the uid and the name; the seven fields of /etc/passwd; useradd and its honest flags; the home directory and /etc/skel; why the hashes moved to /etc/shadow; passwd the command and aging with chage; usermod and renaming honestly; userdel and the orphaned home; locking an account; groups, /etc/group and gshadow; su and sudo; the sudoers grammar; root as uid 0; one service account built safely; the login audit trail; the honest limits; and teaching a friend the passwd file in one sitting.
Set in Space Grotesk, Inter and JetBrains Mono (SIL Open Font License).
Every fact in this book is as the official source states it, fetched and read during this build: the local shadow-utils 4.13 manual pages for useradd, usermod, userdel, groupadd, passwd the command, passwd the file, shadow, group, gshadow, su, sudoers, vipw, chage and lastlog (the definition of truth for this book), and the Wikipedia articles Passwd, Sudo, Su (Unix) and User identifier. No facts are sourced from Reddit, Stack Overflow, vendor blogs or commercial sites. Every command and output pair was run on this machine (Ubuntu, the shadow-utils 4.13 suite, sudo 1.9.15p5) against a throwaway lab tree under a scratch directory, through the documented --root flag: no real user on this host was created, modified or deleted, no password of any real account is typed, shown or reset, and the real /etc files were read or stat-ed but never written. The single hash shown was built by openssl passwd as a throwaway for a lab-only account; hashing schemes are the openssl companion book's chapter, remote login the ssh companion book's. UIDs, GIDs and day numbers are this build's real lab values. Honest notes: useradd -D does not combine with --root on this build (usage, exit 2), so that display ran read-only; usermod's process check surfaced as opendir /proc because the lab tree has none; lastlog here is an honest 292 bytes. An independent guide, not affiliated with or endorsed by the shadow-utils project, Sudo, or the Wikimedia Foundation.
Your purchase is for personal use only. You do not have redistribution rights: please do not share, resell, or republish this book or its pages.
© 2026 Steve Hodgkiss. All rights reserved. Personal use only; no redistribution rights.
Edition 1.0 · stevehodgkiss.net
Contents
Per the passwd(5) manual page, /etc/passwd contains one line for each user account, with seven fields delimited by colons: login name, optional encrypted password, numerical user ID, numerical group ID, user name or comment field, user home directory, and optional user command interpreter; if the password field is a lower-case x, the encrypted password is actually stored in the shadow file instead, and there must be a corresponding line in /etc/shadow or else the user account is invalid. This machine's capture: useradd -m -c "Demo One" demo1 in the lab wrote demo1:x:1001:1001:Demo One:/home/demo1:/bin/sh.
The passwd line
One account, seven fields, six colons: name, password, uid, gid, comment, home, shell, per passwd(5). Read them left to right and the line stops being noise.
The second field here is a lower-case x: the real hash lives in /etc/shadow, and without a matching shadow line the account is invalid.
Our capture, built by useradd in the lab: demo1:x:1001:1001:Demo One:/home/demo1:/bin/sh.
Print your own line, grep "^$USER:" /etc/passwd, then name all seven fields aloud.
Per the useradd(8) manual page, -m creates the user's home directory and the skeleton directory will be copied to it, -k SKEL_DIR is only valid if the -m option is specified, the skeleton default is /etc/skel, if possible the ACLs and extended attributes are copied, and the system administrator is responsible for placing the default user files in /etc/skel. This machine's captures: the lab skel holds .bash_logout, .bashrc and .profile, and after useradd -m the lab home demo1 held exactly the same three names.
The skeleton home
A new home is not empty: -m copies /etc/skel into it, file by file, and even carries ACLs and extended attributes across when it can.
Whose job is the skeleton? The administrator's, the manual page says plainly: default user files are placed in /etc/skel on purpose.
Our capture: lab skel listed .bash_logout, .bashrc, .profile; after useradd -m demo1 the new home listed the same three, same order.
List your /etc/skel, then diff it against your own home's dotfiles.
Per the shadow(5) manual page, each line of the file contains 9 fields separated by colons: encrypted password, date of last password change, minimum password age, maximum password age, password warning period, password inactivity period, account expiration date and a reserved field; the dates are expressed as the number of days since Jan 1, 1970 00:00 UTC, a password field which starts with an exclamation mark means that the password is locked, and this file must not be readable by regular users. This machine's capture: the lab account line demo1:!:20761:0:99999:7:::.
The shadow line
The shadow twin carries the secrets and the calendar: hash, last change, min age, max age, warn, inactive, expiry, reserved, nine fields per shadow(5).
Dates are days since Jan 1, 1970. Our 20761 is this build day, November 4, 2026, and a leading ! means the password is locked.
Our capture: demo1:!:20761:0:99999:7::: straight from the lab shadow, born locked because no password was ever set.
Count the colons in one shadow line of your own, and say what each field holds.
Per the passwd(1) manual page, -l disables a password by changing it to a value which matches no possible encrypted value, but this does not disable the account, as the user may still be able to login using another authentication token, for example an SSH key, and to disable the account administrators should use usermod --expiredate 1, which sets the account's expire date to Jan 2, 1970. Per the usermod(8) manual page, -L puts a '!' in front of the encrypted password and -U removes it. This machine's captures: with a throwaway hash set, passwd -l rewrote the field to ! followed by the hash, passwd -S answered webbit L, and -u restored it; usermod -L and -U did the same.
Locking an account
passwd -l prefixes a bang to the hash: no password can match it, so password login dies. The account itself lives on.
The manual's honest warning: an SSH key may still walk in. To close the account, expire it: usermod --expiredate 1, January 2, 1970.
Our captures: webbit:!$6$labsalt$bdDCX... after -l, passwd -S webbit answering L, and -u removing the bang. Keys versus passwords is the ssh companion book's chapter.
Lock and unlock one lab account, watching the shadow field with grep between each step.
Per the passwd(5) manual page, the numerical group ID field of an account line identifies the primary group of the user. Per the usermod(8) manual page, -G sets the list of supplementary groups, if the user is currently a member of a group which is not listed the user will be removed from the group, and -a, --append adds the user to the supplementary groups, use only with -G. Per the Wikipedia User identifier article, the id command reports the primary and supplementary group identifiers. This machine's captures: usermod --root LAB -aG labteam demo2 filled the member list to labteam:x:4500:demo2, and id ubuntu listed groups=1000(ubuntu),4(adm),24(cdrom),27(sudo),30(dip),105(lxd).
Supplementary groups
Every account has exactly one primary group, field four of its passwd line, and any number of supplementary groups recorded in /etc/group's member lists.
The trap is -G alone: unlisted groups are taken away. Add -a to append, never replace.
Our captures: labteam:x:4500:demo2 after usermod -aG, and id ubuntu showing one primary and five supplementary groups, 27(sudo) among them.
Run id and split your groups list into the primary and the supplementary.
Per the Wikipedia Sudo article, sudo enables a user to run a program with the security privileges of another user, by default the superuser, it originally stood for superuser do, Robert Coggeshall and Cliff Spencer wrote the original subsystem around 1980 at SUNY Buffalo, and users must by default supply their own password for authentication. Per the sudoers(5) manual page, once authenticated the user may use sudo without a password for a short period of time, 15 minutes unless overridden by the timestamp_timeout option. This machine's capture: sudo --version answers Sudo version 1.9.15p5.
sudo, own password
sudo flips the question: your own password, not root's, and the Wikipedia Sudo article dates the idea to around 1980, Buffalo, Coggeshall and Spencer.
One proof buys fifteen minutes of password-free sudo by default, per sudoers(5), unless timestamp_timeout says otherwise.
Our capture: Sudo version 1.9.15p5 on this machine. The name unpacks honestly: superuser do, though it runs as any user a rule names.
Time it: run sudo -v, wait through a meeting, and feel the fifteen minutes expire.
Per this book's plan, the closing lesson teaches one friend the passwd file in one sitting: read one line, name the seven fields, meet its shadow twin, build one account in a lab tree, and end with the guardrails. Per the passwd(5), shadow(5) and useradd(8) manual pages, every step is a documented command or file format. This machine's captures: the teaching strip re-reads the lab's own lines, weblab:x:999:987:lab web service:/home/weblab:/usr/sbin/nologin and labteam:x:4500:demo2, both built during this book.
Teaching a friend
The whole book in one sitting with a friend: id, one line's seven fields, its shadow twin, one lab account, the guardrails. Five steps, one story.
Teach the reading as much as the typing: what does each field hold, and what does a locked bang not stop?
Our captures: the lines they will build look like weblab:x:999:987:lab web service:/home/weblab:/usr/sbin/nologin and labteam:x:4500:demo2. Let them type every line.
Sit with one friend and teach the passwd file in one sitting; they type, you read aloud.