On this page

Every Linux system has at least two accounts: root and whoever set the machine up. Between those two extremes, real systems accumulate service accounts, shared project accounts, and the occasional test user that nobody remembers creating. This guide covers the commands that create, modify, and remove those accounts – and the four plain-text files that store them.

If you have never changed a user’s shell or added someone to a group, start here. The commands are short; the consequences are permanent.

Prerequisites

You need root access. Every command in this guide either writes to /etc/passwd or manipulates account databases that only root can touch. On Ubuntu/Debian, prefix commands with sudo. On Fedora, either log in as root or use sudo. On Arch, same deal.

If the language of permissions and ownership feels unfamiliar, read Permissions & Ownership first. That chapter covers chmod and chown; this guide covers the accounts those permissions are assigned to.

useradd – create a user

The basic form is simple:

$ sudo useradd alice

On Ubuntu and Arch, this creates the user but does not create a home directory. On Fedora, CREATE_HOME=yes is set in /etc/login.defs, so a home directory at /home/alice is created automatically. This is a real difference between distros, not a misconfiguration.

To create a home directory on any distro, pass -m:

$ sudo useradd -m alice

This creates /home/alice and copies the skeleton files from /etc/skel into it. The skeleton directory contains default dotfiles: .profile on Ubuntu, .bash_profile on Fedora and Arch. These are templates. They do not affect login behavior until you edit them.

A few flags come up often:

$ sudo useradd -m -s /bin/bash -G sudo,docker -c "Alice Example" alice
  • -s /bin/bash sets the login shell. Without it, useradd reads the fallback from /etc/default/useradd (the SHELL= line), never from /etc/login.defs. That fallback is /bin/sh on Ubuntu and bash on Fedora and Arch, but it differs, so always pass -s to be explicit.
  • -G sudo,docker adds supplementary groups (the -aG flag on usermod does the same for existing users, see below). Know your distro’s admin group: the sudo group exists on Ubuntu. Fedora and Arch call it wheel instead (there, useradd -G sudo fails with group 'sudo' does not exist). And the docker group only exists after Docker is actually installed. Until then, that flag is an error too.
  • -c "Alice Example" sets the GECOS comment field, a free-text string that shows up in grep alice /etc/passwd.

You can also set a custom primary group or UID:

$ sudo useradd -m -g developers -u 2000 carol
  • -g developers sets the primary group (field 4 in /etc/passwd). Without it, useradd creates a new group named after the user.
  • -u 2000 assigns a specific UID instead of picking the next available one. Useful when UIDs must match across multiple machines.

A custom home directory path works too:

$ sudo useradd -m -d /opt/alice alice

Without -m, the -d flag sets the path in /etc/passwd but does not create the directory. The user would log in to a missing home and get errors.

One more thing: useradd does not set a password. The account exists but is locked until you run passwd (covered later in this guide).

adduser vs useradd – the Debian wrapper

On Ubuntu and Debian, adduser is a higher-level interactive wrapper written in Perl. It creates the home directory, sets the shell, asks for a password, then prompts you for the full name – all in one conversation:

$ sudo adduser alice

On Fedora, adduser is a symlink to useradd. There is no interactive wrapper; adduser alice behaves identically to useradd alice. On Arch, adduser does not exist.

If you are writing scripts, always use useradd – it works the same everywhere. If you are setting up a user by hand on Ubuntu and prefer the guided experience, adduser is the more pleasant option.

groupadd – create a group

Groups let you grant permissions to multiple users at once. Every user has one primary group (field 4 in /etc/passwd, the group a new file is owned by) and zero or more supplementary groups (field 5 in /etc/group, the extra memberships). The -G flag and usermod -aG both deal with supplementary groups. -g sets the primary group.

The command to create a group is straightforward:

$ sudo groupadd developers

That creates a new group in /etc/group with the next available GID. You can add users to it immediately:

$ sudo usermod -aG developers alice

Or create the user with the group already assigned:

$ sudo useradd -m -G developers bob

The difference between -G in useradd and -aG in usermod matters. In useradd, -G sets the initial supplementary groups. In usermod, -aG appends to the existing list. Without -a, usermod -G replaces the entire supplementary group list. Forgetting -a is one of the more common mistakes in user management – and it is silent. The command does not warn you that it just removed the user from every other group.

usermod – change an account

usermod edits an existing account. The most common uses:

Change the login shell:

$ sudo usermod -s /bin/zsh alice

(usermod warns that the shell is missing or non-executable, but records it anyway.)

Move a home directory:

$ sudo usermod -d /home/alice-new -m alice

The -m flag moves the existing home contents to the new path. If the target directory already exists, usermod warns (usermod: directory /home/X exists, exit code 12) and moves nothing. But it still repoints the home field in /etc/passwd, silently leaving the user’s files behind. Check before you run it.

Lock and unlock an account:

$ sudo usermod -L alice   # lock
$ sudo usermod -U alice   # unlock

Locking prepends a ! to the encrypted password in /etc/shadow. The account still exists, but no password will authenticate it. SSH key authentication is not affected by account locking. Only password-based logins are blocked.

Add to a group (without removing others):

$ sudo usermod -aG developers alice

Again: -aG appends. -G alone replaces.

userdel – remove an account

$ sudo userdel alice

This removes the user entry from /etc/passwd and /etc/group but leaves the home directory intact. Files owned by the deleted user become orphaned: they still exist, but their ownership shows a numeric UID instead of a username.

To remove the user and their home directory:

$ sudo userdel -r alice

The -r flag deletes /home/alice along with the user entry. There is no undo. If you want to keep the files but reassign ownership, remove the user first, then chown the files to a different account.

A practical note: never delete a user while they are logged in. The who command shows who is currently logged in; id <user> shows membership and UID/GID details. Use either before removing accounts.

The four account files

Linux stores user and group information in four plain-text files in /etc. Understanding them helps when commands behave unexpectedly.

/etc/passwd – one line per user, seven colon-separated fields:

alice:x:1001:1001:Alice Example:/home/alice:/bin/bash

The fields are: username, password placeholder (x means the real hash lives in shadow), UID, GID, GECOS comment, home directory, login shell.

/etc/shadow – password hashes and aging data, readable only by root:

On Ubuntu, the permissions are 640. On Fedora, SELinux controls access (the raw permissions show 000). On Arch, the file is 600. The details differ, but the rule is the same: regular users cannot read it.

/etc/group – one line per group:

developers:x:1002:alice,bob

Fields: group name, password placeholder (rarely used), GID, comma-separated member list.

/etc/gshadow – group password and administrative data, root-readable only. The file is not empty: every group gets a line, and the password field is usually unused (* or !). Group passwords are a relic. Modern setups use supplementary groups instead.

id and getent – look up accounts

The id command shows who you are:

$ id
uid=1000(alice) gid=1000(alice) groups=1000(alice),27(sudo),1002(developers)

Or ask about another user:

$ id bob
uid=1001(bob) gid=1001(bob) groups=1001(bob),1002(developers)

Useful flags:

$ id -u          # numeric UID only: 1000
$ id -g          # numeric GID only: 1000
$ id -n -u       # username only: alice
$ id -n -g       # group name only: alice

These flags are handy in scripts where you need a number, not a display string.

getent queries the system databases directly. It reads the same files id does, but can target a specific database:

$ getent passwd alice
alice:x:1001:1001:Alice Example:/home/alice:/bin/bash

$ getent group developers
developers:x:1002:alice,bob

The difference from reading /etc/passwd with cat is that getent respects NSS. If your system uses LDAP, SSSD, or another directory service, getent returns entries from those sources too. Plain cat would only show the local files.

passwd and chage – passwords and expiry

A user without a password cannot log in via password authentication. As root, set one:

$ sudo passwd alice

The system prompts for a new password twice. How chatty the strength check is depends on the distro: Fedora warns on weak passwords out of the box (BAD PASSWORD: The password is shorter than 8 characters), while root on Ubuntu and Arch sets weak passwords silently unless the PAM quality module is installed. They still enforce PAM rules if configured.

Password aging controls how long a password remains valid. The chage command manages this:

$ sudo chage -l alice       # list current settings
$ sudo chage -M 90 alice    # expire password after 90 days

The -l flag displays the current password aging info: last change date, minimum and maximum age, warning period, and account expiry. The -M 90 flag sets the maximum number of days a password can be used before the system forces a change.

These settings apply to password-based logins. If you use SSH key authentication exclusively, password expiry policies do not affect your access – but they still matter if someone can fall back to a password.

UID and GID numbers – the numbering scheme

Every user has a numeric UID. Every group has a numeric GID. The convention across major distros:

UID 0 is always root. UIDs 1 through 999 are system accounts: services like www-data and systemd-resolve that run daemons, not interactive shells. Regular accounts start at UID 1000.

The first user created on a fresh Ubuntu install gets UID 1000. Fedora and Arch follow the same pattern. When you create users with useradd, the system picks the next available UID starting at 1000.

Groups follow an identical scheme: GID 0 is root, 1–999 are system groups, 1000+ are user groups. The users group exists on most systems as a fallback (GID 100 on Ubuntu and Fedora, 982 on Arch).

You can check a specific UID:

$ id -u alice
1000

Or see which UID a system account runs as:

$ id -u nobody
65534

UID 65534 (nobody) is the conventional unprivileged account, and the name matches on all three distros. What drifts is the cosmetic stuff: Ubuntu’s GECOS string reads nobody, Fedora’s and Arch’s read Kernel Overflow User, and the nologin path differs (/usr/sbin/nologin on Ubuntu and Fedora, /usr/bin/nologin on Arch).

Capstone: setting up a shared project account

Suppose a small team needs a shared account for running a deployment script. The account should have a home directory, a bash shell, and access to a deploy group that owns the deployment directory.

$ sudo groupadd deploy
$ sudo useradd -m -s /bin/bash -G deploy -c "Deploy Account" deployer
$ sudo passwd deployer

At this point, deployer can log in and has a home directory. The deployment directory needs to belong to the deploy group:

$ sudo chown root:deploy /opt/deployments
$ sudo chmod 2775 /opt/deployments

The 2775 permission set means the directory is group-writable, and new files inherit the group. The leading 2 sets the setgid bit: new files created inside this directory automatically inherit the directory’s group (deploy here) instead of the creator’s primary group. Any user in the deploy group, including deployer, can create and modify files there. One warning: setgid alone does not stop group members from deleting or renaming each other’s files. That happens on all three distros. To get both at once (group inheritance and deletion protection), combine the bits: chmod 3775. New files still inherit the group, and a non-owner member’s rm now fails with Operation not permitted.

To add more team members to the group:

$ sudo usermod -aG deploy alice
$ sudo usermod -aG deploy bob

To verify:

$ id deployer
uid=1002(deployer) gid=1002(deployer) groups=1002(deployer),1003(deploy)
$ getent group deploy
deploy:x:1003:deployer,alice,bob

If the team changes and you need to remove someone:

$ sudo userdel -r olduser

Or just remove their group membership without deleting the account. The gpasswd command manages group membership directly, and -d removes a user from a group:

$ sudo gpasswd -d olduser deploy

Where you are now

You have the full lifecycle of Linux accounts: creating users with useradd, groups with groupadd, modifying accounts with usermod, removing them with userdel, and reading the four files that hold it all. The commands are short; the work is knowing which flag means what and which distro does it differently.

For the permissions those accounts inherit, see Permissions & Ownership. For the services accounts run and the logs they produce, see Services & Logs. If something goes wrong (a locked account, a missing home, a group that does not seem to stick), Troubleshooting covers the common failure patterns.

External references: