/etc/passwd and /etc/shadow
/etc/passwd and /etc/shadow are two text files that manage user information on a Linux system. /etc/passwd stores basic information such as the username, UID, and home directory, and is readable by all users. Password hashes are stored separately in /etc/shadow, which is protected by stricter permissions. Each file uses colon-separated fields. It is safer to interact with these files indirectly through commands such as getent passwd and passwd.
Syntax
/etc/passwd uses 7 colon-separated fields.
username:x:UID:GID:GECOS:home_directory:login_shell
/etc/shadow uses 9 colon-separated fields.
username:hash:last_changed:min_days:max_days:warn_days:inactive_days:expiry:reserved
Field Reference
| File | Field | Description |
|---|---|---|
/etc/passwd | username | The login name. Must be unique within the system. |
| password placeholder | Always contains x. The actual hash is stored in /etc/shadow. | |
| UID | The user ID. 0 is root; 1000 and above are regular users. | |
| GID | The primary group ID. Linked to the corresponding group in /etc/group. | |
| GECOS | An optional comment field. Used for the full name, phone number, and similar information. Can be left empty. | |
| home directory | The working directory after login. Typically /home/username. | |
| login shell | The full path to the shell to launch. Setting /sbin/nologin denies interactive login. | |
/etc/shadow | username | Same username as in /etc/passwd. The two files are linked by this field. |
| password hash | In $id$salt$hash format. ! or * means password authentication is disabled. | |
| last changed | The date the password was last changed, expressed as days elapsed since 1970-01-01. | |
| minimum age | The minimum number of days that must pass before the password can be changed again. 0 means no restriction. | |
| maximum age | The maximum number of days the password remains valid. 99999 is effectively no expiry. | |
| warning period | The number of days before expiry that the user starts receiving warnings. | |
| inactive period | The number of days after expiry before the account is disabled. Empty means the account is never disabled. | |
| account expiry | The last day the account can be used, expressed as days elapsed. Empty means no expiry. |
Examples
View all entries in /etc/passwd. The file is readable by all users.
cat /etc/passwd root:x:0:0:root:/root:/bin/bash bin:x:1:1:bin:/bin:/sbin/nologin daemon:x:2:2:daemon:/sbin:/sbin/nologin adm:x:3:4:adm:/var/adm:/sbin/nologin nobody:x:65534:65534:Kernel Overflow User:/:/sbin/nologin webmaster:x:1001:1001:Web Master,,,:/home/webmaster:/bin/bash deploy:x:1002:1002:Deploy Account:/home/deploy:/bin/bash
Use grep to extract the line for a specific user.
grep '^webmaster:' /etc/passwd webmaster:x:1001:1001:Web Master,,,:/home/webmaster:/bin/bash
getent passwd retrieves the same information. Unlike reading the file directly, getent also queries external directories such as LDAP.
getent passwd webmaster webmaster:x:1001:1001:Web Master,,,:/home/webmaster:/bin/bash
View the password hash in /etc/shadow. Root privileges are required.
sudo grep '^deploy:' /etc/shadow deploy:$6$rounds=5000$nacl8xkP3zQm1w2r$TvjZklM.../0:19800:0:99999:7:::
The hash uses the $id$salt$hash format. Breaking down the output above:
| Part | Value | Meaning |
|---|---|---|
$6$ | SHA-512 | Hash algorithm identifier. |
rounds=5000$ | 5000 | Number of stretching rounds. More rounds means stronger resistance to brute force. |
nacl8xkP3zQm1w2r | Salt | A random string. Ensures the same password produces different hashes. |
TvjZklM.../0 | Hash | The actual hash value computed from the password. |
Create a user with useradd and verify it was added to /etc/passwd. -m creates the home directory, -c sets the GECOS field, and -s sets the login shell.
sudo useradd -m -c "System Operator" -s /bin/bash sysop
Set a password with the passwd command. It prompts for the password interactively.
sudo passwd sysop Changing password for user sysop. New password: Retype new password: passwd: all authentication tokens updated successfully.
Verify the created entries. The UID and GID values vary depending on the environment.
getent passwd sysop sysop:x:1003:1003:System Operator:/home/sysop:/bin/bash
sudo grep '^sysop:' /etc/shadow sysop:$y$j9T$saltsaltsalt$hashhashhash:19800:0:99999:7:::
List system accounts whose login shell is set to /sbin/nologin. Service accounts such as bin and daemon use this setting to prevent interactive login.
grep '/sbin/nologin$' /etc/passwd bin:x:1:1:bin:/bin:/sbin/nologin daemon:x:2:2:daemon:/sbin:/sbin/nologin adm:x:3:4:adm:/var/adm:/sbin/nologin nobody:x:65534:65534:Kernel Overflow User:/:/sbin/nologin
Use usermod to change an existing user's login shell to /sbin/nologin to disable interactive login.
sudo usermod -s /sbin/nologin appuser
getent passwd appuser appuser:x:1002:1002:Application User:/home/appuser:/sbin/nologin
Use the chage command to view the password policy recorded in /etc/shadow.
sudo chage -l user1 Last password change : Mar 25, 2026 Password expires : never Password inactive : never Account expires : never Minimum number of days between password change : 0 Maximum number of days between password change : 99999 Number of days of warning before password expires : 7
Set the maximum password validity to 90 days and warn 14 days before expiry.
sudo chage -M 90 user1 sudo chage -W 14 user1
Verify the updated policy.
sudo chage -l user1 Last password change : Mar 25, 2026 Password expires : Jun 23, 2026 Password inactive : never Account expires : never Minimum number of days between password change : 0 Maximum number of days between password change : 90 Number of days of warning before password expires : 14
Overview
/etc/passwd and /etc/shadow are the core files for user management on Linux. Historically, /etc/passwd stored password hashes directly, but because this file is world-readable, it posed a brute-force attack risk. Modern Linux systems use the "shadow password" scheme, which moves hashes to /etc/shadow — a file readable only by root. The hashing algorithm can be identified by the $id$ prefix; SHA-512 ($6$) and yescrypt ($y$) are widely used today. When editing these files directly, use vipw / vipw -s, which provide file locking and syntax checking. For creating and modifying users, see useradd / usermod. For group information, see Group management (/etc/group).
If you find any errors or copyright issues, please contact us.