Understanding the multi-user and superuser concepts, managing user accounts and groups with useradd, usermod, userdel, and passwd, reading the contents of /etc/passwd, /etc/shadow, and /etc/group, through to building a deploy user with limited rights that is securely locked down.

After episode 7 where we covered symlinks, archives, and compression — how to protect data with backups — in this episode we'll shift from protecting data to protecting access: user & group management.
Why is this topic important? Linux has been a multi-user system since birth. One server serves many users — humans, processes, services, even applications — and each entity must have a clear identity and access rights. Imagine a production server without user management: everyone logs in as root, there's no trace of who did what, and a single mistake can destroy the entire system. User management is the first line of defense between you and disaster.
In this episode we'll cover: first, the multi-user and superuser concepts; second, the core user management commands; third, group management commands; fourth, reading the three key files /etc/passwd, /etc/shadow, and /etc/group; fifth, a case study building a secure deploy user.
Linux is designed as a multi-user system: many users can live on one machine simultaneously, each with their own identity (UID), home directory, and access rights. This isn't just a feature — it's the security model. Because every process runs on behalf of a user, the system always knows who did what.
Above all users stands root (UID 0), the superuser with unlimited rights. Root can read, write, and delete anything, anywhere. Here's an analogy: in a building, every employee has an access card limited to certain floors (regular users), while root is the master key that opens every door.
Warning
Working as root for routine tasks is one of the worst habits in Linux. A single wrong command — for example rm -rf /var when you meant rm -rf /var/log — immediately destroys the system without confirmation, because there's no permission layer holding you back. The professional practice: log in as a regular user, elevate privileges only when needed with sudo. This limits the blast radius of every mistake.
useradd vs adduser: Distribution DifferencesThere are two ways to create a user, and the difference depends on the distro family:
sudo adduser budiadduser is a friendly script that asks questions interactively and creates the home and group at the same time; useradd is a low-level utility that works non-interactively — suitable for scripts. On Ubuntu, useradd also exists, but it doesn't automatically create a home without -m.
| Command | Function |
|---|---|
useradd | Create a user (low level) |
adduser | Create a user (interactive script, Debian/Ubuntu) |
usermod | Modify user attributes |
userdel | Delete a user |
passwd | Set/change passwords |
id | Show a user's UID/GID and groups |
su / sudo | Switch user / elevate privileges |
Example of creating a user with important options:
sudo useradd -m -s /bin/bash -c "Budi Santoso - Developer" budi
sudo passwd budi
sudo id budiuseradd option | Function |
|---|---|
-m | Create the home directory (/home/budi) |
-s | Specify the default shell (e.g. /bin/bash) |
-c | Short comment/description |
-G | Add to supplementary groups |
-e | Account expiry date (YYYY-MM-DD) |
usermodusermod modifies an existing user. The most used option: -aG to add a user to supplementary groups.
sudo usermod -aG sudo budi
sudo usermod -aG docker budi
sudo id budiCaution
The difference between -G and -aG is one of the most expensive traps in user management. usermod -G docker budi overwrites the entire list of a user's supplementary groups — if budi was previously in the sudo and devs groups, both are lost and replaced with only docker. usermod -aG (append) adds to the existing list. Always write -aG, not -G, unless you really want a total replacement. The golden rule: -a together with -G, always.
userdelsudo userdel budi
sudo userdel -r budiWithout -r, the user's home directory and mailbox remain behind — the account is gone, but its traces are scattered. With -r, the home and mailbox are deleted too. Think carefully before using -r: if it's the only copy of a user's data, that data will be permanently lost.
Every user has a primary group and can be a member of supplementary groups. Groups are the cleanest way to manage shared permissions — instead of setting per-user access to dozens of files, you set it per-group once, then add the relevant members.
| Command | Function |
|---|---|
groupadd | Create a group |
groupdel | Delete a group |
groupmod | Modify group attributes |
gpasswd -a user group | Add a user to a group |
gpasswd -d user group | Remove a user from a group |
getent group | Show the group database contents |
sudo groupadd devs
sudo gpasswd -a budi devs
sudo gpasswd -a siti devs
sudo getent group devsdevs:x:1001:budi,sitiThe output above reads: group devs, no password (x), GID 1001, members budi and siti. Now a single chmod command (episode 9) on the devs group directory will set access for both of them at once.
su vs sudo and Password Policiessu vs sudoTwo ways to gain higher privileges — and your choice determines your day-to-day security habits:
su - root
sudo -lsu (switch user) switches identity — you become the target user and must know their password (usually root's). sudo (superuser do) runs a single command as another user (default root) without ever knowing the root password — just your own password, and the permissions are set per-user in the sudoers file. This is why professional practice almost always chooses sudo:
| Aspect | su | sudo |
|---|---|---|
| Password required | Target's password (e.g. root) | Your own user's password |
| Permissions after success | Full, unrestricted | Per-user/per-command in sudoers |
| Audit trail | Not automatically recorded | Recorded in system logs |
| Recommendation | Occasionally, senior admins | Standard for daily work |
su - root is also useful when you genuinely want a full root session (for example recovering a system) — but for one or two commands, sudo is far safer and auditable.
chageA password that never expires is a time bomb. chage (change age) manages password age and grace periods:
sudo chage -M 90 -m 7 -W 14 budi
sudo chage -l budichage option | Meaning |
|---|---|
-M | Maximum days before the password must be changed |
-m | Minimum days before the password can be changed |
-W | Warning days before expiration |
-I | Grace days after expiration before the account is locked |
-l | Show the current age policy |
In the example above, -M 90 forces a password change every 90 days, -m 7 prevents quick re-changes, and -W 14 warns two weeks in advance. The combination of passwd (setting the password), chage (managing its age), and passwd -l/-u (locking/unlocking accounts) gives you full control over the entire account lifecycle.
Note
Password policy is a balance between security and convenience. For systems whose authentication is based on SSH keys (not passwords), forcing a password change every 90 days is often irrelevant — well-managed keys that are revoked when unused are actually more secure. Adjust the chage policy to the authentication model you actually use, rather than just copying a checklist.
All user and group information is stored in text files you can read directly. This isn't a hidden binary database — it's the classic "everything is a file" Linux philosophy.
/etc/passwd — The User Listroot:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
budi:x:1000:1000:Budi Santoso:/home/budi:/bin/bash| Field | Contents |
|---|---|
| 1 | User name |
| 2 | x — the actual password is not here, but in /etc/shadow |
| 3 | UID (User ID) — 0 is root |
| 4 | GID (Group ID) of the primary group |
| 5 | Comment/GECOS (full name, description) |
| 6 | Home directory |
| 7 | Default shell — /usr/sbin/nologin means the user can't log in |
Notice: passwords are never stored here — the second column is only an x placeholder. This is a safety net: /etc/passwd must be readable by all programs, so storing password hashes there would leak them to anyone. The hashes moved to /etc/shadow, which is only readable by root.
/etc/shadow — Passwords and Policyroot:!$6$abC...hash:19501:0:99999:7:::
budi:$6$xyz...hash:19501:0:99999:7:::
siti:!:19501:0:99999:7:::| Field | Contents |
|---|---|
| 1 | User name |
| 2 | Password hash — ! or * means the account is locked |
| 3 | Last password change day (epoch days format) |
| 4 | Minimum days before the password can be changed |
| 5 | Maximum days before the password must be changed |
| 6 | Warning days before expiration |
| 7 | Grace days after expiration |
| 8 | Account expiry date |
The ! prefix before a hash is an important marker: the account is locked and can't be used to log in.
/etc/group — The Group Listroot:x:0:
devs:x:1001:budi,siti
docker:x:999:devnullField 4 contains supplementary members; members whose primary group is that group don't need to be listed here.
Tip
A quick-reading trick: grep (from episode 6) works perfectly on these files. grep budi /etc/passwd to see a user's line, cut -d: -f1 /etc/passwd for a list of all usernames, and awk -F: '$3 >= 1000 {print $1}' /etc/passwd to get only human users (UID ≥ 1000) — not system users. Always remember: UID < 1000 generally means system/service accounts, not humans.
Now let's chain all the concepts in a real DevOps scenario: creating a deploy user used by a CI/CD pipeline to copy applications to the server — with limited rights, not root.
Step 1 — create the user with home and shell:
sudo useradd -m -s /bin/bash -c "Pipeline deploy account" deploy
sudo passwd deployStep 2 — create a group for sharing the application directory, then add deploy:
sudo groupadd webapps
sudo usermod -aG webapps deployStep 3 — if the pipeline needs to manage services, give it restricted sudo access through the sudoers file, not full root (more detail in the hardening episode). For this session, lock the user with passwd -l if the pipeline uses SSH keys:
sudo passwd -l deploy
sudo passwd -u deploypasswd -l locks the account (puts a ! before the hash in /etc/shadow) so password logins are rejected; passwd -u reopens it. This technique is used to "park" an account without deleting it.
Important
Locking an account with passwd -l rejects password-based logins, but it does not cut off already-running access — an active SSH session stays alive, and SSH key-based logins (without passwords) can usually still work depending on the configuration. To revoke access entirely, terminate running sessions and revoke the keys. For accounts no longer used at all, consider userdel — not just locking.
| Mistake | Symptom | Solution |
|---|---|---|
usermod -G without -a | User's supplementary groups suddenly gone | Always usermod -aG |
userdel without -r | User's home and mailbox left behind | Use -r if the account is truly being discarded |
| Working daily as root | Small mistakes have systemic impact | Log in as a regular user + sudo |
Creating a user without -m | No home directory | Add -m |
passwd -l while sessions are still active | Access not actually cut off | Terminate sessions + revoke keys |
Manually editing /etc/shadow | Corrupted hash, account can't log in | Use passwd, usermod, chage |
Putting a password in /etc/passwd | Password leaks to all readers | Always via passwd (goes into /etc/shadow) |
In this episode 8, we've covered the multi-user concept and the dangers of root, core user management commands (useradd, adduser, usermod, userdel, passwd), group management (groupadd, gpasswd, getent), the three key files /etc/passwd, /etc/shadow, and /etc/group, and a case study building a deploy user with limited rights and a lockable account.
Key takeaways:
usermod -aG, not -G, to add groups without overwriting.userdel -r to clean up the home; without it, account traces remain./etc/passwd for identity, /etc/shadow for passwords, /etc/group for membership — and all of them readable with grep/cut/awk.passwd -l locks an account, userdel discards it — choose per your needs.User and group identity is half of the security model; the other half is what they're allowed to do to files. In the next episode 9, we'll discuss File Permissions & Ownership — understanding the permission bits (read, write, execute), octal and symbolic chmod, chown, umask, through to the special bits SUID, SGID, and the sticky bit, and practice securing SSH keys and shared directories. Stay motivated, because this is the core of security that will color the rest of your career in Linux!