When managing Linux systems, we occasionally encounter situations where users need to operate without passwords (perhaps for automation purposes). The classic passwd -d username
command seems like a straightforward solution, but it introduces subtle authentication challenges.
Even with a deleted password, Linux maintains PAM (Pluggable Authentication Modules) security tokens. These tokens get invalidated according to the system's password aging policy, typically every 30 days. The system doesn't distinguish between passwordless users and regular users in this regard.
# Typical error seen in cron logs
Authentication token is no longer valid; new one required
ERROR: failed to open PAM security session: Success
ERROR: cannot set security context
Here are several approaches to resolve this issue, ranked from simplest to most complex:
1. Disable Password Aging for the User
sudo chage -I -1 -m 0 -M 99999 -E -1 username
This prevents the authentication token from expiring by:
-I -1
: Sets password inactivity to never-m 0
: Minimum days between changes to 0-M 99999
: Maximum password age to ~273 years-E -1
: Account expiration to never
2. Configure PAM to Ignore Token Expiration
Edit /etc/pam.d/cron
and modify the auth line:
# Change from:
auth required pam_unix.so
# To:
auth sufficient pam_unix.so likeauth nullok
The nullok
option allows empty passwords, while sufficient
makes authentication optional.
3. Use Systemd Timers Instead of Cron
Create a systemd service and timer that doesn't enforce PAM authentication:
# /etc/systemd/system/mycronjob.service
[Unit]
Description=My Cron Job
[Service]
Type=simple
User=username
ExecStart=/path/to/script.sh
# /etc/systemd/system/mycronjob.timer
[Unit]
Description=Run my job daily
[Timer]
OnCalendar=daily
Persistent=true
[Install]
WantedBy=timers.target
The underlying issue stems from Linux's security model. Even without a password, the system maintains a shadow database entry for the user. The PAM stack still validates authentication tokens against this entry, following the system's password policy.
When examining /etc/shadow
, you'll notice passwordless users still have an entry:
username::18659:0:99999:7:::
The empty field between colons indicates no password, but the remaining fields still control password aging policies.
For long-running automation tasks, consider creating a proper service account with restricted permissions instead of modifying existing user accounts:
sudo useradd -r -s /usr/sbin/nologin svc_automation
sudo passwd -d svc_automation
sudo chage -m 0 -M 99999 -I -1 -E -1 svc_automation
The -r
flag creates a system account with more lenient default security policies.
When you delete a user's password using passwd -d
in Linux, you might encounter an unexpected behavior with cron jobs. The system still enforces password expiration policies, causing authentication failures every 30 days (default PAM policy) with errors like:
Authentication token is no longer valid; new one required
ERROR: failed to open PAM security session: Success
ERROR: cannot set security context
Even without a password, Linux maintains authentication tokens through PAM (Pluggable Authentication Modules). The system still tracks "password aging" for account security, regardless of whether a password exists.
Here are three approaches to resolve this:
1. Disable Password Aging
Use chage
to modify password expiration settings:
sudo chage -I -1 -m 0 -M 99999 -E -1 username
This command:
-I -1
: Sets password inactivity to never-m 0
: Minimum days between changes to 0-M 99999
: Maximum days before change to ~273 years-E -1
: Account expiration to never
2. Modify PAM Configuration
Edit /etc/pam.d/crond
(RHEL/CentOS) or /etc/pam.d/cron
(Debian/Ubuntu):
# Replace this line:
auth required pam_unix.so
# With:
auth sufficient pam_unix.so likeauth nullok
3. System Account Conversion
For service accounts, consider making it a true system account:
sudo usermod -r username
Create a verification script to check token status:
#!/bin/bash
USER="your_username"
if sudo -U $USER true 2>&1 | grep -q "Authentication token"; then
echo "Token expired - running chage"
sudo chage -I -1 $USER
fi
For more secure automation, consider switching to SSH key-based authentication:
# Generate key pair
ssh-keygen -t ed25519 -f ~/.ssh/cron_key -N ""
# Add to authorized_keys
cat ~/.ssh/cron_key.pub >> ~/.ssh/authorized_keys
# Use in cron with:
* * * * * ssh -i ~/.ssh/cron_key localhost "your_command"
Remember that removing password aging reduces security auditing capabilities. Always document these changes in your system configuration logs.