You need a Linux machine where you can use sudo, and
you should not practise on a server anyone depends on. The commands
here change real system state. A spare machine, a virtual machine, or a
cloud instance you can rebuild is the right place; a laptop you own is
fine too. If the terminal itself is new to you, do
Introduction to the
Linux Terminal first — it takes about ten minutes and everything
below assumes it. Every step tells you how to undo it.
Why Accounts Are a Security Control
Every user account on a machine is a potential way in. Accounts accumulate: a colleague who left, a service you trialled once, a "temp" login created during an emergency. Each one has a password that may be weak, may be reused, and is almost certainly no longer being watched.
Good account hygiene is therefore not administrative tidiness — it is one of the cheapest security controls available. This tutorial covers creating accounts correctly, grouping them so permissions stay manageable, and — the part most often skipped — removing them properly.
The Files Behind the Commands
Three files hold everything. You will almost never edit them by hand, but knowing what they contain makes every command below make sense.
/etc/passwd— one line per account: username, UID, GID, home directory and login shell. Despite the name it holds no passwords and is world-readable/etc/shadow— the password hashes and ageing information. Readable only by root. This is the file that actually matters/etc/group— group names and their member lists
Look at your own entry:
getent passwd $USER
id
id shows your UID, your primary group and every supplementary group you belong
to. Groups are how Linux grants shared access without handing out root.
Privilege comes from the numeric UID, not the username. Any account with UID 0 is root,
whatever it is called. A second UID-0 account is a classic backdoor, and worth checking
for: awk -F: '$3==0 {print $1}' /etc/passwd should print only
root.
Creating an Account
On Debian and Ubuntu, prefer adduser. It is a friendly wrapper that creates the
home directory, sets sensible defaults and prompts for a password:
sudo adduser alice
useradd is the lower-level tool present on every distribution. It does far less
by default — notably it will not create a home directory unless you ask:
sudo useradd -m -s /bin/bash alice
sudo passwd alice
-m— create the home directory (omitting this is the most common mistake)-s /bin/bash— set the login shell-G groupname— add supplementary groups at creation time
Groups: Grant Access Without Granting Root
When several people need the same access, put them in a group and grant the group — never copy permissions onto each account individually.
sudo addgroup developers
sudo usermod -aG developers alice
-a in usermod -aG is not optional.
usermod -G developers alice replaces every supplementary group
Alice belongs to. Forgetting -a is how administrators accidentally remove
their own sudo membership and lock themselves out. Always
-aG.
Group changes only take effect in a new login session. Confirm with
id alice rather than assuming.
Locking, Expiring and Auditing
Locking is usually better than deleting: it stops the login immediately while preserving file ownership and the audit trail.
sudo usermod -L alice # lock the password
sudo usermod -U alice # unlock it again
Locking the password does not block SSH key logins. To disable an account completely, also set the shell to a non-login shell:
sudo usermod -s /usr/sbin/nologin alice
Password ageing and expiry are handled by chage:
sudo chage -l alice # show current settings
sudo chage -E 2026-12-31 alice # expire the account on a date
sudo chage -M 90 alice # require a password change every 90 days
Useful audit questions, answered directly:
awk -F: '$3>=1000 && $3<65534 {print $1}' /etc/passwd # real human accounts
sudo awk -F: '($2=="") {print $1}' /etc/shadow # accounts with EMPTY passwords
lastlog | sort -k4 # who has never logged in
last -n 20 # recent successful logins
Removing an Account Properly
Lock the account and leave it for a few weeks. Deletion is irreversible and you will not discover what depended on it until afterwards.
sudo find / -user alice -not -path "/proc/*" 2>/dev/null. Files owned by
a deleted UID become orphaned, and a future account reusing that UID silently inherits
them.
sudo crontab -l -u alice and ps -u alice. A cron job owned by
a deleted user fails silently.
sudo deluser --remove-home alice on Debian/Ubuntu, or
sudo userdel -r alice elsewhere. Back up the home directory first if there
is any chance it holds something needed.
Service Accounts
Software that runs as a daemon should have its own account that no human can log into. That way a compromise of the service does not hand over a usable shell.
sudo useradd --system --no-create-home --shell /usr/sbin/nologin myapp
--system— allocates a low UID, outside the human range, and skips ageing--shell /usr/sbin/nologin— no interactive login, ever--no-create-home— most services need a data directory, not a home
Now Do It Yourself: Five Steps
You will create a real user account, inspect exactly what the system recorded, add the account to a group, and remove it again cleanly. Every output below was produced by running these commands — inside an isolated namespace, so no real account was touched, but the commands and their output are the genuine ones.
Go: open a terminal on the machine you are practising on.
Do: run cat /etc/passwd | tail -5, then run id on its own.
You should see: the last few account lines, each with seven fields separated by colons, and then your own identity — something like uid=1000(yourname) gid=1000(yourname) groups=1000(yourname),27(sudo). Note /etc/passwd is world-readable and holds no passwords despite the name; the x in the second field means the password hash lives elsewhere, in /etc/shadow, which only root can read.
If not: if id does not list sudo (or wheel on Red Hat-family systems) among your groups, you cannot run the rest of this page — every remaining step needs administrative rights. ⚠️ Never cat /etc/shadow to "have a look". It contains password hashes, and displaying them puts them in your scrollback and shell history.
Go: same terminal.
Do: run these two commands.
sudo useradd -m -s /bin/bash alice
grep "^alice" /etc/passwd
You should see: a line like alice:x:1001:1002::/home/alice:/bin/bash. Read the fields in order: name, the x placeholder, user id, primary group id, an empty comment field, home directory, login shell. -m is what creates the home directory — without it the account exists but has nowhere to live, and the user gets confusing errors at first login. -s sets the shell.
If not: useradd: user 'alice' already exists means it is there from an earlier attempt; skip to step 5 and remove it first. If the command is not found at all, you may be on a system where the tool is adduser — that is a friendlier wrapper around the same thing and will prompt you interactively.
Go: same terminal.
Do: run grep "^alice" /etc/group, then id alice, then ls -ld /home/alice.
You should see: a group line alice:x:1002:, then uid=1001(alice) gid=1002(alice) groups=1002(alice), then a home directory owned by alice. Most Linux systems give every new user a private group of their own name — that is what makes a default file mode of 664 safe, because "group" means only that one person.
If not: if id alice reports no such user while the /etc/passwd line is clearly there, you are looking at a cached lookup; that is rare, and getent passwd alice asks the system properly rather than reading the file directly. On a machine using central logins, getent is the command that tells the truth.
Go: same terminal.
Do: run these three commands.
sudo groupadd developers
sudo usermod -aG developers alice
id alice
You should see: uid=1001(alice) gid=1002(alice) groups=1002(alice),1003(developers) — both groups listed.
If not: 🔴 if a group you added earlier has vanished, you left out the -a. Verified: after usermod -G testers alice the account reads groups=1002(alice),1004(testers) — developers is simply gone. Your primary group survives, because it is not a supplementary one, which is exactly what makes the damage easy to miss at a glance. usermod -G replaces every supplementary group; -aG appends. This is the classic way an administrator removes their own sudo access by accident and cannot get it back without a rescue boot. Always write -aG, and check with id immediately afterwards. Note also that group changes only take effect at the user's next login — an open session keeps the groups it started with.
Go: same terminal.
Do: run sudo userdel -r alice, then grep -c "^alice" /etc/passwd.
You should see: possibly a note that a mail spool was not found, which is harmless, and then 0 — no matching line remains. -r removes the home directory too; without it the account disappears but its files stay behind owned by a user id that no longer exists, which is how orphaned files accumulate on long-lived servers.
If not: userdel: user alice is currently used by process ... means alice is logged in or running something. Deal with that first rather than forcing it. ⚠️ Before -r on any real account, check what is about to be deleted with ls -la /home/alice — on a real machine that folder may be the only copy of someone's work, and there is no recycle bin.
Without scrolling up: what is the difference between usermod -G and
usermod -aG, and why does it matter more than any other flag on this page?
Answer: -G replaces all supplementary groups, -aG adds to
them. Getting it wrong on your own account can remove your sudo membership
and lock you out of administering the machine.
Now do it without the page: create a user bob with no
home directory and no login shell — the shape used for service accounts that must
never log in — then confirm from /etc/passwd that both are as you
intended, and remove him. You will need -s /usr/sbin/nologin and to leave
-m off.
Summary
- Every account is an entry point — the ones nobody watches are the dangerous ones
- Privilege is the UID, not the name — only
rootshould have UID 0 - Always
usermod -aG— omitting-awipes existing group membership - Lock before you delete, and remember locking a password does not stop SSH keys
- Find owned files first — orphaned UIDs get silently inherited
- Service accounts get
nologin, never a shell
List accounts with UID ≥ 1000, check lastlog for logins that never
happened, and confirm nothing but root holds UID 0. On most machines that
takes two minutes and finds at least one account nobody remembers creating.