User and Group Management
Users and Groups Overview
Every process runs as a user (UID). Users belong to one primary group (GID) and optional supplementary groups. Linux stores account data in plain-text databases protected by permissions:
| File | Purpose | Permissions |
|---|---|---|
/etc/passwd |
Account names, UIDs, homes, shells | world-readable |
/etc/shadow |
Hashed passwords, expiry | root-only |
/etc/group |
Group definitions and members | world-readable |
/etc/gshadow |
Group passwords (rare) | root-only |
id alice
id # current user
groups bob
getent passwd alice
getent group sudo
awk -F: '$3 == 0 { print }' /etc/passwd # UID 0 accounts
UID 0 is always root. System accounts typically use UIDs below 1000 (Debian) or below 500 (RHEL).
Creating Users
Debian/Ubuntu
sudo adduser alice # interactive; creates home, sets password
sudo adduser --disabled-password --gecos "" deploy # automation user
sudo usermod -aG sudo alice # grant sudo (Ubuntu)
sudo usermod -aG docker alice # supplementary group
sudo chage -d 0 alice # force password change on next login
RHEL/Fedora
sudo useradd -m -s /bin/bash alice
sudo passwd alice
sudo usermod -aG wheel alice # sudo group on RHEL family
sudo useradd -r -s /sbin/nologin nginx # system account
Remove users:
sudo deluser alice # Debian; keep home
sudo deluser --remove-home alice
sudo userdel -r alice # RHEL; -r removes home
Groups
sudo groupadd developers
sudo groupadd -g 1500 appgroup # explicit GID for NFS consistency
sudo usermod -aG developers alice
sudo gpasswd -d alice developers # remove from group
sudo groupdel developers # only if empty
getent group developers
Primary group is set at user creation; supplementary groups control access to shared resources (docker, www-data, disk groups).
sudo Configuration
Edit /etc/sudoers only with visudo — syntax errors lock out all sudo access.
sudo visudo
sudo visudo -f /etc/sudoers.d/deploy # drop-in file (preferred)
Examples:
# Full sudo for alice
alice ALL=(ALL:ALL) ALL
# Passwordless restart only
deploy ALL=(ALL) NOPASSWD: /bin/systemctl restart myapp
# Run as specific user
backup ALL=(postgres) NOPASSWD: /usr/bin/pg_dump *
Test before closing session:
sudo -l -U alice
sudo -u postgres whoami
Password and Account Policies
sudo passwd alice # set password
sudo passwd -l alice # lock account (prefix ! on hash)
sudo passwd -u alice # unlock
sudo chage -l alice # view expiry policy
sudo chage -M 90 -W 14 alice # max 90 days, warn 14 days before
sudo chage -E 2026-12-31 alice # account expires on date
Configure defaults in /etc/login.defs (PASS_MAX_DAYS, PASS_MIN_DAYS, UMASK).
Service Accounts
Applications run as dedicated users to limit blast radius:
sudo useradd -r -s /usr/sbin/nologin -d /opt/myapp myapp
sudo chown -R myapp:myapp /opt/myapp
sudo chmod 750 /opt/myapp
Use -r for system UID, /usr/sbin/nologin to block interactive login, and no password (locked account).
PAM and Authentication
Pluggable Authentication Modules control login behavior via /etc/pam.d/:
ls /etc/pam.d/
cat /etc/pam.d/common-auth # Debian
cat /etc/pam.d/system-auth # RHEL
LDAP/SSO integration, MFA, and password quality checks (pam_pwquality) hook in here — avoid editing PAM unless you understand lockout risk.
Best Practices
| Practice | Reason |
|---|---|
| One human user per person | Audit trails and accountability |
| Least privilege via groups and sudo | Avoid shared passwords |
| Disable unused accounts promptly | Offboarded employees retain access otherwise |
Use /etc/sudoers.d/ drop-ins |
Easier to manage than monolithic sudoers |
Never edit /etc/shadow by hand |
Use passwd, useradd, usermod |
Common Mistakes
| Mistake | Consequence |
|---|---|
Shared deploy SSH key across team |
Cannot revoke one person |
Adding users to docker group |
Equivalent to root (socket access) |
usermod -G instead of -aG |
Removes all other supplementary groups |
| Broken sudoers syntax | Total sudo lockout; requires recovery console |
# WRONG — replaces groups
sudo usermod -G docker alice
# CORRECT — append group
sudo usermod -aG docker alice
Troubleshooting
User cannot sudo: Check group membership (groups user), sudoers entry, and /var/log/auth.log for “not in sudoers”.
Account locked after failed logins: Check faillock --user alice (RHEL) or PAM pam_tally2 settings.
Home directory missing: sudo mkhomedir_helper alice or recreate with useradd -m.
Production Scenario
A SaaS platform provisions per-tenant Linux users on shared app servers:
- Terraform creates
tenant_1234system user with/usr/sbin/nologin - Ansible sets ACLs so tenant can only write
/data/tenant_1234 - sudoers.d allows ops team passwordless
systemctl restart tenant-1234.service - Offboarding runs
userdel -r tenant_1234and removes sudoers drop-in
Quarterly audit: awk -F: '$3 == 0 || $3 >= 1000 { print }' /etc/passwd cross-checked against HR roster.
Proper user hygiene is the foundation of multi-tenant servers, compliance audits, and incident response — know who can become root and how.