Linux user management is surprisingly fragile, and the biggest misconception is that useradd and passwd are all you need for secure access.
Let’s watch a user get added and then escalate privileges.
First, we create a user, alice.
sudo useradd -m -s /bin/bash alice
sudo passwd alice
alice can now log in with a password. But to do anything useful, she needs to be in groups. Groups are the fundamental access control mechanism in Linux for resources and commands.
sudo usermod -aG sudo,docker alice
Here, we added alice to the sudo group (allowing her to run commands as root) and the docker group (allowing her to manage Docker containers without root). The -aG flags are crucial: -a for append, -G for supplementary groups. Without -a, she’d replace all existing supplementary groups.
Now, alice can run commands as root using sudo.
sudo -i
# Now running as root
But sudo itself is configured by /etc/sudoers. This file dictates who can run what commands on which hosts, and how. It’s not just about being in the sudo group.
To edit sudoers safely, we use visudo. This locks the file and performs syntax checks.
sudo visudo
A common entry looks like this:
%sudo ALL=(ALL:ALL) ALL
This means members of the sudo group (%sudo) can run any command (ALL) on any host (ALL), as any user ((ALL:ALL) - the first ALL is the effective user, the second is the effective group).
Let’s say we want alice to only be able to restart the web server. We’d add a line like this:
alice ALL=/usr/sbin/service apache2 restart, /usr/sbin/service nginx restart
This is far more granular and secure than just dumping her into the sudo group.
This brings us to PAM (Pluggable Authentication Modules). PAM is the magic behind the scenes that handles authentication, authorization, account management, and session management. When you run login, sudo, sshd, or even passwd, PAM is involved.
The configuration for PAM is in /etc/pam.d/. For example, /etc/pam.d/sudo dictates how sudo authenticates users.
#%PAM-1.0
session required pam_env.so readenv=1 user_readenv=0
session required pam_env.so readenv=1 user_readenv=1
auth required pam_env.so
auth sufficient pam_rootok.so
auth required pam_group.so use_uid
auth required pam_unix.so try_first_pass
auth optional pam_sss.so
account required pam_unix.so
account required pam_group.so use_uid
account optional pam_sss.so
password required pam_unix.so minlen=4 maxrepeat=999 default=password
password optional pam_gnome_keyring.so
session required pam_unix.so
session optional pam_keyinit.so forceok
session optional pam_loginuid.so
session optional pam_keyinit.so revoke
session required pam_limits.so
session required pam_env.so user_readenv=1
session required pam_env.so readenv=1 user_readenv=0
session optional pam_sss.so -i
This file defines a chain of modules for each type of service (auth, account, password, session). The keywords required, sufficient, optional, and requisite determine how the chain proceeds. sufficient means if this module succeeds, the stack for this service is considered successful, and no more modules of that type are run. required means it must succeed for the service to succeed, but the stack continues even if it fails (the overall service will fail later if any required module fails).
A common security pitfall is misconfiguring PAM, for instance, by making password changes too lax. A line like password requisite pam_cracklib.so retry=3 minlen=8 dcredit=-1 ucredit=-1 ocredit=-1 lcredit=-1 would enforce stronger passwords than the default pam_unix.so might.
The most surprising thing most people don’t realize is how PAM’s sufficient keyword can short-circuit authentication. If a module marked sufficient succeeds, the rest of the modules for that type (e.g., auth) are skipped entirely. This is why the order of modules in PAM configuration files is critically important. A poorly placed sufficient module, like pam_permit.so (which always succeeds), can effectively disable authentication for that service.
The next problem you’ll likely encounter is managing user home directories and their permissions across different systems or when moving users.