Comprehensive reference for managing Linux users, groups, permissions, ACLs, quotas, and authentication policies.

Table of Contents#

  1. Overview
  2. User Operations
  3. UID/GID Ranges and System Users
  4. Login Shells
  5. Group Operations
  6. Modifying Users
  7. Querying User Information
  8. Important Files
  9. Sudo Configuration
  10. Access Control Lists (ACLs)
  11. User Quotas
  12. PAM Password Policies
  13. Examples
  14. Troubleshooting
  15. Sources

1. Overview#

Linux user management controls who can log in, what they can access, and what privileges they have. The system identifies users by numeric UIDs and groups by GIDs. Authentication, authorization, and account policies are configured through files in /etc/, PAM modules, and tools like sudo. Understanding the full stack, from user creation to ACLs and quotas, is essential for system administration and security.

2. User Operations#

CommandDescription
sudo adduser <username>Create a new user (interactive, Debian-style)
sudo useradd <username>Create a new user (low-level, all distros)
sudo useradd -m -s /bin/bash <username>Create user with home directory and shell
sudo userdel <username>Delete a user (keeps home directory)
sudo userdel -r <username>Delete a user and their home directory
sudo passwd <username>Set or change a user's password
sudo chage -l <username>View password aging information
sudo chage -M 90 <username>Set maximum password age to 90 days
sudo chage -d 0 <username>Force password change on next login

3. UID/GID Ranges and System Users#

Linux reserves specific UID/GID ranges by convention (defined in /etc/login.defs):

RangeTypePurpose
0rootSuperuser
1-999System accountsDaemons, services (no login, no home directory)
1000-60000Regular usersHuman users (default UID_MIN/UID_MAX on most distros)
65534nobodyUnprivileged fallback user for NFS, etc.

Key settings in /etc/login.defs:

UID_MIN         1000
UID_MAX        60000
SYS_UID_MIN      201
SYS_UID_MAX      999
GID_MIN         1000
GID_MAX        60000

Creating system users:

# Create a system user (UID below 1000, no home, no login)
sudo useradd -r -s /usr/sbin/nologin <service-name>

# Create a system user with a specific home directory
sudo useradd -r -s /usr/sbin/nologin -d /var/lib/<service-name> -m <service-name>

# Verify the assigned UID
id <service-name>

4. Login Shells#

The login shell determines what happens when a user logs in. Non-interactive accounts should use a restricted shell:

ShellPurpose
/bin/bashStandard interactive shell
/bin/zshZ shell (interactive)
/bin/fishFish shell (interactive)
/usr/sbin/nologinPolitely denies login with a message; preferred for service accounts
/bin/falseSilently denies login (exits with status 1); older convention
/usr/bin/git-shellAllows only git push/pull operations (for git-only SSH accounts)
# Set a user's shell to nologin (disable interactive login)
sudo usermod -s /usr/sbin/nologin <username>

# List valid shells
cat /etc/shells

# Change your own shell
chsh -s /bin/zsh

Security note: service accounts should always use /usr/sbin/nologin or /bin/false. An interactive shell on a service account is a privilege escalation vector if the account is compromised.

5. Group Operations#

CommandDescription
sudo groupadd <groupname>Create a new group
sudo groupadd -g <gid> <groupname>Create a group with a specific GID
sudo groupdel <groupname>Delete a group
sudo usermod -aG <groupname> <username>Add a user to a group (append; -a is critical)
sudo gpasswd -d <username> <groupname>Remove a user from a group
groups <username>Show groups a user belongs to
getent group <groupname>Show members of a group
newgrp <groupname>Switch primary group for current session

Warning: omitting -a with -G replaces all supplementary groups with only the one specified.

6. Modifying Users#

CommandDescription
sudo usermod -l <newname> <oldname>Rename a user
sudo usermod -d /new/home -m <username>Change home directory and move files
sudo usermod -s /bin/zsh <username>Change the default shell
sudo usermod -L <username>Lock a user account (prefix ! to password hash)
sudo usermod -U <username>Unlock a user account
sudo usermod -e 2026-12-31 <username>Set account expiry date
sudo usermod -u <new-uid> <username>Change UID (update file ownership separately)
sudo usermod -g <new-gid> <username>Change primary group

After changing a UID, fix file ownership:

sudo find / -user <old-uid> -exec chown <new-uid> {} +

7. Querying User Information#

id <username>                # Show UID, GID, and groups
whoami                       # Show current user
who                          # Show logged-in users
w                            # Show logged-in users with activity
last                         # Show login history
last <username>              # Show login history for a specific user
lastlog                      # Show last login of all users
faillog -a                   # Show failed login attempts
getent passwd <username>     # Query user from all NSS sources (LDAP, local, etc.)

8. Important Files#

FileDescription
/etc/passwdUser account information (name, UID, GID, home, shell)
/etc/shadowEncrypted passwords and aging data (restricted access)
/etc/groupGroup definitions (name, GID, member list)
/etc/gshadowGroup passwords (rarely used)
/etc/login.defsDefault settings for user creation (UID/GID ranges, password policies)
/etc/skel/Template for new user home directories
/etc/sudoersSudo authorization policy
/etc/sudoers.d/Drop-in directory for modular sudo rules
/etc/security/limits.confPer-user resource limits (PAM)
/etc/pam.d/PAM module configuration files

Format of /etc/passwd:

username:x:UID:GID:comment:home:shell

Format of /etc/shadow:

username:$hash:last_change:min:max:warn:inactive:expire:reserved

9. Sudo Configuration#

Basics#

# Add user to sudo/wheel group
sudo usermod -aG sudo <username>    # Debian/Ubuntu
sudo usermod -aG wheel <username>   # RHEL/Fedora/Arch

# Add a sudoers drop-in file (safer than editing /etc/sudoers directly)
echo "<username> ALL=(ALL) NOPASSWD:ALL" | sudo tee /etc/sudoers.d/<username>
sudo chmod 440 /etc/sudoers.d/<username>

Sudoers Syntax#

Always edit with visudo to prevent syntax errors that lock you out:

sudo visudo                          # edit /etc/sudoers
sudo visudo -f /etc/sudoers.d/myfile # edit a drop-in file

Sudoers rule format:

<who> <where>=(<runas>) <commands>
FieldDescription
<who>User or %group
<where>Hostname (usually ALL)
<runas>User to run as (usually ALL or root)
<commands>Comma-separated command paths, or ALL

Examples:

# Allow user full sudo with password
alice ALL=(ALL) ALL

# Allow group without password
%devops ALL=(ALL) NOPASSWD: ALL

# Allow specific commands only
bob ALL=(root) /usr/bin/systemctl restart nginx, /usr/bin/journalctl

# Allow a user to run commands as another user
deploy ALL=(www-data) NOPASSWD: /usr/bin/rsync

# Require password, but cache for 30 minutes
Defaults:alice timestamp_timeout=30

# Log all sudo commands to a file
Defaults logfile="/var/log/sudo.log"

Sudo Security#

SettingDescription
Defaults requirettyRequire a TTY for sudo (blocks cron/scripts)
Defaults passwd_tries=3Limit password attempts
Defaults secure_path="/usr/local/sbin:..."Override PATH for sudo commands
Defaults !root_sudoPrevent root from using sudo
Defaults lecture="always"Always show the "be careful" lecture

10. Access Control Lists (ACLs)#

Standard Unix permissions (owner/group/other) only support one owner and one group. ACLs provide fine-grained control for multiple users and groups.

Prerequisites: filesystem must be mounted with ACL support (ext4 has it by default; XFS always supports it).

Viewing ACLs#

# Show ACLs for a file
getfacl <file>

# Show ACLs for a directory
getfacl <directory>

Setting ACLs#

# Grant a specific user read/write
setfacl -m u:<username>:rw <file>

# Grant a specific group read-only
setfacl -m g:<groupname>:r <file>

# Set default ACL on a directory (inherited by new files)
setfacl -d -m u:<username>:rwx <directory>

# Remove a specific ACL entry
setfacl -x u:<username> <file>

# Remove all ACLs (revert to standard permissions)
setfacl -b <file>

# Copy ACLs from one file to another
getfacl <source> | setfacl --set-file=- <target>

# Recursive ACL application
setfacl -R -m g:<groupname>:rx <directory>

ACL Mask#

The mask defines the maximum effective permissions for named users and groups:

# Set the mask (limits effective permissions)
setfacl -m m::rx <file>

# After setting: a user with rw ACL effectively gets only rx

ACL Indicators#

When ACLs are present, ls -l shows a + after the permission bits:

-rw-rwxr--+ 1 alice devs 4096 Mar 22 10:00 report.txt

11. User Quotas#

Quotas limit disk usage per user or group, preventing any single user from filling a filesystem.

Setup#

# Install quota tools
sudo apt install quota              # Debian/Ubuntu
sudo pacman -S quota-tools          # Arch

# Enable quotas in /etc/fstab (add usrquota,grpquota to options)
# /dev/sda1 /home ext4 defaults,usrquota,grpquota 0 2

# Remount the filesystem
sudo mount -o remount /home

# Initialize quota database
sudo quotacheck -cugm /home

# Enable quotas
sudo quotaon /home

Managing Quotas#

# Edit quotas for a user (opens editor)
sudo edquota <username>

# Set quotas directly (soft=500M, hard=1G, inodes soft=10000, hard=15000)
sudo setquota -u <username> 500M 1G 10000 15000 /home

# Copy quotas from one user to another
sudo edquota -p <template-user> <target-user>

# View quota for a user
quota -u <username>

# View quota report for all users
sudo repquota -a

# Set a grace period for soft limits
sudo edquota -t

Quota Concepts#

ConceptDescription
Soft limitThreshold that can be exceeded temporarily (grace period)
Hard limitAbsolute maximum; writes fail beyond this
Grace periodTime a user can exceed the soft limit before it becomes enforced
Block quotaLimits total disk space (in KB or MB)
Inode quotaLimits the number of files (each file uses one inode)

12. PAM Password Policies#

PAM (Pluggable Authentication Modules) enforces password complexity, lockout, and other policies.

Password Quality (pam_pwquality)#

Configuration in /etc/security/pwquality.conf or as PAM module arguments:

# Minimum password length
minlen = 12

# Require at least 1 uppercase, 1 lowercase, 1 digit, 1 special
ucredit = -1
lcredit = -1
dcredit = -1
ocredit = -1

# Reject passwords containing the username
usercheck = 1

# Reject dictionary words
dictcheck = 1

# Maximum consecutive identical characters
maxrepeat = 3

# Minimum number of character classes (uppercase, lowercase, digit, other)
minclass = 3

# Reject passwords similar to the old one
difok = 5

PAM configuration (typically in /etc/pam.d/common-password or /etc/pam.d/system-auth):

password requisite pam_pwquality.so retry=3 enforce_for_root
password required  pam_unix.so use_authtok sha512 shadow

Account Lockout (pam_faillock)#

# /etc/security/faillock.conf (modern method)
deny = 5            # lock after 5 failed attempts
unlock_time = 600   # unlock after 600 seconds (10 minutes)
fail_interval = 900 # count failures within 15 minutes

# PAM configuration
auth required pam_faillock.so preauth
auth required pam_faillock.so authfail
account required pam_faillock.so
# View failed login attempts
faillock --user <username>

# Manually unlock a locked account
faillock --user <username> --reset

Password History (pam_pwhistory)#

Prevent users from reusing recent passwords:

# In /etc/pam.d/common-password or system-auth
password required pam_pwhistory.so remember=12 enforce_for_root use_authtok

13. Examples#

Create a System User for a Service#

sudo useradd -r -s /usr/sbin/nologin -d /var/lib/myapp -m myapp

Bulk Add Users from a File#

while IFS=: read -r user pass; do
  sudo useradd -m "$user"
  echo "$user:$pass" | sudo chpasswd
done < users.txt

Grant Sudo Privileges#

# Add user to sudo/wheel group
sudo usermod -aG sudo <username>    # Debian/Ubuntu
sudo usermod -aG wheel <username>   # RHEL/Fedora/Arch

# Or add a sudoers entry (use visudo or drop-in file)
echo "<username> ALL=(ALL) NOPASSWD:ALL" | sudo tee /etc/sudoers.d/<username>
sudo chmod 440 /etc/sudoers.d/<username>

Set Up a Shared Directory with ACLs#

# Create the shared directory
sudo mkdir /srv/shared
sudo chown root:devteam /srv/shared
sudo chmod 2770 /srv/shared          # setgid ensures new files inherit group

# Grant additional access to another group
setfacl -m g:managers:rx /srv/shared
setfacl -d -m g:managers:rx /srv/shared    # default ACL for new files

Audit User Accounts#

# Find users with UID 0 (should only be root)
awk -F: '$3 == 0 {print $1}' /etc/passwd

# Find users with empty passwords
sudo awk -F: '$2 == "" {print $1}' /etc/shadow

# Find users with no expiry set
sudo chage -l <username> | grep "Account expires"

# Find accounts that have never logged in
lastlog | grep "**Never logged in**"

Troubleshooting#

IssueCauseSolution
useradd creates user without home directoryMissing -m flag (behavior varies by distro)Use useradd -m or set CREATE_HOME yes in /etc/login.defs
User cannot sudoNot in sudo/wheel groupusermod -aG sudo <user> (Debian) or wheel (RHEL/Arch); user must log out and back in
usermod -G removed all other groupsMissing -a (append) flagAlways use -aG together; re-add removed groups
ACLs not workingFilesystem mounted without ACL supportRemount with acl option or check if the filesystem supports ACLs natively
Quota not enforcedQuota not enabled or database not initializedRun quotacheck -cugm and quotaon on the filesystem
Password change rejectedPAM policy too strictCheck /etc/security/pwquality.conf; adjust minlen, credits, or difok
Account locked after failed loginspam_faillock triggeredUnlock with faillock --user <user> --reset
New user cannot log in via SSHShell set to /usr/sbin/nologin or not listed in /etc/shellsVerify shell with getent passwd <user> and check /etc/shells

Sources#

  • man useradd, man usermod, man userdel
  • man passwd, man shadow, man chage
  • man sudoers, man visudo
  • man setfacl, man getfacl
  • man edquota, man repquota
  • man pam_pwquality, man pam_faillock, man pam_pwhistory