Vucense

Linux Users & Groups: Complete Management Guide for Ubuntu 24.04 2026

🟢Beginner

Master Linux user and group management on Ubuntu 24.04. adduser, usermod, groupadd, su, sudo, /etc/passwd, /etc/shadow, SSH key provisioning, and service accounts. Fully tested.

Noah Choi

Author

Noah Choi

Linux & Cloud Native Infrastructure Engineer

Published

Duration

Reading

15 min

Build

20 min

Linux Users & Groups: Complete Management Guide for Ubuntu 24.04 2026
Article Roadmap

Key Takeaways

  • The identity model: Every user has a UID (number), a username (text label), a primary group, and zero or more supplementary groups. Every process runs as a UID. Every file is owned by a UID and GID. Permissions are checked against those numbers — not the names.
  • adduser vs useradd: On Ubuntu, use adduser username — it handles home directory creation, skeleton files, and prompts. useradd is the raw POSIX command requiring -m -s -d flags for basic setup.
  • Groups are sets: usermod -aG groupname username adds a user to a supplementary group. The -a flag is critical — without it, the command replaces all existing groups with the new one.
  • Sovereign identity: All user management happens locally in /etc/passwd, /etc/shadow, and /etc/group — no LDAP, no cloud IAM, no external identity provider required. Every command on this page works air-gapped.

Introduction: How Linux Identity Works

Direct Answer: How do I create and manage users and groups on Ubuntu 24.04 LTS in 2026?

To create a user on Ubuntu 24.04, run sudo adduser username — it prompts for a password and optional info, creates /home/username, and sets /bin/bash as the shell. To add the user to sudo, run sudo usermod -aG sudo username. To create a group, run sudo groupadd groupname. To add a user to a group, run sudo usermod -aG groupname username (the -a flag is mandatory — it appends to groups rather than replacing them). Verify with id username — this shows the UID, primary GID, and all supplementary groups. To delete a user and their home directory, run sudo deluser --remove-home username. To lock an account without deleting it, run sudo usermod -L username. All user data lives in four files: /etc/passwd (usernames and UIDs), /etc/shadow (hashed passwords), /etc/group (group memberships), and /etc/gshadow (group passwords).

“Root is not a user you log in as — it’s an emergency access level. Your day-to-day account with sudo privileges gives you the same power on demand, with a full audit trail. Root has no trail.”


Part 1: Reading the User Database

Before creating users, understand what already exists.

# View your own identity
id

Expected output:

uid=1001(youruser) gid=1001(youruser) groups=1001(youruser),4(adm),24(cdrom),27(sudo),30(dip),46(plugdev),110(lxd)

Reading this: UID 1001, primary group 1001 (youruser), member of 7 supplementary groups including sudo (group 27).

# View all human (login) users — UIDs 1000+
awk -F: '$3 >= 1000 && $1 != "nobody" {print $1, $3, $6, $7}' /etc/passwd

Expected output:

youruser 1001 /home/youruser /bin/bash
# View all system service accounts — UIDs < 1000
awk -F: '$3 < 1000 {printf "%-20s UID:%-6s Shell:%-25s\n", $1, $3, $7}' /etc/passwd | head -15

Expected output:

root                 UID:0      Shell:/bin/bash
daemon               UID:1      Shell:/usr/sbin/nologin
bin                  UID:2      Shell:/usr/sbin/nologin
sys                  UID:3      Shell:/usr/sbin/nologin
www-data             UID:33     Shell:/usr/sbin/nologin
mysql                UID:120    Shell:/usr/sbin/nologin
postgres             UID:121    Shell:/usr/sbin/nologin

Service accounts have /usr/sbin/nologin as their shell — they cannot be interactively logged into.

# View all groups
cat /etc/group | grep -v "^#" | sort | head -20

Expected output:

adm:x:4:syslog,youruser
audio:x:29:
cdrom:x:24:youruser
docker:x:999:youruser
plugdev:x:46:youruser
sudo:x:27:youruser
www-data:x:33:

The /etc/passwd file format:

username:password:UID:GID:comment:home:shell
youruser :x      :1001:1001:Your Name:/home/youruser:/bin/bash

# 'x' in password field means password is in /etc/shadow (never in /etc/passwd)

Part 2: Creating Users

adduser — the right way on Ubuntu

# Create a new user interactively
sudo adduser alice

Expected output:

Adding user `alice' ...
Adding new group `alice' (1002) ...
Adding new user `alice' (1002) with group `alice' ...
Creating home directory `/home/alice' ...
Copying files from `/etc/skel' ...
New password: [enter password]
Retype new password: [repeat]
passwd: password updated successfully
Changing the user information for alice
Enter the new value, or press ENTER for the default
	Full Name []: Alice Smith
	Room Number []:
	Work Phone []:
	Home Phone []:
	Other []:
Is the information correct? [Y/n] Y
Adding new user `alice' to supplemental / extra groups `users' ...
Adding user `alice' to group `users' ...

Verify the user was created:

id alice

Expected output:

uid=1002(alice) gid=1002(alice) groups=1002(alice),100(users)
# Verify home directory was created with correct contents
ls -la /home/alice/

Expected output:

total 28
drwxr-x--- 3 alice alice 4096 Apr 17 12:05 .
drwxr-xr-x 4 root  root  4096 Apr 17 12:05 ..
-rw-r--r-- 1 alice alice  220 Apr 17 12:05 .bash_logout
-rw-r--r-- 1 alice alice 3526 Apr 17 12:05 .bashrc
-rw-r--r-- 1 alice alice  807 Apr 17 12:05 .profile
drwx------ 2 alice alice 4096 Apr 17 12:05 .ssh

The files came from /etc/skel — the skeleton directory copied to every new home.

adduser with flags (non-interactive)

# Create a user non-interactively (useful in scripts)
sudo adduser \
  --disabled-password \
  --gecos "Deploy Bot,,," \
  --shell /bin/bash \
  deploybot

# Set the password separately
echo "deploybot:$(openssl rand -base64 24)" | sudo chpasswd

Expected output:

Adding user `deploybot' ...
Adding new group `deploybot' (1003) ...
Adding new user `deploybot' (1003) with group `deploybot' ...
Creating home directory `/home/deploybot' ...
Copying files from `/etc/skel' ...

useradd — when you need exact control

# Create a service account with no login shell and no home directory
sudo useradd \
  --system \
  --no-create-home \
  --shell /usr/sbin/nologin \
  --comment "My App Service Account" \
  myapp-svc

# Verify
id myapp-svc
getent passwd myapp-svc

Expected output:

uid=998(myapp-svc) gid=998(myapp-svc) groups=998(myapp-svc)
myapp-svc:x:998:998:My App Service Account:/home/myapp-svc:/usr/sbin/nologin

--system assigns a UID below 1000, marking it as a service account. --no-create-home skips home directory creation.


Part 3: Managing Passwords and Account State

# Change your own password
passwd

# Change another user's password (requires sudo)
sudo passwd alice

# Force a user to change password on next login
sudo passwd --expire alice

# Lock an account (prepends ! to password hash — login impossible)
sudo usermod -L alice

# Verify lock status (locked accounts show ! in shadow)
sudo passwd -S alice

Expected output of passwd -S:

alice L 04/17/2026 0 99999 7 -1
# L = Locked | P = Password set | NP = No password
# Unlock an account
sudo usermod -U alice

# Set account expiry date (useful for contractors/temporary access)
sudo usermod --expiredate 2026-06-30 alice

# Disable an account entirely by setting shell to nologin
sudo usermod --shell /usr/sbin/nologin alice

# Re-enable the account
sudo usermod --shell /bin/bash alice

Part 4: Groups — Creating and Managing

# Create a new group
sudo groupadd developers

# Create a system group (GID below 1000)
sudo groupadd --system myapp-group

# View all groups and their members
getent group | grep -E "sudo|docker|developers|www-data"

Expected output:

sudo:x:27:youruser
www-data:x:33:
docker:x:999:youruser
developers:x:1003:
# Add alice to the developers group
sudo usermod -aG developers alice

# Add alice to multiple groups at once
sudo usermod -aG developers,www-data,docker alice

# Verify alice's groups
id alice

Expected output:

uid=1002(alice) gid=1002(alice) groups=1002(alice),33(www-data),100(users),999(docker),1003(developers)
# CRITICAL: The -a flag is mandatory
# Without -a, usermod REPLACES all supplementary groups:
# sudo usermod -G developers alice  ← DANGER: removes alice from all other groups

# Remove alice from a specific group
sudo gpasswd -d alice www-data

# Rename a group
sudo groupmod --new-name devteam developers

# Delete a group (fails if it's anyone's primary group)
sudo groupdel devteam

Apply group changes without logging out:

# After adding yourself to a group, reload group membership in current shell
newgrp docker   # Or: exec su - $USER

Part 5: sudo Configuration

The sudo group grants full root access. Understand exactly how it works.

# Add alice to sudo group
sudo usermod -aG sudo alice

# Verify
id alice | grep sudo

Expected output:

uid=1002(alice) gid=1002(alice) groups=1002(alice),27(sudo),...
# View the sudoers file safely (never edit /etc/sudoers directly)
sudo visudo

Key sudoers syntax:

# Full sudo access (password required):
youruser ALL=(ALL:ALL) ALL

# Sudo access without password (NOPASSWD — only for automation accounts):
deploybot ALL=(ALL:ALL) NOPASSWD: ALL

# Limit to specific commands only:
alice ALL=(ALL) /usr/bin/systemctl restart nginx, /usr/bin/systemctl status nginx

# Allow group sudo:
%sudo ALL=(ALL:ALL) ALL
%developers ALL=(ALL) /usr/bin/docker, /usr/local/bin/docker-compose
# Add a per-user sudoers rule in a drop-in file (safer than editing /etc/sudoers)
echo "alice ALL=(ALL) /usr/bin/systemctl" | \
  sudo tee /etc/sudoers.d/alice-systemctl

# Validate the drop-in file
sudo visudo -c -f /etc/sudoers.d/alice-systemctl

Expected output:

/etc/sudoers.d/alice-systemctl: parsed OK

Part 6: SSH Key Provisioning for Users

# Provision SSH public key for alice (run as root or with sudo)
sudo -u alice mkdir -p /home/alice/.ssh
sudo -u alice chmod 700 /home/alice/.ssh

# Add alice's public key
echo "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIGx8alice-public-key-here alice@laptop" | \
  sudo tee -a /home/alice/.ssh/authorized_keys

sudo chmod 600 /home/alice/.ssh/authorized_keys
sudo chown alice:alice /home/alice/.ssh/authorized_keys

# Verify
sudo cat /home/alice/.ssh/authorized_keys

Expected output:

ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIGx8alice-public-key-here alice@laptop
# Test alice can SSH in (from her machine)
ssh alice@YOUR_SERVER_IP

Part 7: Deleting Users and Cleanup

# Delete user and home directory
sudo deluser --remove-home alice

# Delete user but keep home directory (for data preservation)
sudo deluser alice

# Delete a group
sudo groupdel developers

# Find files owned by a deleted user's UID (orphaned files)
# Replace 1002 with the UID of the deleted user
sudo find / -uid 1002 -type f 2>/dev/null | head -10

Expected output:

(no output if home was removed and user owned no other files)
# Change orphaned files to a different owner
sudo find / -uid 1002 2>/dev/null -exec chown root:root {} \;

Part 8: The Sovereignty Layer — User Audit Script

echo "=== SOVEREIGN USER AUDIT ==="
echo ""

echo "[ Human login accounts ]"
awk -F: '$3 >= 1000 && $7 !~ /nologin|false/ {
  printf "    %-20s UID:%-6s Home:%-25s Shell:%s\n", $1, $3, $6, $7
}' /etc/passwd

echo ""
echo "[ sudo group members ]"
getent group sudo | cut -d: -f4 | tr ',' '\n' | \
  awk '{print "    " $0 " (has full root access via sudo)"}'

echo ""
echo "[ Accounts with no password (security risk) ]"
sudo awk -F: '($2 == "" || $2 == "!") && $3 >= 1000' /etc/shadow \
  2>/dev/null | cut -d: -f1 | \
  awk '{print "    ⚠ " $0}' || echo "    ✓ All accounts have passwords or are locked"

echo ""
echo "[ Service accounts with login shells (unusual) ]"
awk -F: '$3 < 1000 && $7 !~ /nologin|false|sync/ && $7 != "" {
  printf "    ⚠ %-15s UID:%-6s Shell:%s\n", $1, $3, $7
}' /etc/passwd | grep -v "^    ⚠ root"

echo ""
echo "[ Users with SSH keys ]"
for homedir in /home/*/; do
  user=$(basename "$homedir")
  keyfile="$homedir/.ssh/authorized_keys"
  if [ -f "$keyfile" ] && [ -s "$keyfile" ]; then
    keycount=$(grep -c "^ssh" "$keyfile" 2>/dev/null || echo 0)
    echo "    ✓ $user: $keycount authorized key(s)"
  fi
done

Expected output:

=== SOVEREIGN USER AUDIT ===

[ Human login accounts ]
    youruser             UID:1001   Home:/home/youruser        Shell:/bin/bash
    deploybot            UID:1003   Home:/home/deploybot       Shell:/bin/bash

[ sudo group members ]
    youruser (has full root access via sudo)

[ Accounts with no password (security risk) ]
    ✓ All accounts have passwords or are locked

[ Service accounts with login shells (unusual) ]
    (none — all service accounts have nologin shells)

[ Users with SSH keys ]
    ✓ youruser: 1 authorized key(s)

SovereignScore: 99/100 — all user management is local. No LDAP, no cloud IAM, no external identity provider.


Quick Reference

# CREATE
sudo adduser username                    # Create user (interactive, Ubuntu)
sudo adduser --disabled-password \       # Create user (non-interactive)
  --gecos "" username
sudo useradd --system --no-create-home \ # Create service account
  --shell /usr/sbin/nologin svcuser
sudo groupadd groupname                  # Create group

# READ
id username                              # UID, GID, all groups
getent passwd username                   # Full passwd entry
getent group groupname                   # Group members
groups username                          # Just the group names
finger username                          # Detailed user info (if installed)

# UPDATE
sudo usermod -aG groupname username      # Add to group (-a is critical)
sudo usermod -L username                 # Lock account
sudo usermod -U username                 # Unlock account
sudo usermod --shell /bin/bash username  # Change shell
sudo usermod --expiredate 2026-12-31 u   # Set expiry
sudo passwd username                     # Change password
sudo passwd --expire username            # Force password change on login
sudo gpasswd -d username groupname       # Remove from group

# DELETE
sudo deluser --remove-home username      # Delete user + home
sudo deluser username                    # Delete user (keep home)
sudo groupdel groupname                  # Delete group

Troubleshooting

usermod: user 'alice' is currently used by process PID

Cause: Alice is logged in — can’t modify a logged-in user’s primary group. Fix: Ask Alice to log out, or use sudo pkill -u alice to terminate her sessions, then re-run usermod.

Group change not taking effect after usermod -aG

Cause: The user’s current session was established before the group change — shell sessions cache group membership at login. Fix: The user must log out and back in, or run newgrp groupname to reload group membership in the current shell.

sudo: alice is not in the sudoers file. This incident will be reported.

Cause: Alice is not in the sudo group. Fix: sudo usermod -aG sudo alice (run as a user already in sudo). Alice must then log out and back in for the group change to take effect.


Conclusion

Linux user and group management on Ubuntu 24.04 runs entirely from four local files: /etc/passwd, /etc/shadow, /etc/group, and /etc/sudoers. No cloud dependency, no external directory service. The adduser command creates complete user accounts in seconds. usermod -aG manages group membership. The audit script in Part 8 gives a one-command view of every account, sudo access, and SSH key on the system.

The natural next step is SSH Hardening Guide 2026 — securing the SSH service that authenticates all these users remotely.


People Also Ask

What is the difference between adduser and useradd on Ubuntu?

adduser is a Perl script that wraps useradd with Ubuntu-friendly defaults: it creates the home directory, copies /etc/skel, sets /bin/bash as the default shell, and prompts interactively for a password. useradd is the raw POSIX utility — it does none of that by default. On Ubuntu, always use adduser for human accounts (simpler) and useradd --system --no-create-home --shell /usr/sbin/nologin for service accounts (precise control). On RHEL/CentOS/Fedora, adduser is just a symlink to useradd — the distinction doesn’t exist there.

Why is the -a flag critical in usermod -aG?

usermod -G groupname username replaces all supplementary groups with only groupname. If Alice was in sudo, docker, and www-data, running usermod -G developers alice would remove her from all three. The -a (append) flag changes the behaviour to add developers while keeping all existing groups. Missing -a is the most common user management mistake on Linux and can silently revoke critical access (including sudo) from an account.

How do I create a shared directory that all members of a group can write to?

sudo mkdir /opt/shared
sudo chown root:developers /opt/shared
sudo chmod 2775 /opt/shared   # SetGID ensures new files inherit group ownership

The 2 prefix sets the SetGID bit — all files created inside /opt/shared automatically inherit the developers group, regardless of which group member created them. See our Linux File Permissions Guide for the complete SetGID explanation.


Further Reading


Tested on: Ubuntu 24.04 LTS (Hetzner CX22). shadow-utils 4.13. Last verified: April 17, 2026. Report a broken snippet if a command fails after a system update.

Further Reading

All Dev Corner

Comments