Create a new user account The low-level tool for adding users to a Linux system. Touches five files, creates a home directory, and sets up the entire authentication infrastructure for a new account β in one command.
- What is useradd?
- Where does useradd live?
- How useradd works internally
- Syntax
- All Options
- Files Modified by useradd
- Default Values: /etc/default/useradd
- /etc/login.defs β System-wide Policy
- Skeleton Directory: /etc/skel
- UID & GID Ranges
- useradd vs adduser vs usermod vs userdel
- Related Commands
useradd is the low-level command for creating new user accounts on Linux. It:
- Adds an entry to
/etc/passwd(user database) - Adds an entry to
/etc/shadow(password database) - Adds an entry to
/etc/group(primary group) - Optionally adds to
/etc/gshadow(group password database) - Creates the home directory (with
-m) - Copies skeleton files from
/etc/skelinto the home directory - Sets up initial password aging in
/etc/shadow
useradd is the plumbing β it does exactly what you tell it, no more. On Debian/Ubuntu, adduser is a friendlier wrapper around useradd that prompts interactively.
/usr/sbin/useradd β most Linux systems
/sbin/useradd β older distros (symlink)
which useradd
useradd --version
# useradd 4.13 (shadow-utils)useradd is part of shadow-utils β the same package that provides passwd, groupadd, userdel, usermod, chage, and su.
# Debian/Ubuntu:
dpkg -S $(which useradd) # passwd: /usr/sbin/useradd
# RHEL/Fedora:
rpm -qf $(which useradd) # shadow-utils-...Requires root or CAP_CHOWN, CAP_SETUID capabilities.
parse args β validate β find next UID β lock files β update databases
β create home β copy skel β set password aging β unlock files β log
Step by step:
- Parse and validate arguments β check username format (no spaces, valid chars), no duplicate username/UID
- Find next UID β scan
/etc/passwdfor highest UID, increment (or use-uvalue) - Lock files β acquire exclusive lock on
/etc/passwd.lockand/etc/shadow.lockto prevent concurrent modifications - Update
/etc/passwdβ append new line:username:x:UID:GID:GECOS:home:shell - Update
/etc/shadowβ append new line with!!(locked, no password yet) - Update
/etc/groupβ create primary group or add to existing - Update
/etc/gshadowβ group shadow entry - Create home directory β
mkdir,chown,chmodper-dand-mflags - Copy skeleton β recursive copy of
/etc/skelcontents to home - Set ownership β
chown -R uid:gid homedir - Apply password aging from
/etc/login.defs - Unlock files β release locks
- Log to syslog β records account creation
File locking mechanism:
useradd uses lckpwdf() which creates /etc/passwd.lock. If the lock can't be acquired (another useradd/usermod running), it fails rather than corrupting the files.
Exit codes:
| Code | Meaning |
|---|---|
0 |
Success |
1 |
Can't update password file |
2 |
Invalid command syntax |
3 |
Invalid argument to option |
4 |
UID already in use (with -u, without -o) |
6 |
Specified group doesn't exist |
9 |
Username already in use |
10 |
Can't update group file |
12 |
Can't create home directory |
14 |
Can't update SELinux user mapping |
useradd [OPTIONS] LOGIN
useradd -D [OPTIONS] # view/modify defaults
LOGINβ the username to create (required)-Dβ display or modify default values (stored in/etc/default/useradd)
| Option | Long | Description |
|---|---|---|
-u UID |
--uid |
Set specific UID (must be unique unless -o) |
-o |
--non-unique |
Allow non-unique UID (use with -u) |
-g GID |
--gid |
Primary group (name or GID) |
-G groups |
--groups |
Supplementary groups (comma-separated) |
-c comment |
--comment |
GECOS field (full name, phone, etc.) |
-l |
--no-log-init |
Don't add user to lastlog/faillog databases |
| Option | Long | Description |
|---|---|---|
-m |
--create-home |
Create home directory (copies /etc/skel) |
-M |
--no-create-home |
Do NOT create home directory |
-d dir |
--home-dir |
Set home directory path (default: /home/LOGIN) |
-k skeldir |
--skel |
Use alternative skeleton directory |
-K KEY=VAL |
--key |
Override /etc/login.defs values |
| Option | Long | Description |
|---|---|---|
-s shell |
--shell |
Login shell (default: from /etc/default/useradd) |
-p hash |
--password |
Set encrypted password (use passwd instead!) |
-L |
(via passwd) | Lock account after creation |
| Option | Long | Description |
|---|---|---|
-e date |
--expiredate |
Account expiry date (YYYY-MM-DD) |
-f days |
--inactive |
Days after password expiry before disabling |
| Option | Long | Description |
|---|---|---|
-r |
--system |
Create system account (low UID, no home by default) |
-N |
--no-user-group |
Don't create private group for user |
-U |
--user-group |
Create private group (default behavior) |
| Option | Long | Description |
|---|---|---|
-Z context |
--selinux-user |
SELinux user mapping |
-b basedir |
--base-dir |
Base directory for home (default: /home) |
alice:x:1001:1001:Alice Smith,,,:/home/alice:/bin/bash
β β β β β β β
β β β β β β ββ login shell
β β β β β ββ home directory
β β β β ββ GECOS: full name, room, work phone, home phone, other
β β β ββ primary GID
β β ββ UID
β ββ password: 'x' = look in /etc/shadow
ββ username (LOGIN)
# View the entry created by useradd:
grep "^alice:" /etc/passwd
# Permissions: world-readable (programs need UID/name lookup)
ls -l /etc/passwd
# -rw-r--r-- 1 root root 2847 /etc/passwdalice:!!:19523:0:99999:7:::
β β β β β β
β β β β β ββ warn days before expiry
β β β β ββ max days between changes (99999 = never)
β β β ββ min days between changes
β β ββ last change (days since epoch Jan 1 1970)
β ββ !! = locked, no password set yet
ββ username
# View (root only):
sudo grep "^alice:" /etc/shadow
# Permissions: root read only
ls -l /etc/shadow
# -rw-r----- 1 root shadow 1456 /etc/shadowalice:x:1001:
β β β ββ list of supplementary members (empty = no extras)
β β ββ GID
β ββ group password ('x' = in /etc/gshadow)
ββ group name
alice:!::
β β ββ members
β ββ ! = no group password
ββ group name
cat /etc/default/useradd# Default values used when no flags are specified:
GROUP=100 # default primary GID (if -N: use this group)
HOME=/home # base directory for home dirs
INACTIVE=-1 # days after expiry before disabling (-1 = never)
EXPIRE= # account expiry date (empty = never)
SHELL=/bin/sh # default shell (often /bin/bash on distros)
SKEL=/etc/skel # skeleton directory
CREATE_MAIL_SPOOL=no # create /var/mail/username# View current defaults:
useradd -D
# Modify a default:
useradd -D -s /bin/bash # change default shell
useradd -D -b /home # change base directory
useradd -D -e 2024-12-31 # set default expiry
# These changes are written to /etc/default/useradd/etc/login.defs controls UID/GID ranges, password aging defaults, and other system-wide security policy applied to all new accounts.
cat /etc/login.defs | grep -v "^#\|^$"Key settings:
# UID/GID ranges
UID_MIN 1000 # minimum UID for regular users
UID_MAX 60000 # maximum UID for regular users
SYS_UID_MIN 201 # minimum UID for system accounts (-r)
SYS_UID_MAX 999 # maximum UID for system accounts
GID_MIN 1000 # minimum GID for regular groups
GID_MAX 60000 # maximum GID
SYS_GID_MIN 201
SYS_GID_MAX 999
# Password aging defaults (applied to new accounts)
PASS_MAX_DAYS 99999 # max days a password is valid
PASS_MIN_DAYS 0 # min days between password changes
PASS_WARN_AGE 7 # days to warn before expiry
PASS_MIN_LEN 8 # minimum password length
# Home directory
CREATE_HOME yes # create home dir by default (Debian-style)
# Hashing algorithm
ENCRYPT_METHOD SHA512 # or YESCRYPT on modern systems
# umask for home directories
UMASK 022
# Login tracking
LASTLOG_ENAB yes # log last login time
FAILLOG_ENAB yes # track failed login attempts
LOG_UNKFAIL_ENAB no # log unknown usernames in failed logins
# Mail
MAIL_DIR /var/mail # or /var/spool/mailWhen useradd -m creates a home directory, it copies all files from /etc/skel into it.
ls -la /etc/skel/
# .bash_logout
# .bashrc
# .profile
# (possibly: .bash_profile, .vimrc, etc.)# Customize skeleton for all new users:
echo "alias ll='ls -la'" >> /etc/skel/.bashrc
cp company_motd.txt /etc/skel/.motd
mkdir /etc/skel/bin # every new user gets a ~/bin directory
# Use alternative skeleton:
useradd -m -k /etc/skel.developer alice
useradd -m -k /dev/null alice # empty home (no skeleton files)0 root (superuser)
1-99 statically allocated system accounts (distro-managed)
100-999 dynamically allocated system accounts (useradd -r)
1000-65533 regular user accounts (useradd without -r)
65534 nobody (nfsnobody β unmapped UIDs)
65535 (historical limit β often avoided)
# These ranges are configurable in /etc/login.defs:
grep "^UID_MIN\|^UID_MAX\|^SYS_UID" /etc/login.defs
# Find next available UID:
awk -F: '$3 >= 1000 && $3 < 65534 {print $3}' /etc/passwd | sort -n | tail -1
# List all users and UIDs:
awk -F: '{printf "%-20s %s\n", $1, $3}' /etc/passwd | sort -t' ' -k2 -n| Command | Purpose | Interactive? | Distro |
|---|---|---|---|
useradd |
Create user (low-level) | No | All Linux |
adduser |
Create user (high-level, friendly) | Yes (Perl script) | Debian/Ubuntu |
usermod |
Modify existing user | No | All Linux |
userdel |
Delete user | No | All Linux |
deluser |
Delete user (high-level) | Optional | Debian/Ubuntu |
# useradd: manual, precise, scriptable
useradd -m -s /bin/bash -c "Alice Smith" alice
# adduser: interactive, creates home, sets password, prompts for info
adduser alice
# Asks: password, full name, room, phone, etc.
# usermod: modify after creation
usermod -aG sudo alice # add to sudo group
usermod -s /bin/zsh alice # change shell
usermod -l newname oldname # rename user
# userdel: remove user
userdel alice # remove account (keep home)
userdel -r alice # remove account + home + mail spool| Command | Relation |
|---|---|
adduser |
Friendly wrapper around useradd (Debian/Ubuntu) |
usermod |
Modify existing user account |
userdel |
Delete user account |
passwd |
Set/change user password |
chage |
Manage password aging policy |
groupadd |
Create new group |
groupmod |
Modify existing group |
groupdel |
Delete group |
groups |
Show groups a user belongs to |
id |
Show UID, GID, and group memberships |
finger |
Display user information (GECOS) |
chfn |
Change GECOS (finger) information |
chsh |
Change login shell |
newusers |
Bulk create users from file |
pwck |
Verify password file integrity |
grpck |
Verify group file integrity |
vipw |
Safely edit /etc/passwd (with locking) |
See also:
examples.mdΒ·edge-cases.mdΒ·interview-questions.md