ZetCode

Linux useradd, usermod, and groups Commands

last modified October 23, 2026

Linux is a multi-user system. Every process runs as a user, every file is owned by a user and a group, and the permissions decide who may do what. This article shows how to create, modify, lock, and delete user accounts with useradd, usermod, and userdel, how to manage groups with groupadd and gpasswd, and how to inspect accounts with id and groups.

The examples were run in a Debian 12 container with shadow 4.13 and adduser 3.134. They are run by the user jano, who administers the system with sudo. Managing accounts requires root privileges; reading account information does not.

Account data is stored in four text files:

FileContentReadable by
/etc/passwdUsers: name, UID, primary GID, comment, home, shelleveryone
/etc/shadowPassword hashes, password aging, expiryroot
/etc/groupGroups: name, GID, member listeveryone
/etc/gshadowGroup passwords and administratorsroot

Creating a user with useradd

The useradd command creates a user account. Without options, it does less than one might expect.

sudo useradd bob
grep bob /etc/passwd
ls /home

The account exists, but its home directory /home/bob was not created, and its login shell is /bin/sh. Whether useradd creates the home directory depends on the CREATE_HOME setting in /etc/login.defs; Debian and Ubuntu leave it off, Fedora and RHEL turn it on. Do not rely on the default; pass the options explicitly.

$ sudo useradd bob
$ grep bob /etc/passwd
bob:x:1001:1001::/home/bob:/bin/sh
$ ls /home
jano

Home directory, shell, and comment

The -m option creates the home directory, -s sets the login shell, and -c the comment, usually the full name.

sudo useradd -m -s /bin/bash -c "Carol Smith" carol
getent passwd carol
ls -la /home/carol

The seven fields of the passwd entry, separated by colons, are: the user name, x (the password is in /etc/shadow), the user ID (UID), the ID of the primary group (GID), the comment, the home directory, and the shell. The new home directory contains copies of the files in /etc/skel, the skeleton directory; administrators put default configuration files there. getent reads the account databases through the system library, so it also finds users from LDAP or other sources, not only from /etc/passwd.

$ sudo useradd -m -s /bin/bash -c "Carol Smith" carol
$ getent passwd carol
carol:x:1002:1002:Carol Smith:/home/carol:/bin/bash
$ ls -la /home/carol
total 24
drwxr-xr-x 2 carol carol 4096 Oct 23 21:48 .
drwxr-xr-x 1 root  root  4096 Oct 23 21:48 ..
-rw-r--r-- 1 carol carol  220 Jun  6  2025 .bash_logout
-rw-r--r-- 1 carol carol 3526 Jun  6  2025 .bashrc
-rw-r--r-- 1 carol carol  807 Jun  6  2025 .profile

Shadow and group entries

useradd also wrote entries to /etc/shadow and /etc/group.

sudo grep carol /etc/shadow
getent group carol
id carol

The second field of the shadow entry is the password hash. A ! means there is no valid password yet, so carol cannot log in with a password. The next fields are the date of the last password change in days since January 1, 1970, and the aging values: the minimum and maximum number of days between changes and the warning period. Debian creates a private group with the same name as the user, as the USERGROUPS_ENAB yes setting in /etc/login.defs says. id shows the UID, the primary group, and all groups of the user.

$ sudo grep carol /etc/shadow
carol:!:20749:0:99999:7:::
$ getent group carol
carol:x:1002:
$ id carol
uid=1002(carol) gid=1002(carol) groups=1002(carol)

Setting a password

Root sets the password of any user with passwd, without knowing the old one.

sudo passwd carol
sudo grep carol /etc/shadow
su - carol -c 'whoami; pwd'

The password is typed twice and not echoed. The shadow entry now holds a yescrypt hash (the $y$ prefix), the default on current Debian and Ubuntu. su - starts a login shell as carol after asking for her password; -c runs a command in it. See the passwd command article for more.

$ sudo passwd carol
New password:
Retype new password:
passwd: password updated successfully
$ sudo grep carol /etc/shadow
carol:$y$j9T$AnE6QSM3vQkwlEFuerR/q0$0jr5CMtAzSsFz9g/u4S1KdxGoRLb/ZHqwUAJGABuPB/:20749:0:99999:7:::
$ su - carol -c 'whoami; pwd'
Password:
carol
/home/carol

Setting passwords non-interactively

In scripts, the chpasswd command reads user:password pairs from standard input.

echo 'bob:Maple-7-Snow' | sudo chpasswd
sudo passwd -S bob

passwd -S shows the status: P means a usable password, followed by the date of the last change and the aging values. Avoid putting real passwords on the command line, where they end up in the shell history and are visible to other users in the process list; read them from a file with restricted permissions instead.

$ echo 'bob:Maple-7-Snow' | sudo chpasswd
$ sudo passwd -S bob
bob P 2026-10-23 0 99999 7 -1

Defaults

The -D option prints the defaults that useradd applies. Further settings are in /etc/login.defs.

useradd -D
grep -E '^(UID|GID)_(MIN|MAX)' /etc/login.defs

Regular users get UIDs and GIDs from 1000 up. IDs below 1000 are reserved for system accounts. Defaults can be changed with useradd -D and an option, for example sudo useradd -D -s /bin/bash, which updates /etc/default/useradd.

$ useradd -D
GROUP=100
HOME=/home
INACTIVE=-1
EXPIRE=
SHELL=/bin/sh
SKEL=/etc/skel
CREATE_MAIL_SPOOL=no
LOG_INIT=yes
$ grep -E '^(UID|GID)_(MIN|MAX)' /etc/login.defs
UID_MIN			 1000
UID_MAX			60000
GID_MIN			 1000
GID_MAX			60000

Creating groups and adding users to them

The groupadd command creates a group. With useradd, the -G option sets the supplementary groups and -u a specific UID.

sudo groupadd developers
sudo groupadd -g 2000 ops
sudo useradd -m -u 1500 -G developers,ops dave
id dave
getent group developers ops

Each user has one primary group, which becomes the group of new files, and any number of supplementary groups. Supplementary memberships are listed in the last field of /etc/group. -g 2000 sets the GID of the group; a fixed ID is useful when the same accounts must match on several machines, for example with NFS.

$ sudo groupadd developers
$ sudo groupadd -g 2000 ops
$ sudo useradd -m -u 1500 -G developers,ops dave
$ id dave
uid=1500(dave) gid=1500(dave) groups=1500(dave),1003(developers),2000(ops)
$ getent group developers ops
developers:x:1003:dave
ops:x:2000:dave

System users

Services should run as dedicated users without a login. The -r option creates a system account.

sudo useradd -r -s /usr/sbin/nologin -d /var/lib/webapp webapp
id webapp
getent passwd webapp
sudo su - webapp
sudo -u webapp id

The UID comes from the system range, counting down from 999. A system account gets no password aging and no home directory unless -m is added; su warns that the directory does not exist. The nologin shell refuses interactive logins with a message. Commands can still be run as the user with sudo -u, which is how a service or an administrator uses the account.

$ sudo useradd -r -s /usr/sbin/nologin -d /var/lib/webapp webapp
$ id webapp
uid=999(webapp) gid=999(webapp) groups=999(webapp)
$ getent passwd webapp
webapp:x:999:999::/var/lib/webapp:/usr/sbin/nologin
$ sudo su - webapp
su: warning: cannot change directory to /var/lib/webapp: No such file or directory
This account is currently not available.
$ sudo -u webapp id
uid=999(webapp) gid=999(webapp) groups=999(webapp)

The id and groups commands

The id command shows identity information; options select single values. The groups command lists group names.

id
id -un
id -u carol
id -nG dave
groups dave
groups

Without a user name, both commands show the current process. With a name, they look the user up in the account databases. -u prints the UID, -n names instead of numbers, and -G all groups. id -u is common in scripts to check for root: [ "$(id -u)" -eq 0 ].

$ id
uid=1000(jano) gid=1000(jano) groups=1000(jano)
$ id -un
jano
$ id -u carol
1002
$ id -nG dave
dave developers ops
$ groups dave
dave : dave developers ops
$ groups
jano

Adding a user to a group with usermod

The usermod command changes an existing account. Its -G option sets the supplementary groups; together with -a, it adds to them.

sudo usermod -aG developers carol
id carol
sudo usermod -G ops carol
id carol

The first command added carol to developers. The second, without -a, replaced the whole list: carol is now in ops and no longer in developers. Forgetting the -a is a classic mistake; on a server, it can remove an administrator from the sudo group.

$ sudo usermod -aG developers carol
$ id carol
uid=1002(carol) gid=1002(carol) groups=1002(carol),1003(developers)
$ sudo usermod -G ops carol
$ id carol
uid=1002(carol) gid=1002(carol) groups=1002(carol),2000(ops)

Managing members with gpasswd

The gpasswd command adds or removes a single member without touching other memberships.

sudo gpasswd -a carol developers
sudo gpasswd -d carol ops
getent group developers ops

-a adds a user to a group and -d removes them. Removal is the case where usermod is clumsy: it would need the complete list of remaining groups.

$ sudo gpasswd -a carol developers
Adding user carol to group developers
$ sudo gpasswd -d carol ops
Removing user carol from group ops
$ getent group developers ops
developers:x:1003:dave,carol
ops:x:2000:dave

Group changes and running sessions

Group memberships are read when a user logs in. Processes that are already running keep their old groups.

id -nG
sudo usermod -aG developers jano
id -nG
id -nG jano
sg developers -c 'id -nG'

The commands were typed in an interactive shell. After usermod, id -nG still does not show developers for the current shell, while id -nG jano, which reads /etc/group, does. The user has to log out and back in. Until then, sg runs a single command with the new group, and newgrp developers starts a new shell with it.

$ id -nG
jano
$ sudo usermod -aG developers jano
$ id -nG
jano
$ id -nG jano
jano developers
$ sg developers -c 'id -nG'
developers jano

Renaming a user

The -l option of usermod changes the login name. The home directory is not renamed unless we set it with -d and move the content with -m.

sudo usermod -l david -d /home/david -m dave
getent passwd david
ls /home
id david
sudo groupmod -n david dave
id david

The UID stays the same, so all files keep their owner. The private group, however, is still called dave; groupmod -n renames it. The user should not be logged in during the rename.

$ sudo usermod -l david -d /home/david -m dave
$ getent passwd david
david:x:1500:1500::/home/david:/bin/sh
$ ls /home
carol
david
jano
$ id david
uid=1500(david) gid=1500(dave) groups=1500(dave),1003(developers),2000(ops)
$ sudo groupmod -n david dave
$ id david
uid=1500(david) gid=1500(david) groups=1500(david),1003(developers),2000(ops)

Changing the shell and comment

The -s and -c options of usermod work as with useradd.

sudo usermod -s /bin/bash -c "Bob Brown" bob
getent passwd bob

Users can change their own shell with chsh and their full name with chfn. The home directory in the entry is still /home/bob, although it was never created.

$ sudo usermod -s /bin/bash -c "Bob Brown" bob
$ getent passwd bob
bob:x:1001:1001:Bob Brown:/home/bob:/bin/bash

Locking and unlocking an account

The -L option of usermod locks the password and -U unlocks it. passwd -l and passwd -u do the same.

sudo usermod -L carol
sudo passwd -S carol
sudo grep carol /etc/shadow | cut -d: -f1-2 | cut -c1-20
su - carol -c whoami
sudo usermod -U carol
su - carol -c whoami

Locking puts a ! in front of the hash, so no password can match it; the status shows L. The correct password is rejected while the account is locked and accepted after unlocking, because the hash itself was kept. A locked password does not stop logins that do not use it, such as SSH keys; to disable an account completely, also expire it, as shown next.

$ sudo usermod -L carol
$ sudo passwd -S carol
carol L 2026-10-23 0 99999 7 -1
$ sudo grep carol /etc/shadow | cut -d: -f1-2 | cut -c1-20
carol:!$y$j9T$AnE6QS
$ su - carol -c whoami
Password:
su: Authentication failure
$ sudo usermod -U carol
$ su - carol -c whoami
Password:
carol

Account expiration

The -e option sets the date when the account expires, which is handy for temporary accounts. chage -l shows the expiration and aging settings.

sudo useradd -m -e 2026-12-31 intern
sudo chage -l intern
sudo usermod -e 2026-10-01 bob
su - bob -c whoami
sudo usermod -e '' bob

An expired account cannot log in by any method, even with the correct password or an SSH key. Setting a date in the past is a clean way to disable an account while keeping its files; an empty string removes the expiration.

$ sudo useradd -m -e 2026-12-31 intern
$ sudo chage -l intern
Last password change					: Oct 23, 2026
Password expires					: never
Password inactive					: never
Account expires						: Dec 31, 2026
Minimum number of days between password change		: 0
Maximum number of days between password change		: 99999
Number of days of warning before password expires	: 7
$ sudo usermod -e 2026-10-01 bob
$ su - bob -c whoami
Password:
Your account has expired; please contact your system administrator.
su: Authentication failure
$ sudo usermod -e '' bob

The adduser command

Debian and Ubuntu provide adduser, a friendlier front end to useradd. It asks for the password and the user information interactively.

sudo adduser eve
sudo adduser eve developers
id eve

adduser creates the home directory and sets the password in one step, using the settings from /etc/adduser.conf; this version also adds new users to the users group. With two arguments, it adds an existing user to a group. On Fedora and RHEL, adduser is just a link to useradd, so in scripts, use useradd with explicit options everywhere.

$ sudo adduser eve
Adding user `eve' ...
Adding new group `eve' (1004) ...
Adding new user `eve' (1004) with group `eve (1004)' ...
Creating home directory `/home/eve' ...
Copying files from `/etc/skel' ...
New password:
Retype new password:
passwd: password updated successfully
Changing the user information for eve
Enter the new value, or press ENTER for the default
	Full Name []: Eve Adams
	Room Number []:
	Work Phone []:
	Home Phone []:
	Other []:
Is the information correct? [Y/n] Y
Adding new user `eve' to supplemental / extra groups `users' ...
Adding user `eve' to group `users' ...
$ sudo adduser eve developers
Adding user `eve' to group `developers' ...
Done.
$ id eve
uid=1004(eve) gid=1004(eve) groups=1004(eve),100(users),1003(developers)

Deleting a user

The userdel command deletes an account; -r also removes the home directory and the mail spool.

sudo -u carol sleep 300 &
sleep 1
pgrep -u carol -a
sudo userdel carol
pgrep -u carol -a
ps -o user,pid,cmd -u 1002
sudo pkill -u 1002
ls -ld /home/carol
sudo userdel -r david
sudo userdel bob
ls /home

carol had a running process when we deleted her account. In this environment, userdel did not stop us, and the process kept running with the bare UID 1002; tools no longer accept the name carol. Stop the processes of a user first with pkill -u. Without -r, the home directory stays, owned by the numeric UID. If a new user later gets UID 1002, they become the owner of these files. Use find / -nouser to find such orphaned files. The message about the missing mail spool is harmless.

$ sudo -u carol sleep 300 &
$ sleep 1
$ pgrep -u carol -a
403 sleep 300
$ sudo userdel carol
$ pgrep -u carol -a
pgrep: invalid user name: carol
$ ps -o user,pid,cmd -u 1002
USER         PID CMD
1002         403 sleep 300
$ sudo pkill -u 1002
$ ls -ld /home/carol
drwxr-xr-x 2 1002 1002 4096 Oct 23 21:48 /home/carol
$ sudo userdel -r david
userdel: david mail spool (/var/mail/david) not found
$ sudo userdel bob
$ ls /home
carol
eve
intern
jano

Deleting groups

The groupdel command deletes a group.

sudo groupdel eve
sudo groupdel ops
getent group ops

A group that is the primary group of a user cannot be deleted. The ops group is gone; members lose it from their supplementary groups automatically.

$ sudo groupdel eve
groupdel: cannot remove the primary group of user 'eve'
$ sudo groupdel ops
$ getent group ops

Summary of commands

TaskCommand
Create a useruseradd -m -s /bin/bash -c "Name" user
Create a system useruseradd -r -s /usr/sbin/nologin user
Set a passwordpasswd user, chpasswd
Add to a groupusermod -aG group user, gpasswd -a user group
Remove from a groupgpasswd -d user group
Rename a userusermod -l new -d /home/new -m old
Lock, unlockusermod -L user, usermod -U user
Expireusermod -e YYYY-MM-DD user
Delete with homeuserdel -r user
Create, rename, delete a groupgroupadd, groupmod -n, groupdel
Show identityid, groups, getent passwd

Source

useradd(8) manual page, usermod(8) manual page

In this article, we have created regular and system users, set passwords, managed groups and memberships, renamed, locked, expired, and deleted accounts, and looked at the files that store them. See also the file permissions, chown, and sudo articles.

Author

My name is Jan Bodnar, and I am a passionate programmer with extensive programming experience. I have been writing programming articles since 2007. To date, I have authored over 1,400 articles and 8 e-books. I possess more than ten years of experience in teaching programming.

List all Linux tutorials.