Accounts & PAM policy
Password rules, lockout, and login limits.
Beyond SSH, the account system itself needs hardening, and on Linux that means PAM — the Pluggable Authentication Modules that sit behind login, sudo, SSH, and more. PAM is where you enforce password quality, account lockout after failed attempts, and session limits, in one place that every authentication path consults. Even in a keys-only world these matter for local logins, sudo, and any service that still authenticates users.
minlen = 14 # minimum length — length beats complexitydifok = 5 # must differ from the old password by 5+ charsdcredit = -1 # require at least one digitucredit = -1 # ...one uppercaseenforce_for_root = 1 # root is not exempt
Lockout and login limits
Two PAM controls blunt local brute force and abuse. faillock temporarily locks an account after several failed attempts, so guessing is rate-limited even for local or console logins. And limits (via /etc/security/limits.conf) cap resources per user — a maximum number of processes, for instance — which contains a fork bomb or a runaway account. These are cheap, broadly applicable defenses that apply no matter which service the login came through.
deny = 5 # lock after 5 failed attemptsunlock_time = 900 # for 15 minuteseven_deny_root = 1# check/reset with: faillock --user deploy [--reset]
Password aging and inactive accounts
Set sensible aging so credentials do not live forever, and expire accounts that fall idle. login.defs sets defaults for new users; chage manages an existing account’s aging, and can lock an account that has not been used in N days. The security goal is that stale, forgotten credentials — the ones nobody is watching — do not remain valid indefinitely, because those are exactly what an attacker hopes to find still working months later.
$ sudo chage -l deploy # view aging policy for an account$ sudo chage -M 90 -I 30 deploy # max 90-day password; lock 30 days after expiry$ sudo passwd -l olduser # lock an account (disables password login)