Create a Linux User Safely with useradd
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.
The route
Jump straight to the step you need, or tick off Done means at the end.
- You need a shell, an account allowed to use
sudo, and thepasswdpackage. - Version. Debian's
useraddfrom shadow-utils 4.13, installed here as package version1: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.
1. Inspect the defaults
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
- Same-named group by default. On this machine,
USERGROUPS_ENAB yesin/etc/login.defsgives a new account a same-named primary group unless you specify-g,-Nor-U. - No home unless you ask. The local
login.defsdoes not enableCREATE_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.
2. Choose a valid, unused login name
Use a short name such as ada, not a display name or an email address. This implementation rejects:
- Bad first characters: names beginning with a dash, plus or tilde.
- Bad characters anywhere: whitespace, a colon or a comma.
- Fully numeric names (on Ubuntu).
- Anything over 32 characters.
$ 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.
3. Create a regular account with a home
Pick the shell and groups deliberately:
$ sudo useradd -m -s /bin/bash -G audio,video ada
-mcreates/home/adaand copies in the contents of/etc/skel.-ssets the login shell.-Gadds 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.
4. Verify the account before handing it over
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.
5. Create a service account for daemons
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
- The choices that matter:
--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. - Need groups? Add them with
--groups group1,group2after confirming those groups exist. - Keep access narrow. Do not add a service to broad groups just to make an error disappear. Grant only the filesystem, device or socket access it requires, and check the service's installation documentation if it expects a dedicated directory.
6. Change defaults only on purpose
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.
7. Remove an account only after checking ownership
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.
Done means
- Valid, new name. The login name is valid and was not already present.
- Right groups. The account has the intended primary and supplementary groups.
- Home and shell checked. The home directory choice and login shell were verified.
- Password handled. A password was set through
passwd, or the account is intentionally locked or non-interactive. - Defaults recorded. Any default change was written down and can be restored.
- Ownership checked. Before any deletion, processes and owned files were checked.