At the heart of Linux authentication lie two critically important files: /etc/passwd and /etc/shadow. Every time a user logs into the system, Linux consults these files to verify credentials. Understanding their structure is essential for any system administrator.
Let's examine how these files work, what each field means, and how to properly manage them.
Purpose of These Files
/etc/passwd — the primary user account database. Contains basic information: username, UID, home directory, shell. Historically stored passwords too, but this proved insecure.
/etc/shadow — stores encrypted passwords and expiration policies. Introduced to enhance security: passwords were separated from public information and access was restricted.
Key difference:
/etc/passwd— readable by all users (permissions 644)/etc/shadow— accessible only by root (permissions 640 or 600)
This means any user can see the list of system accounts, but cannot access password hashes.
Structure of /etc/passwd
Each line in /etc/passwd describes one user and consists of seven colon-separated fields:
username:password:UID:GID:GECOS:home_directory:shell
Viewing the File
cat /etc/passwd
Example entry:
john:x:1001:1001:John Smith,Room 404,555-1234:/home/john:/bin/bash
Field-by-Field Breakdown
1. Username
Unique login name. Maximum length — 32 characters.
john
2. Password
In modern systems, this is always x or *, indicating the actual password is stored in /etc/shadow.
Possible values:
x— password in /etc/shadow*or!— account locked- empty — login without password (extremely insecure)
x
3. UID (User ID)
Numeric user identifier. The system uses UID internally, not the username.
Standard ranges:
0— root (superuser)1-999— system accounts1000+— regular users
1001
4. GID (Group ID)
Identifier of the user's primary group. Corresponds to an entry in /etc/group.
1001
5. GECOS (comment field)
Additional user information. Historically used for GECOS system compatibility. Can contain multiple comma-separated fields:
- Full name
- Room/office number
- Work phone
- Home phone
- Other information
John Smith,Room 404,555-1234
This field is optional and may be empty.
6. Home Directory
Path to the user's home directory. Users land here upon login.
/home/john
7. Shell
Program launched when the user logs into the system.
Typical values:
/bin/bash— Bash (most popular shell)/bin/sh— standard shell/bin/zsh— Z shell/usr/sbin/nologin— prevents interactive login/bin/false— also blocks login
/bin/bash
Real-World Entry Examples
Root user:
root:x:0:0:root:/root:/bin/bash
System user (daemon):
www-dаta:x:33:33:www-dаta:/var/www:/usr/sbin/nologin
Regular user:
alice:x:1002:1002:Alice Johnson:/home/alice:/bin/bash
Locked account:
backup:*:1003:1003:Backup User:/backup:/bin/false
Structure of /etc/shadow
The /etc/shadow file contains encrypted passwords and related security policy information.
Viewing the File (requires root privileges)
sudo cat /etc/shadow
Each line consists of nine fields:
username:password:lastchanged:minimum:maximum:warn:inactive:expire:reserved
Example entry:
john:$6$rounds=5000$salt$hashedpassword:19000:0:99999:7:30:19500:
Field-by-Field Breakdown
1. Username
Matches the username in /etc/passwd. The files are synchronized.
john
2. Password (encrypted)
Password hash in special format. If the field contains ! or *, the user cannot log in with a password.
Hash format:
$id$salt$hashed
Where id is the encryption algorithm:
$1$— MD5 (deprecated, insecure)$5$— SHA-256$6$— SHA-512 (recommended)$y$— yescrypt (modern)
Special values:
!or*— account locked!!— password not yet set- empty — login without password (dangerous)
$6$rounds=5000$salt$hashedpassword
3. Last Changed
Number of days since January 1, 1970 (Unix epoch) when the password was last changed.
19000
To convert to a readable date:
date -d "1970-01-01 UTC 19000 days"
4. Minimum
Minimum number of days that must pass before password can be changed. If 0, the user can change password anytime.
0
5. Maximum
Maximum number of days the password remains valid. After this, the user is forced to change it.
Standard value — 99999 (approximately 273 years, effectively "never").
99999
6. Warning
Number of days before password expiration when the system starts warning the user.
7
7. Inactive
Number of days after password expiration during which the user can still log in and change the password. After this, the account locks.
Empty value means immediate lockout.
30
8. Expire
Account expiration date in days since 1970. After this date, the user cannot log in regardless of password validity.
19500
9. Reserved
Reserved for future use. Usually empty.
Practical File Operations
Find User with Specific UID
grep ':1001:' /etc/passwd
List All Regular Users (UID >= 1000)
awk -F: '$3 >= 1000 {print $1}' /etc/passwd
Check if User Exists
grep -q '^username:' /etc/passwd && echo "User exists" || echo "User not found"
List Users with /bin/bash
grep '/bin/bash$' /etc/passwd | cut -d: -f1
Find Users Without Password (insecure!)
sudo awk -F: '($2 == "") {print $1}' /etc/shadow
Check Locked Accounts
sudo awk -F: '($2 == "!" || $2 == "*") {print $1}' /etc/shadow
See When User Last Changed Password
sudo chage -l username
This command outputs readable information from /etc/shadow.
User Creation and Management
Creating a User
Basic command:
sudo useradd username
With additional parameters:
sudo useradd -m -d /home/username -s /bin/bash -c "Full Name" username
Parameters:
-m— create home directory-d— specify home directory path-s— specify shell-c— comment (GECOS)
Alternative — interactive mode:
sudo adduser username
adduser is a friendlier wrapper around useradd that asks questions interactively.
Setting Password
sudo passwd username
System will prompt to enter new password twice.
Modifying User Information
Change GECOS (full name):
sudo chfn username
Change shell:
sudo chsh -s /bin/zsh username
Change home directory:
sudo usermod -d /new/home/path username
Locking and Unlocking Accounts
Lock:
sudo usermod -L username
Or:
sudo passwd -l username
This adds ! before the password hash in /etc/shadow.
Unlock:
sudo usermod -U username
Or:
sudo passwd -u username
Deleting a User
Account only:
sudo userdel username
With home directory:
sudo userdel -r username
The -r option removes the home directory and user's mail spool.
Password Policy Configuration
Change Password Validity Period
sudo chage -M 90 username
Password will be valid for 90 days.
Set Minimum Period Between Changes
sudo chage -m 7 username
User cannot change password more frequently than once every 7 days.
Configure Warning Period
sudo chage -W 14 username
System will start warning 14 days before password expiration.
Set Account Expiration Date
sudo chage -E 2025-12-31 username
Account will automatically lock after December 31, 2025.
Force Password Change on Next Login
sudo chage -d 0 username
Or:
sudo passwd -e username
User will be required to change password on next login.
Security and Best Practices
File Permissions
Verify correct permissions:
ls -l /etc/passwd /etc/shadow
Should be:
-rw-r--r-- 1 root root /etc/passwd
-rw-r----- 1 root shadow /etc/shadow
If permissions differ, correct them:
sudo chmod 644 /etc/passwd
sudo chmod 640 /etc/shadow
Backup
Always create backups before manual editing:
sudo cp /etc/passwd /etc/passwd.backup
sudo cp /etc/shadow /etc/shadow.backup
Direct Editing (not recommended)
If manual editing is absolutely necessary, use special commands:
sudo vipw # safe editing of /etc/passwd
sudo vipw -s # safe editing of /etc/shadow
These commands lock files during editing and verify syntax.
User Auditing
Regular checks:
Users with UID 0 (should only be root):
awk -F: '($3 == 0) {print $1}' /etc/passwd
Users without passwords:
sudo awk -F: '($2 == "") {print $1}' /etc/shadow
Users with login shells (potential system access):
grep -v '/nologin\|/false' /etc/passwd | cut -d: -f1
Strengthening Hash Algorithm
Ensure the system uses SHA-512 or yescrypt. Check /etc/login.defs:
grep ENCRYPT_METHOD /etc/login.defs
Should show:
ENCRYPT_METHOD SHA512
Or in /etc/pam.d/common-password (Debian/Ubuntu):
password [success=1 default=ignore] pam_unix.so obscure sha512
Related Files
/etc/group
Contains user group information:
cat /etc/group
Format:
groupname:password:GID:user_list
/etc/gshadow
Protected passwords for groups (rarely used):
sudo cat /etc/gshadow
/etc/login.defs
Default parameters for user creation:
cat /etc/login.defs
Configures:
- UID/GID ranges
- Password policies
- Encryption algorithms
/etc/default/useradd
Default settings for useradd command:
cat /etc/default/useradd
Common Errors and Solutions
Problem: after editing /etc/passwd I cannot log into the system.
Cause: syntax error in the file.
Solution: boot into recovery mode, remount root partition as writable, and restore from backup:
mount -o remount,rw /
cp /etc/passwd.backup /etc/passwd
Problem: user cannot log in despite correct password.
Cause: account locked (! in /etc/shadow) or shell is /usr/sbin/nologin.
Solution: check and unlock:
sudo passwd -u username
sudo usermod -s /bin/bash username
sudo passwd -u username
sudo usermod -s /bin/bash username
Problem: passwd command doesn't work for user.
Cause: /etc/shadow file corrupted or has incorrect permissions.
Solution: verify permissions and ownership:
sudo chmod 640 /etc/shadow
sudo chown root:shadow /etc/shadow
Problem: user created but home directory doesn't exist.
Cause: useradd without -m option.
Solution: create directory manually:
sudo mkdir /home/username
sudo chown username:username /home/username
sudo cp -r /etc/skel/. /home/username/
Migrating Users Between Servers
Exporting Users
Create script to export specific users (UID >= 1000):
Export passwd entries:
awk -F: '$3 >= 1000 && $3 < 65534' /etc/passwd > users.passwd
Export shadow entries:
sudo awk -F: '$3 >= 1000 && $3 < 65534 {print $1}' /etc/passwd | \
while read user; do sudo grep "^$user:" /etc/shadow; done > users.shadow
Export groups:
awk -F: '$3 >= 1000 && $3 < 65534' /etc/group > users.group
Importing on New Server
Merge files:
sudo cat users.passwd >> /etc/passwd
sudo cat users.shadow >> /etc/shadow
sudo cat users.group >> /etc/group
Create home directories:
cat users.passwd | cut -d: -f1,6 | while IFS=: read user home; do
if [ ! -d "$home" ]; then
sudo mkdir -p "$home"
sudo chown "$user:$user" "$home"
fi
done
⚠️ Warning: ensure UID/GID don't conflict with existing users.
Conclusion
Files /etc/passwd and /etc/shadow form the foundation of Linux user management. Understanding their structure is critical for administration: from creating accounts to configuring security policies and troubleshooting access issues.
Core principles: never edit these files directly without absolute necessity, use specialized commands (useradd, usermod, passwd, chage), regularly verify file permissions, and create backups before any modifications.
These simple precautions will protect your system from accidental errors and unauthorized access.