Zimbra Collaboration Suite stores mailbox credentials in its internal LDAP directory. A weak password policy means accounts with short or simple passwords become easy targets for brute-force attacks and credential stuffing. Once an attacker owns a mailbox, they use it to relay spam, exfiltrate data, or pivot deeper into the network. Locking down the password policy is one of the first hardening steps on any production Zimbra deployment.
This guide walks through every password-related attribute in Zimbra – minimum length, complexity rules, expiry, history, account lockout, per-COS overrides, forced resets, and auditing. All commands run as the zimbra user on the CLI using zmprov. The same settings are available in the Zimbra Administration Console under Class of Service, but CLI is faster and scriptable.
Prerequisites
- A running Zimbra Collaboration Suite server (version 8.8.15 or 10.x)
- Root or sudo access to the Zimbra server
- SSH access to the server CLI
- Basic familiarity with
zmprov– the Zimbra provisioning command-line tool
All commands below should be run as the zimbra user. Switch to it first:
sudo su - zimbra
Step 1: Check the Current Password Policy
Before changing anything, dump the current password settings from the default Class of Service. This shows what Zimbra enforces out of the box.
zmprov gc default | grep -i password
The output lists every password-related attribute and its current value:
zimbraFeatureChangePasswordEnabled: TRUE
zimbraPasswordEnforceHistory: 0
zimbraPasswordLocked: FALSE
zimbraPasswordLockoutDuration: 1h
zimbraPasswordLockoutEnabled: FALSE
zimbraPasswordLockoutFailureLifetime: 1h
zimbraPasswordLockoutMaxFailures: 10
zimbraPasswordMaxAge: 0
zimbraPasswordMaxLength: 64
zimbraPasswordMinAge: 0
zimbraPasswordMinAlphaChars: 0
zimbraPasswordMinDigitsOrPuncs: 0
zimbraPasswordMinLength: 6
zimbraPasswordMinLowerCaseChars: 0
zimbraPasswordMinNumericChars: 0
zimbraPasswordMinPunctuationChars: 0
zimbraPasswordMinUpperCaseChars: 0
The defaults are weak – a 6-character password with no complexity requirements, no expiry, no lockout, and no history enforcement. Every one of these needs tightening on a production mail server.
Step 2: Set Minimum Password Length
Short passwords are the easiest to crack. Set the minimum length to at least 10 characters. This single change blocks most dictionary attacks.
zmprov mc default zimbraPasswordMinLength 10
Verify the change took effect:
zmprov gc default zimbraPasswordMinLength
The output confirms the new minimum length:
zimbraPasswordMinLength: 10
Users with existing passwords shorter than 10 characters will not be locked out, but they will be required to meet the new minimum when they change their password next time.
Step 3: Require Password Complexity
Length alone is not enough. Force passwords to include a mix of character types – uppercase, lowercase, numbers, and special characters. This prevents users from setting aaaaaaaaaa as a valid 10-character password.
zmprov mc default zimbraPasswordMinUpperCaseChars 1
zmprov mc default zimbraPasswordMinLowerCaseChars 1
zmprov mc default zimbraPasswordMinNumericChars 1
zmprov mc default zimbraPasswordMinPunctuationChars 1
You can also enforce a combined minimum of digits and punctuation characters with a single attribute:
zmprov mc default zimbraPasswordMinDigitsOrPuncs 2
Confirm all complexity settings are applied:
zmprov gc default | grep -i "zimbraPasswordMin"
The output should show all the updated values:
zimbraPasswordMinAge: 0
zimbraPasswordMinAlphaChars: 0
zimbraPasswordMinDigitsOrPuncs: 2
zimbraPasswordMinLength: 10
zimbraPasswordMinLowerCaseChars: 1
zimbraPasswordMinNumericChars: 1
zimbraPasswordMinPunctuationChars: 1
zimbraPasswordMinUpperCaseChars: 1
With these settings, a valid password must be at least 10 characters long and contain at least one uppercase letter, one lowercase letter, one number, and one special character.
Step 4: Set Password Expiry with zimbraPasswordMaxAge
Password expiry forces users to rotate their credentials regularly. The zimbraPasswordMaxAge attribute sets the maximum number of days a password remains valid. A value of 0 means passwords never expire, which is the default.
Set passwords to expire every 90 days:
zmprov mc default zimbraPasswordMaxAge 90
You can also set a minimum age to prevent users from quickly cycling through passwords to reuse an old one:
zmprov mc default zimbraPasswordMinAge 1
This requires at least 1 day between password changes. Combined with password history (next step), it effectively blocks users from resetting back to a previous password within the same session.
Step 5: Enforce Password History
Password history prevents users from reusing recent passwords. When users rotate a password, they often just toggle between two favorites. The zimbraPasswordEnforceHistory attribute stores the number of previous passwords to remember.
Set history to remember the last 10 passwords:
zmprov mc default zimbraPasswordEnforceHistory 10
Verify the setting:
zmprov gc default zimbraPasswordEnforceHistory
Expected output showing history is enabled:
zimbraPasswordEnforceHistory: 10
Now if a user tries to set a password they have used within the last 10 changes, Zimbra will reject it.
Step 6: Configure Account Lockout Policy
Account lockout protects against brute-force login attempts. By default, Zimbra has lockout disabled. You need to enable it and set thresholds for failed attempts, lockout duration, and the failure counting window.
Enable lockout and set it to lock accounts after 5 failed attempts:
zmprov mc default zimbraPasswordLockoutEnabled TRUE
zmprov mc default zimbraPasswordLockoutMaxFailures 5
zmprov mc default zimbraPasswordLockoutDuration 30m
zmprov mc default zimbraPasswordLockoutFailureLifetime 1h
Here is what each attribute does:
- zimbraPasswordLockoutEnabled – activates the lockout mechanism
- zimbraPasswordLockoutMaxFailures – number of failed attempts before lockout (set to 5)
- zimbraPasswordLockoutDuration – how long the account stays locked (30 minutes). Set to
0to lock permanently until an admin unlocks it - zimbraPasswordLockoutFailureLifetime – the time window for counting failures. If a user fails 3 times, waits 2 hours (beyond the 1h window), and fails again, the counter resets
Verify the lockout configuration:
zmprov gc default | grep -i "zimbraPasswordLockout"
All lockout attributes should reflect the new values:
zimbraPasswordLockoutDuration: 30m
zimbraPasswordLockoutEnabled: TRUE
zimbraPasswordLockoutFailureLifetime: 1h
zimbraPasswordLockoutMaxFailures: 5
If an account gets locked out, an administrator can manually unlock it from the CLI. To check if a specific account is currently locked:
zmprov ga [email protected] zimbraAccountStatus zimbraPasswordLockoutLockedTime
To unlock a locked account:
zmprov ma [email protected] zimbraAccountStatus active zimbraPasswordLockoutLockedTime ""
Step 7: Set Per-COS Password Policies
Zimbra uses Class of Service (COS) to group accounts with shared settings. The default COS applies to all accounts unless overridden. In production, you might need different password policies for different groups – stricter rules for administrators, relaxed rules for service accounts or distribution list owners.
First, list all Classes of Service on the server:
zmprov gac
Typical output shows the available COS names:
default
defaultExternal
Create a new COS for administrators with stricter password requirements:
zmprov cc admin_cos zimbraPasswordMinLength 14 zimbraPasswordMinUpperCaseChars 2 zimbraPasswordMinNumericChars 2 zimbraPasswordMinPunctuationChars 2 zimbraPasswordMaxAge 60 zimbraPasswordEnforceHistory 15 zimbraPasswordLockoutEnabled TRUE zimbraPasswordLockoutMaxFailures 3
Assign an account to this stricter COS:
zmprov ma [email protected] zimbraCOSId $(zmprov gc admin_cos zimbraId | awk '{print $2}')
Verify the account is now using the new COS:
zmprov ga [email protected] zimbraCOSId
To modify the defaultExternal COS for external or partner accounts with a different policy:
zmprov mc defaultExternal zimbraPasswordMinLength 12 zimbraPasswordMaxAge 60 zimbraPasswordLockoutEnabled TRUE zimbraPasswordLockoutMaxFailures 5
Step 8: Force Password Change at Next Login
When onboarding new users or after a security incident, you may need to force specific accounts to change their password on next login. Zimbra provides the zimbraPasswordMustChange attribute for this.
Force a single user to change their password at next login:
zmprov ma [email protected] zimbraPasswordMustChange TRUE
To force all accounts in a domain to reset their passwords, loop through the account list:
for user in $(zmprov -l gaa example.com); do
zmprov ma "$user" zimbraPasswordMustChange TRUE
done
Verify the flag is set on a specific account:
zmprov ga [email protected] zimbraPasswordMustChange
The output shows the current state of the attribute:
zimbraPasswordMustChange: TRUE
Once the user logs in and changes their password, Zimbra automatically sets this attribute back to FALSE.
Step 9: Audit Weak Passwords on Zimbra
After tightening the policy, existing accounts still have their old weak passwords until they rotate. You cannot decrypt stored passwords (they are hashed), but you can identify accounts that have not changed their password since the policy update.
Check the last password change date for all accounts in a domain:
for user in $(zmprov -l gaa example.com); do
echo -n "$user: "
zmprov ga "$user" zimbraPasswordModifiedTime | grep zimbraPasswordModifiedTime
done
The output shows each account and when their password was last changed:
[email protected]: zimbraPasswordModifiedTime: 20260115103022Z
[email protected]: zimbraPasswordModifiedTime: 20250801142315Z
[email protected]: zimbraPasswordModifiedTime: 20240312091205Z
Accounts with old zimbraPasswordModifiedTime values have not rotated their password under the new policy. You can force those accounts to change their password using the method from Step 8.
To list accounts where the password is currently locked (due to too many failed attempts):
for user in $(zmprov -l gaa example.com); do
locktime=$(zmprov ga "$user" zimbraPasswordLockoutLockedTime | grep zimbraPasswordLockoutLockedTime | awk '{print $2}')
if [ -n "$locktime" ]; then
echo "LOCKED: $user (since $locktime)"
fi
done
This helps you spot accounts that are under active brute-force attack or users who have simply forgotten their credentials.
Zimbra Password Attributes Reference
The table below lists all password-related attributes in Zimbra, their purpose, and recommended production values.
| Attribute | Description | Recommended Value |
|---|---|---|
zimbraPasswordMinLength | Minimum number of characters required | 10 |
zimbraPasswordMaxLength | Maximum password length allowed | 64 (default) |
zimbraPasswordMinUpperCaseChars | Minimum uppercase letters required | 1 |
zimbraPasswordMinLowerCaseChars | Minimum lowercase letters required | 1 |
zimbraPasswordMinNumericChars | Minimum numeric digits required | 1 |
zimbraPasswordMinPunctuationChars | Minimum special characters required | 1 |
zimbraPasswordMinDigitsOrPuncs | Combined minimum of digits and special characters | 2 |
zimbraPasswordMinAlphaChars | Minimum alphabetic characters required | 0 (default) |
zimbraPasswordMaxAge | Days before password expires (0 = never) | 90 |
zimbraPasswordMinAge | Minimum days before password can be changed again | 1 |
zimbraPasswordEnforceHistory | Number of previous passwords remembered | 10 |
zimbraPasswordLockoutEnabled | Enable account lockout on failed attempts | TRUE |
zimbraPasswordLockoutMaxFailures | Failed attempts before lockout | 5 |
zimbraPasswordLockoutDuration | How long the account stays locked | 30m |
zimbraPasswordLockoutFailureLifetime | Time window for counting failed attempts | 1h |
zimbraPasswordLocked | Prevents user from changing their own password | FALSE (default) |
zimbraPasswordMustChange | Force password change at next login | Per-account basis |
zimbraFeatureChangePasswordEnabled | Allow users to change their own password | TRUE (default) |
Conclusion
You have configured a complete password policy on Zimbra covering minimum length, complexity requirements, expiry, history, account lockout, per-COS overrides, forced resets, and auditing. These settings apply to all new password changes – existing weak passwords remain until users rotate them, so consider forcing a domain-wide reset after deploying the policy.
For additional hardening, enable TLS certificates on your Zimbra server, configure proper firewall rules for Zimbra services, and set up Amavis spam filtering whitelist and blacklist rules to protect your mail infrastructure from both external threats and compromised accounts.