— LiveStream

To set a non-expiring password for an AIX functional ID, set the user's maxage attribute to 0 and disable interactive sign-on while leaving service connectivity intact. This keeps an application's service account (for example, a DB2 datasource ID) from being locked out by a routine password-expiry policy, without weakening overall security.
Functional IDs (also called service accounts or application IDs) are non-human accounts that an application server uses to connect to a backend resource. The credentials are stored once in the application configuration, so end users never type the datasource password and usually never even know the ID exists. The challenge is that standard corporate password policies force every account to rotate its password on a schedule. When a functional ID silently expires at 2 a.m., the application loses its database connection and the outage looks like a mystery. This guide shows the correct, supportable way to make an AIX functional ID's password non-expiring while hardening the account so it cannot be used to log in directly.
The problem: password expiry breaks service accounts
Consider a typical setup. An application such as a marketing or campaign listener has a datasource ID (for example, uniadmn) that it uses to connect to a DB2 database. The user ID and password are preset in the application server. The end user clicks a button in the UI; behind the scenes the application authenticates to DB2 using the functional ID. No human ever interactively logs in as that ID.
Now apply a normal AIX password policy with maxage 13 (13 weeks, the AIX default unit is weeks). After about three months, AIX expires the password. The next time the application tries to authenticate, DB2 rejects the credential, the connection pool drains, and the application throws authentication errors. Because nobody changed anything visibly, the root cause is easy to miss.
The fix is to treat the functional ID differently from a human user: its password should not expire, but the account should be locked down so it can only be used programmatically — never as an interactive login.
Why "just make it non-expiring" is acceptable here
Security teams resist non-expiring passwords for good reason. For an interactive human account, a static password is a standing risk. A functional ID is different: under most modern IS guidelines a service ID may be set as non-expiring without a separate exemption, provided you offset the risk by disabling its direct sign-on. The trade is explicit: you remove forced rotation, but you also remove the account's ability to be logged into by a person. The credential lives only inside the application configuration and is exercised only over the application's own connection.
The solution: zero out maxage and disable login
On AIX the relevant per-user attributes are managed with the chuser command (or the SMIT/SMITTY menu front-end). Three attributes do the work for a non-expiring functional ID:
maxage=0— the maximum age, in weeks, before the password must change. Setting it to0means the password never expires.login=true— allows local authentication so the application/service can still use the credential. Setting this tofalsewould block all authentication, including the application's.rlogin=false— blocks remote interactive login viatelnet,rlogin, andrsh, so the ID cannot be used for an interactive remote session.
To fully prevent a person from "signing on" directly while still letting the application authenticate, you typically pair rlogin=false with su=true restricted to the right group, or set the account's shell to a non-interactive one. The combination below is the supportable, audit-friendly pattern.
Understanding the AIX maxage unit (a common mistake)
A frequent error is assuming maxage is measured in days. On AIX it is measured in weeks. So maxage=8 is eight weeks (about 56 days), not eight days. The special value 0 disables expiry entirely. The companion attributes minage (minimum weeks before a change is allowed) and maxexpired (weeks after expiry that the password can still be changed at login) are also in weeks; maxexpired=-1 means an expired password can be changed indefinitely.
Step-by-step: non-expiring functional ID via SMIT
SMIT (the System Management Interface Tool) gives you a guided, menu-driven path. Use smitty for the fast text interface.
- Log in to the database/application server as
root, or use a privileged account that can runchuser. - Launch the user-management menu directly:
smitty user - From the Users menu you will see options including Add a User, Change a User's Password, Change / Show Characteristics of a User, Lock / Unlock a User's Account, Reset User's Failed Login Count, Remove a User, and List All Users. Move the cursor to Change / Show Characteristics of a User and press
Enter. - Type the functional ID's user name (for example,
uniadmn) and pressEnter. - In the characteristics screen, set these fields:
- User can LOGIN? →
true - User can LOGIN REMOTELY (rsh, tn, rlogin)? →
false - Password MAX. AGE →
0
- User can LOGIN? →
- Press
Enterto apply. SMIT runs the underlyingchusercommand for you and reports OK at the top of the screen. - Press
F10(orEsc+0) to exit SMIT.
Leaving User can LOGIN? set to true is deliberate: AIX uses this same flag to decide whether the credential can authenticate at all. If you set it to false, the application will also fail to authenticate. Direct interactive sign-on is instead blocked by disabling remote login and, where required, by restricting su and the shell.
Step-by-step: the same change from the command line
The command line is faster, scriptable, and exactly what SMIT runs underneath. As root:
- Make the password non-expiring and disable remote interactive login in one call:
chuser maxage=0 rlogin=false login=true uniadmn - Belt-and-suspenders: clear any inherited expiry-related limits so the account cannot be locked by stale policy:
chuser maxage=0 minage=0 maxexpired=-1 uniadmn - Restrict who may
suto the ID so only an authorized admin group can assume it (replacedbadminwith your group):chuser sugroups=dbadmin uniadmn - If a person should never get an interactive shell as this ID, set a non-login shell:
chuser shell=/usr/bin/false uniadmn
Only do this if the application authenticates via PAM/LDAP/loadable auth rather than spawning a login shell — test in a non-production environment first.
If the password was already expired before you started, clear the expired flag so the next authentication succeeds without prompting for a change:
- Reset the change-required flag:
pwdadm -c uniadmn - If needed, set a fresh password non-interactively and then clear the forced-change flag again:
echo "uniadmn:NewStr0ngP@ss" | chpasswd -cthenpwdadm -c uniadmn
The -c flag on pwdadm clears the ADMCHG flag that would otherwise force a password change at the next login — which an application cannot satisfy.
Common pitfalls and how to avoid them
- Thinking maxage is in days. It is in weeks. Use
0for never-expire; do not enter a large number like365expecting one year — that would be 365 weeks. - Setting
login=falseto "lock it down." This blocks the application's own authentication too. Keeplogin=trueand instead disablerloginand restrictsu/shell. - Forgetting the ADMCHG flag. After an admin resets the password, AIX flags it for mandatory change on next login. The application cannot change it interactively, so authentication keeps failing until you run
pwdadm -c. - Account lockout from failed logins. If
loginretriesis set and a misconfigured app hammers the wrong password, the ID gets locked. Check and reset withchuser account_locked=false uniadmnandchsec -f /etc/security/lastlog -s uniadmn -a unsuccessful_login_count=0. - Editing files by hand. Resist hand-editing
/etc/security/user. Usechuser/chsecso AIX keeps the stanza consistent and the change is auditable. - Not documenting the exception. Even when no formal IS exemption is required, record which functional IDs are non-expiring, why, and who owns them. Auditors will ask.
Verification: confirm the functional ID is correct
Never assume a change took effect — verify the attributes and test authentication.
- Confirm the three core attributes in one query:
lsuser -a maxage login rlogin uniadmn
Expected output is along the lines of:uniadmn maxage=0 login=true rlogin=false - Confirm the password is not flagged for forced change and is not expired:
lssec -f /etc/security/passwd -s uniadmn -a flags lastupdate
Theflagsvalue should be empty (noADMCHG). - Show the full account stanza for the record:
lsuser uniadmn - Prove the application can still authenticate — restart the application/datasource connection or run a connection test from the app server, and confirm DB2 (or the relevant backend) accepts the functional ID.
- Prove direct remote sign-on is blocked — attempt
ssh uniadmn@serverortelnetand confirm it is refused, demonstrating the ID cannot be used for interactive remote login.
If lsuser shows maxage=0, the password flags are clean, the application authenticates, and remote login is refused, the functional ID is correctly configured: non-expiring for the application, locked for humans.
Quick reference table
| Goal | Attribute | Command |
| Password never expires | maxage=0 | chuser maxage=0 uniadmn |
| Allow app authentication | login=true | chuser login=true uniadmn |
| Block remote interactive login | rlogin=false | chuser rlogin=false uniadmn |
| Clear forced-change flag | ADMCHG | pwdadm -c uniadmn |
| Unlock account | account_locked=false | chuser account_locked=false uniadmn |
| Verify settings | — | lsuser -a maxage login rlogin uniadmn |
A note on modern equivalents
AIX is fully supported (IBM AIX 7.3 is current), so these commands remain valid. That said, the most secure modern pattern for service accounts is to eliminate the static password entirely where the platform allows it — for example, using key-based or certificate authentication, Kerberos/GSSAPI for DB2, or a centralized secrets manager (such as IBM Security Verify, CyberArk, or HashiCorp Vault) that rotates and injects credentials automatically. When forced rotation and a stored password are unavoidable for a legacy app, the maxage=0 plus disabled-sign-on approach above is the correct, defensible compromise.
Key Takeaways
- Use
maxage=0to make an AIX functional ID's password non-expiring — and remember AIX measuresmaxagein weeks, not days. - Keep
login=true, setrlogin=falseso the application can still authenticate while interactive remote sign-on is blocked. - Run
pwdadm -cafter any admin password reset to clear the ADMCHG flag, or authentication will keep failing. - Verify with
lsuserand a real connection test; never assume the change applied. - Document every non-expiring service account and prefer key/Kerberos/secrets-manager auth when the platform allows it.
Frequently Asked Questions
Is the AIX maxage value in days or weeks?
It is in weeks. maxage=8 means eight weeks (roughly 56 days). The value 0 is special and disables password expiry completely, which is what you want for a functional ID.
Will setting login=false make the account more secure for a service ID?
No — it will break it. AIX uses the login attribute to decide whether the credential may authenticate at all, including for the application. Keep login=true and lock down interactive use with rlogin=false, restricted sugroups, and a non-login shell where appropriate.
How do I check whether an AIX password is set to never expire?
Run lsuser -a maxage <username>. If it returns maxage=0, the password is non-expiring. Pair it with lssec -f /etc/security/passwd -s <username> -a flags to confirm no ADMCHG forced-change flag is set.
Do I need a security exemption to set a non-expiring service password?
Under most current IS guidelines a functional ID can be non-expiring without a separate exemption, on the condition that its direct interactive sign-on is disabled. Always confirm your own organization's policy and document the account regardless.
If this AIX administration walkthrough helped, subscribe to @explorenystream on YouTube for more hands-on UNIX and system-administration guides.