Featured image

Table of Contents Link to heading

User Private Group (UPG) Link to heading

Most modern Linux distributions create a User Private Group (UPG) automatically when a new user account is created. The group has the same name and GID as the username and UID, and the new user is the sole member.

The UPG model ensures that new files created by the user are owned by a group that no other user shares — preventing accidental information leakage through group-readable files. Users can explicitly grant group access to specific files when collaboration is needed.

On distributions that do not implement UPG (some older systems), new users are assigned to a shared default group (typically users).

Group Management Link to heading

Groups provide a mechanism for users to share file access. An administrator creates groups aligned with organisational roles (developers, webteam, dba) and adds users to those groups. File and directory permissions are then set for the group rather than for individual users — which scales far better than per-user ACLs.

For commands to view existing group information, see Group Accounts.

All group management commands require administrative privileges.

Creating Groups: groupadd Link to heading

# Create a new group
sudo groupadd developers

# Create with a specific GID
sudo groupadd --gid 2001 developers

# Create a system group (GID < 1000, no home directory convention)
sudo groupadd --system nginx

GID considerations:

  • GIDs 0–999 are reserved for system groups on most distributions
  • To create a system group (GID in the reserved range), use --system or --gid with a value below 1000 combined with --system
  • In environments with multiple systems, coordinate GIDs across hosts to ensure consistent group identity when sharing files via NFS or other network storage
  • Avoid creating GIDs that overlap with the UID range you use for regular users — it prevents confusion when inspecting file ownership

Group naming conventions:

  • First character: lowercase letter (a-z) or underscore _
  • Remaining characters: lowercase alphanumeric, hyphen -, or underscore _
  • Last character: not a hyphen
  • Maximum length: 32 characters on most distributions (16 is a safer maximum for compatibility)

Deleting Groups: groupdel Link to heading

groupdel removes a group from the system. Only supplementary groups can be deleted — a group that is the primary group of any user account cannot be deleted until that user’s primary group is changed.

sudo groupdel developers

When a group is deleted, files that were group-owned by it become orphaned — they retain the numeric GID but it no longer maps to a name. Find orphaned files after group deletion:

sudo find / -nogroup 2>/dev/null
sudo find / -gid 2001 2>/dev/null    # by numeric GID if known

Modifying Groups: groupmod Link to heading

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

# Change the GID
sudo groupmod --gid 2002 developers
Warning

Changing a group’s GID with groupmod --gid orphans all files previously owned by the old GID. Those files retain the old numeric GID which no longer maps to a group name. After changing a GID, find and update affected files:

sudo find / -gid OLD_GID -exec chgrp NEW_GID {} \;

Renaming a group (changing the name, not the GID) does not affect file ownership — the GID is unchanged, so files retain correct group ownership immediately.

User Account Configuration Files Link to heading

Before creating users, understand the default configuration that shapes newly created accounts.

/etc/default/useradd Link to heading

/etc/default/useradd stores the defaults used by useradd when options are not explicitly specified. View or change defaults with:

useradd -D              # display current defaults
sudo useradd -D --shell /bin/zsh    # change default shell for new accounts

useradd -D

Field Description
GROUP Default primary GID (used when UPG is not enabled)
HOME Base directory for user home directories (typically /home)
INACTIVE Days after password expiry before account is locked (-1 = disabled)
EXPIRE Default account expiration date (empty = never)
SHELL Default login shell
SKEL Skeleton directory copied into new home directories (/etc/skel)
CREATE_MAIL_SPOOL Whether to create a mail spool file for the user

/etc/login.defs Link to heading

/etc/login.defs defines system-wide defaults for user and group creation — UID/GID ranges, password policy, and home directory behaviour. Edit this file directly to change the values:

# View active settings (excludes comments and blank lines)
grep -Ev '^#|^$' /etc/login.defs

/etc/login.defs

Key settings:

Setting Description
UID_MIN / UID_MAX Range for regular user UIDs (typically 1000–60000)
GID_MIN / GID_MAX Range for regular group GIDs
PASS_MAX_DAYS Maximum days before password must be changed
PASS_MIN_DAYS Minimum days between password changes
PASS_MIN_LEN Minimum password length
PASS_WARN_AGE Days before expiry that user receives a warning
CREATE_HOME Whether to create home directories by default
UMASK Default umask for new home directories
USERGROUPS_ENAB Enable UPG (create a private group per user)
ENCRYPT_METHOD Password hashing algorithm (SHA512 is current standard)

User Management Link to heading

Creating Users: useradd and adduser Link to heading

Linux provides two tools for creating users with different levels of abstraction:

useradd — Low-Level (Universal) Link to heading

useradd is available on all Linux distributions and requires explicit options for a complete account setup. Without options, it creates a minimal account that may lack a home directory or usable password.

# Create with home directory (explicit — some distributions require this)
sudo useradd --create-home username

# Full account creation
sudo useradd \
  --uid 1500 \
  --gid developers \
  --groups sudo,docker \
  --shell /bin/bash \
  --create-home \
  --comment "Jane Smith" \
  username

# Create a system account (service account, no home, nologin shell)
sudo useradd --system --shell /sbin/nologin --comment "nginx web server" nginx

# Create with skeleton directory (files from /etc/skel copied to home)
sudo useradd --skel /etc/skel --create-home username

useradd

adduser — High-Level (Debian/Ubuntu) Link to heading

adduser is an interactive Perl script on Debian-based distributions. It walks through account creation with sensible prompts and defaults — home directory, password, and GECOS information are all handled interactively:

sudo adduser username                   # interactive setup
sudo adduser --no-create-home username  # no home directory
sudo adduser --home /opt/app username   # custom home path
sudo adduser --shell /bin/zsh username  # custom shell
sudo adduser --ingroup developers username  # assign primary group

adduser

Note
adduser is not available on RHEL/CentOS/Rocky Linux — use useradd on those systems. When writing scripts that must run on multiple distributions, use useradd with explicit options rather than adduser.

UID Considerations Link to heading

UID Range Purpose
0 Root — any account with UID 0 has full root privileges, regardless of name
1–499 (or 1–999) System accounts — reserved for service accounts
65534 nfsnobody — special account for unmapped NFS users
1000+ Regular user accounts (conventional starting point)

Operational guidelines:

  • In networked environments sharing home directories via NFS, coordinate UID assignments across all hosts — mismatched UIDs cause permission problems where a user on host A owns files that appear orphaned on host B
  • For maximum compatibility with legacy systems, keep UIDs below 60000
  • Starting regular users at 1000 leaves a large range for system accounts (1–999) and prevents conflicts with future distribution packages

Username Conventions Link to heading

  • First character: lowercase letter (a-z) or underscore _
  • Remaining characters: lowercase alphanumeric, hyphen -, or underscore _
  • Last character: not a hyphen
  • Maximum length: 32 characters (16 characters for broadest compatibility)
  • Use --badname with adduser to allow names that violate these conventions (not recommended for production)

Password Management Link to heading

A newly created account has no password set (or a locked password, depending on distribution). The account cannot be used until a password is assigned.

# Set or change a user's password (prompts for new password)
sudo passwd username

# Change your own password
passwd

# Lock an account (prepend ! to password hash in /etc/shadow)
sudo passwd --lock username

# Unlock an account
sudo passwd --unlock username

# Expire a password immediately (force change at next login)
sudo passwd --expire username

# Set an empty password (passwordless login — not recommended in production)
sudo passwd --delete username

# Check account status
sudo passwd -S username
# username P 01/15/2024 0 99999 7 -1 (P=password set, L=locked, NP=no password)

Password policy factors:

Factor Guidance
Length Minimum 12 characters; longer passphrases are better than complex short passwords
Composition Mix of character types; avoid dictionary words and keyboard patterns
Rotation High-privilege accounts: every 30–60 days; standard users: every 90 days
History Prevent reuse of recent passwords (configured via PAM pam_pwhistory)

If an account is compromised and the password has a defined maximum age, the intruder loses access when the password expires — limiting the window of unauthorised access.

Password Aging: chage Link to heading

chage manages the password aging policy stored in /etc/shadow on a per-account basis:

# List current password aging information
sudo chage --list username
chage -l username               # shorthand

# Force password change at next login (set last change date to epoch)
sudo chage --lastday 0 username

# Set maximum password age to 90 days
sudo chage --maxdays 90 username

# Disable password expiration
sudo chage --maxdays -1 username

# Set account expiration date
sudo chage --expiredate 2025-12-31 username

# Set warning period (days before expiry that user is warned)
sudo chage --warndays 14 username

# Set inactive period (days after expiry before account locks)
sudo chage --inactive 30 username

Deleting Users: userdel Link to heading

# Remove the account only (home directory and mail spool preserved)
sudo userdel username

# Remove the account, home directory, and mail spool
sudo userdel --remove username

# Remove in an alternate root directory (for chroot environments)
sudo userdel --root /chroot username

After deletion, files owned by the deleted UID become orphaned. Find and reassign or remove them:

sudo find / -nouser 2>/dev/null                     # orphaned files
sudo find / -nouser 2>/dev/null -exec ls -la {} \;  # with details

Modifying Users: usermod Link to heading

usermod modifies an existing account’s attributes. Most changes take effect at the next login.

# Rename a user account
sudo usermod --login new_username old_username

# Change a user's UID
sudo usermod --uid 1600 username

# Change the login shell
sudo usermod --shell /bin/zsh username

# Add to supplementary groups (without removing existing group memberships)
sudo usermod --append --groups docker,developers username

# Replace supplementary group list entirely (removes all current memberships)
sudo usermod --groups docker,developers username

# Move home directory to a new path
sudo usermod --move-home --home /opt/users/username username

# Set account expiration date
sudo usermod --expiredate 2025-12-31 username

# Remove account expiration
sudo usermod --expiredate "" username

# Lock or unlock account
sudo usermod --lock username
sudo usermod --unlock username
Warning
usermod --groups (without --append) replaces all supplementary group memberships with the new list. If you intend to add a user to a group without removing them from others, always use --append --groups. Accidentally removing a user from the sudo group locks them out of administrative access.