A new starter needs a login, and useradd will happily create one with no home, the wrong shell and no password. Here is how to get it right first time. You will create a regular account with a home directory, a chosen shell and supplementary groups, then verify what changed. It also covers service accounts and how to remove an account once you have checked it owns nothing you need. Allow about fifteen minutes.
sudo, and the passwd package.useradd from shadow-utils 4.13, installed here as package version 1:4.13+dfsg1-4ubuntu3.2. Other distributions can have different defaults.Privilege boundary: Reading defaults is ordinary. Creating or deleting an account changes system identity files and needs elevated privileges.
Start with the read-only form. It prints the values from /etc/default/useradd that fill in any option you leave out:
$ useradd -D
GROUP=100
HOME=/home
INACTIVE=-1
EXPIRE=
SHELL=/bin/sh
SKEL=/etc/skel
CREATE_MAIL_SPOOL=no
LOG_INIT=yes
USERGROUPS_ENAB yes in /etc/login.defs gives a new account a same-named primary group unless you specify -g, -N or -U.login.defs does not enable CREATE_HOME, so do not expect a home directory without -m.Confirm the installed binary and version before you copy examples into automation:
$ command -v useradd
/usr/sbin/useradd
$ dpkg-query -W -f='${Package} ${Version}\n' passwd
passwd 1:4.13+dfsg1-4ubuntu3.2
$ useradd --help | sed -n '1,2p'
Usage: useradd [options] LOGIN
Checkpoint: If your output differs, your local defaults win over this guide.
Tip: On Debian the manpage points administrators at adduser as the usual higher-level tool. useradd is the lower-level utility, used here because you want its options and predictable mechanics.
Use a short name such as ada, not a display name or an email address. This implementation rejects:
$ getent passwd ada
$ getent group ada
Checkpoint: No output means neither name exists in the databases getent consults. Any result is a stop sign: pick another login or investigate the identity service before changing anything.
A name can exist in NIS or LDAP even when a local file search misses it. Let useradd run its normal checks rather than forcing a duplicate with -o; duplicate UIDs make file ownership and access decisions much harder to reason about.
Pick the shell and groups deliberately:
$ sudo useradd -m -s /bin/bash -G audio,video ada
-m creates /home/ada and copies in the contents of /etc/skel.-s sets the login shell.-G adds supplementary groups. Every group must already exist, and the list takes commas but no spaces.With the local defaults above, this also creates a same-named primary group. It does not set a usable password: without -p, the new account is locked with no password defined.
Warning: Do not use -p with a plaintext password. The option expects a crypt-formatted value, and even that value is visible to anyone who can inspect the process list.
Set the password with the normal tool instead, ideally from a controlled terminal:
$ sudo passwd ada
New password:
Retype new password:
passwd: password updated successfully
Tip: For an SSH account, check your organisation's authentication policy before enabling it. Setting a local password does not by itself grant SSH access.
Check the account record, group membership, home directory and shell. All read-only:
$ getent passwd ada
ada:x:1001:1001::/home/ada:/bin/bash
$ id ada
uid=1001(ada) gid=1001(ada) groups=1001(ada),29(audio),44(video)
$ sudo test -d /home/ada && echo 'home directory exists'
home directory exists
$ sudo passwd -S ada
ada P ...
Checkpoint: The passwd record names the expected home and shell, id shows the intended groups, and the directory exists. Your UID, GID, group numbers and password-status fields will differ, so check the names rather than copying these numbers.
Then test the login shell without starting a session or changing account state:
$ sudo -u ada /bin/bash -c 'printf "uid=%s home=%s shell=%s\n" "$(id -u)" "$HOME" "$SHELL"'
uid=1001 home=/home/ada shell=/bin/bash
sudo -u changes the effective user for this one command. It does not prove every interactive login path works, but it catches a misspelled shell or an unusable home directory early.
When nobody should log in, use a system account. It gets an ID from the system-user range, no home directory by default, and no password-ageing information:
$ sudo useradd --system --no-create-home --shell /usr/sbin/nologin exampled
$ getent passwd exampled
exampled:x:998:998::/nonexistent:/usr/sbin/nologin
--system, an explicitly non-interactive shell, and no home directory unless the service genuinely needs one. The exact UID, GID and home path are system-specific.--groups group1,group2 after confirming those groups exist.useradd -D on its own only displays defaults. Add options and it writes /etc/default/useradd, which is a privileged, persistent change:
$ sudo useradd -D -s /bin/bash
$ useradd -D | grep '^SHELL='
SHELL=/bin/bash
This affects later accounts, not existing ones. Record the previous output before changing a production host so you can put it back.
Recovery: To restore the value seen earlier on this machine, set it back and check it:
$ sudo useradd -D -s /bin/sh
$ useradd -D | grep '^SHELL='
SHELL=/bin/sh
Warning: Do not use -K casually to override UID ranges or password ageing for one account. Those overrides can bypass the host's identity policy, so review them like any other security-sensitive configuration.
Destructive action: Account deletion cannot be undone. Stop services that use the account, inspect its processes and find the files it owns first.
These checks do not delete anything:
$ ps -u exampled -f
$ sudo find / -xdev -user exampled -print 2>/dev/null
Move or reassign files according to your retention policy. Only then remove the account:
$ sudo userdel exampled
$ getent passwd exampled
Checkpoint: No output from the final command means the account is gone from the available databases.
Warning: For a regular account, sudo userdel -r ada also removes the home directory and mail spool where supported. That is irreversible, so back up or archive first and never use -r while you still need the user's files.
passwd, or the account is intentionally locked or non-interactive.