Skip to content
shellhacks.dev
Linux

How to Add Create and Delete Users on Linux

Add, modify and delete users on Linux with useradd, adduser and userdel, set the home directory and shell, and know which defaults a system account needs.

6 min read
Summarize in AI
Illustration for "How to Add Create and Delete Users on Linux": a terminal session, file permission bits, a magnifier over matching lines.

User accounts live in /etc/passwd, /etc/shadow and /etc/group, and a handful of commands edit them safely. The two creation commands behave differently, which catches people moving between Debian and Red Hat families. The examples use shadow-utils 4.14 and Debian's adduser 3.137, with root or sudo.

Create a user the portable way

Shell
sudo useradd -m -s /bin/bash -c "Alice Example" alice
sudo passwd alice
id alice
Text
uid=1001(alice) gid=1001(alice) groups=1001(alice)

-m creates the home directory from /etc/skel, -s sets the login shell and -c the comment field. Without -m, some distributions create no home directory. Without -s, the default shell may be /bin/sh. A new account has a locked password until passwd sets one; see setting passwords and expiry.

Debian and Ubuntu: adduser

Shell
sudo adduser alice
sudo adduser --disabled-password --gecos "" ci-runner

adduser is a Perl script that calls useradd, creates the home, copies skeleton files and prompts for a password and details. --disabled-password creates a key-only account. It does not exist on Red Hat family systems, where adduser is just a link to useradd, so scripts meant to be portable should call useradd directly.

Add to groups at creation

Shell
sudo useradd -m -G sudo,docker -s /bin/bash bob

-G sets supplementary groups, and the list must be comma-separated without spaces. Granting sudo or docker is equal to granting root-level control, so do it deliberately; see giving a user sudo access. Changing groups of an existing user is covered in managing groups with usermod, and the missing -a flag there is a classic mistake.

Service accounts

Shell
sudo useradd --system --no-create-home --shell /usr/sbin/nologin appsvc
getent passwd appsvc

--system picks a UID from the system range defined in /etc/login.defs, nologin blocks interactive login, and no home is created unless the service needs one. Prefer a systemd unit with DynamicUser=yes for many services, which creates the account only while the service runs.

Lock and delete

Shell
sudo usermod -L alice          # lock the password
sudo userdel -r alice          # remove user, home and mail spool
sudo find / -xdev -nouser 2>/dev/null | head

Locking is reversible and keeps files. userdel -r deletes the home directory, and it refuses if the user is logged in unless -f is given. Files elsewhere keep the old numeric ID, which the final find lists; a later account that reuses the UID would silently own them. See disabling a user account for the safer option when data must be kept.

What the account fields mean

A line in /etc/passwd has seven fields: login name, a password placeholder, user id, primary group id, the comment (often the full name), the home directory and the login shell. The placeholder is an x on systems that keep hashes in /etc/shadow. The user id is the number that file ownership refers to, and ordinary accounts start at 1000 on Debian and Ubuntu, and at 1000 on current Red Hat releases (older ones used 500). The values come from UID_MIN and related lines in /etc/login.defs, and system accounts use the range below it.

The shell field has a second use. A login shell must be listed in /etc/shells for tools such as FTP daemons to accept the account, and setting it to /usr/sbin/nologin or /bin/false prevents interactive logins while leaving the account usable by services. Those two differ in message: nologin prints a polite refusal, which can be customised in /etc/nologin.txt, and false exits silently.

The home directory and skeleton

With -m, useradd copies the contents of /etc/skel into the new home. That directory is the place to put defaults for every future user: a .bashrc, a .profile, an editor configuration. Changing it affects only accounts created afterwards. The mode of the new home is set by HOME_MODE in login.defs, and recent releases default to 700, while older systems used 755, so an account created years ago may be readable by others. Check with ls -ld /home/* and tighten with chmod 750 or 700 where it matters.

If the home lives on a separate volume or a network share, create the account without -m and prepare the directory yourself, with the right owner set by chown alice:alice. Creating a home on a mount that is not present writes the files into the mount point on the root disk, where they are hidden when the share is attached later.

Keys instead of passwords

For servers, the usual practice is to create the account and install a public key and leave the password locked. The key goes in ~/.ssh/authorized_keys with directory mode 700 and file mode 600 and the correct owner, because the SSH daemon refuses keys in files that other users can write. A short sequence does it: install -d -m 700 -o alice -g alice /home/alice/.ssh, then write the key with the same owner and mode 600. ssh-copy-id automates the steps from a machine that already has access. Disabling password logins in sshd_config once keys work closes the most common brute-force path.

Naming, ids and removal

Pick a naming convention and keep it. A short lowercase name made from the person's real name or company login avoids clashes with system names, and avoids characters such as dots and capital letters that some tools handle badly. Keep ids consistent across machines that share storage, either by creating users in the same order, by passing -u explicitly, or by using a directory service. When a person leaves, lock the account first, review what they own with find / -xdev -user alice, move the data that matters and then delete. Deleting immediately leaves cron jobs, services and files with an owner that no longer resolves, and reusing the id for a new person gives them the old person's files.

Auditing what a new account can do

After creating an account, check it the way an attacker would. Run sudo -l -U alice to list what sudo allows, id alice for the groups, and sudo -u alice -i to look at the environment it gets. Confirm that the home directory has the intended mode and that no world-writable files sit inside it. For a service account, confirm that it cannot log in with su - appsvc and that its files are owned by it and not root, so a compromise of the service stays within its own data.

Record each creation in the place the team keeps change history, with the reason and the person who approved it. Accounts without an owner are the ones that stay around for years. A script that creates users from a list in a repository, run through a review, gives that record for free and makes the next account identical to the last.

Where this does not apply

On machines that use LDAP, SSSD, FreeIPA or Active Directory, local commands create local users only, and central accounts are managed in the directory. Container images usually need a fixed UID chosen to match host volumes, passed with -u. The options are documented in useradd(8), and the Debian Reference shows the adduser workflow.

Share

Keep reading

Get new posts by email

One email when a new post is published. No spam.

Unsubscribe in one click. No spam, ever.