Start a conversation

Kerio Connect License Limit Reached Although Fewer Users Are Visible: Enabled Accounts Left Over from a Former Domain

Overview

This article explains why Kerio Connect can report that your license is full even though the Accounts > Users list shows fewer accounts than your license allows, and how to find and disable the enabled accounts that are consuming the missing seats without being visible in the administration interface.

You are in this situation if you see a combination of the following:

  • On Status > Dashboard, the License Details tile shows a created figure that is higher than the number of accounts you can see. For example: Number of users allowed by the license: 15 and Number of active mailboxes: 11 (16 created), while Accounts > Users lists only 13 accounts.
  • The Domain drop-down at the top of Accounts > Users offers only one domain, no search filter is active, and Configuration > Domains shows a single domain – possibly with one or more names in its Aliases column.
  • When you log in to the administration interface, this warning appears:
    Total number of user mailboxes (local and mapped from the directory service) authorized by the license has been exceeded. Please buy an add-on license for other users, or delete some mailboxes.
    Otherwise the access for users exceeding the permitted limit will be denied.
  • At the bottom of Accounts > Users, the status text reads You cannot add more users. and the Details… link opens a dialog whose Current number of users value is lower than your license, yet Number of users remaining in license is 0.
  • Creating a new account, or activating a new account from the directory service, is blocked by the license limit.

What is actually happening. Kerio Connect counts every enabled account record on the server against the license, regardless of which domain the record belongs to and regardless of whether that domain still exists in Configuration > Domains. The Accounts > Users list, on the other hand, only ever shows the accounts of the domain currently selected in its Domain drop-down – and that drop-down only offers domains that are currently configured. If a past domain rename or migration left local account records that still carry the old domain name, and that old name now survives only as a domain alias (or not at all), those records are invisible in the administration interface but are still enabled and still occupy one license seat each.

This is not a product defect. The license counter is correct; it is counting accounts you cannot see. The fix is to locate those records in the users.cfg configuration file and disable them (disabled accounts do not count against the license). This applies to Kerio Connect on Windows, macOS, and Linux, with or without a directory service (Active Directory / Open Directory) connection.

For general background on what does and does not consume a license seat, see Licenses in Kerio Connect.

Prerequisites

  • An administrator account with full server administration rights in the Kerio Connect administration interface (Status > Dashboard, Accounts > Users, Configuration > Domains).
  • Administrative access to the operating system of the Kerio Connect server: a local Administrator on Windows, or root (or sudo) on macOS and Linux. Editing the configuration file requires these rights; on macOS and Linux the file can only be maintained as root.
  • A maintenance window. Disabling the hidden accounts requires stopping and restarting the Kerio Connect service, during which all users are disconnected from mail, calendars, and mobile sync.
  • A current backup. Either a Kerio Connect backup that includes the configuration files, or at minimum a manual copy of users.cfg taken while the service is stopped. See Backups and Data Recovery for what the built-in backup contains and which files hold the configuration.

Solution

How Kerio Connect counts users against the license (and why the Users list disagrees)

Kerio Connect answers a different question in each of the places where you see a user count. Understanding which question each place answers makes the rest of the procedure obvious:

Where you look What Kerio Connect counts Scope
Status > Dashboard > License Details – the created number in Number of active mailboxes: X (Y created) Every account record whose Account is enabled setting is on: locally created accounts and accounts mapped from a directory service The whole server – all domains, including records whose domain name is no longer a configured domain
Accounts > Users – the rows in the list, the Export CSV, and Current number of users in the Details… dialog Enabled accounts whose domain is exactly the domain selected in the Domain drop-down One configured domain at a time
Accounts > UsersNumber of users remaining in license in the Details… dialog, and the You cannot add more users. status text License limit minus the server-wide enabled-account total (the same total as the Dashboard) The whole server

Two consequences follow directly from this:

  1. If the server has more than one configured domain, the Users list understates the license usage unless you add up every domain in the drop-down. This is the simple, documented case.
  2. If an account record's domain name is not a currently configured domain – for example, because the domain was renamed and the old name now only exists as an alias – there is no entry in the Domain drop-down that will ever show that record. The record still exists, is still enabled, and is still counted. This is the case this article solves.

Domain aliases are only alternative names for a domain used in email addresses; they are not domains of their own, so they are never offered in the Domain drop-down. See Creating Aliases in Kerio Connect.

What does not consume a license seat: disabled accounts, mailing lists, resources, aliases, domains, and the internal built-in administrator account. Note that the separate active figure on the Dashboard (users who have signed in since the last server restart) is unrelated to licensing – see The Difference between Active and Created Mailboxes.

Step 1 – Confirm the discrepancy and rule out the expected explanations

  1. Go to Status > Dashboard and write down the created figure from Number of active mailboxes: X (Y created) in the License Details tile. In the running example this is 16.
  2. Go to Accounts > Users. Open the Domain drop-down at the top of the list and note every domain offered. For each domain: select it, make sure the search box is empty, and click Export.
    The file users_<DomainName>_<date>.csv contains one row per account; count the rows whose Enable column is Yes (disabled accounts appear in the list and in the export but do not count).
    The DataSource column tells you which rows are local accounts (Internal) and which are mapped from a directory service (LDAP) – you will need this split in Step 2. See Exporting Users Lists.
  3. Add up the enabled accounts across all domains from the drop-down. If the total equals the Dashboard's created figure, you simply have accounts spread over several domains (including the case where your former domain still exists as a domain of its own); disable or remove unused accounts through the interface as described in Disabling and Deleting User Accounts in Kerio Connect and stop here. If the total is lower than the created figure (13 versus 16 in the example), continue.
  4. Go to Configuration > Domains and note the domain names in the Name column and every name in the Aliases column. A former domain name appearing in Aliases is the typical signature of the situation described in this article, but the procedure below works even if the old name appears nowhere.
  5. Rule out a per-domain limit: double-click your domain in Configuration > Domains, and on the General tab check the User count section. If Limit maximum number of users in the domain is enabled, that limit can block account creation independently of the license. Clear it or raise it if it is not intentional.

Step 2 – Find the hidden account records in users.cfg

Locally created accounts are stored as records in the file users.cfg in the Kerio Connect installation directory. Accounts mapped from a directory service are read live from the directory and do not appear as records in this file. Every local account is one <listitem> block inside <list name="User">, and each block carries at least the login name, the domain, and the enabled flag:

<listitem>
    <variable name="Name">service</variable>
    <variable name="Domain">old-example.com</variable>
    <variable name="Account_enabled">1</variable>
    <variable name="Auth_type">0</variable>
    <variable name="Password">DES:...</variable>
    ...
</listitem>

The default location of the file is:

Operating system Default path
Windows C:\Program Files\Kerio\MailServer\users.cfg
macOS /usr/local/kerio/mailserver/users.cfg
Linux /opt/kerio/mailserver/users.cfg

⚠️ Warning: users.cfg contains password hashes and other sensitive account data. Do not email it, attach it to support requests, or copy it to shared locations. Read it in place, or produce a sanitized inventory as shown below.

Reading the file is safe while the service is running; you will only stop the service later, when you actually change it. Use whichever method suits your platform.

Method A – Windows, PowerShell inventory (recommended on Windows). The following read-only script parses users.cfg and writes a CSV to your Desktop containing only the login name, domain, enabled flag, authentication type, and GUID of every local account record. It does not modify Kerio Connect, and the CSV contains no passwords. Open an elevated Windows PowerShell window (right-click Windows PowerShell > Run as administrator) on the Kerio Connect server and run:

$cfgPath = Join-Path $env:ProgramFiles 'Kerio\MailServer\users.cfg'
$outPath = Join-Path $env:USERPROFILE 'Desktop\kerio-userscfg-inventory.csv'

if (-not (Test-Path -LiteralPath $cfgPath)) {
    throw "Kerio user configuration file was not found: $cfgPath"
}

[xml]$xml = Get-Content -LiteralPath $cfgPath -Raw
$userLists = @($xml.config.list | Where-Object { $_.name -eq 'User' })

$rows = foreach ($list in $userLists) {
    foreach ($item in @($list.listitem)) {
        $values = @{}
        foreach ($entry in @($item.variable)) {
            $values[$entry.name] = $entry.InnerText
        }
        [pscustomobject]@{
            Name               = $values['Name']
            Domain             = $values['Domain']
            AccountEnabled     = $values['Account_enabled']
            AuthenticationType = $values['Auth_type']
            Guid               = $values['Guid']
        }
    }
}

$rows |
    Sort-Object Domain, Name |
    Export-Csv -LiteralPath $outPath -NoTypeInformation -Encoding UTF8

Write-Host "Created: $outPath"

If Kerio Connect is installed somewhere other than C:\Program Files\Kerio\MailServer, change the first line accordingly. The resulting kerio-userscfg-inventory.csv looks like this (the AuthenticationType and Guid columns are informational only; 0 means the account's password is stored in Kerio Connect itself):

"Name","Domain","AccountEnabled","AuthenticationType","Guid"
"helpdesk","example.com","1","0","1A2B3C4D-0000-4000-8000-000000000001"
"archive","old-example.com","1","0","1A2B3C4D-0000-4000-8000-000000000002"
"scanner","old-example.com","1","0","1A2B3C4D-0000-4000-8000-000000000003"
"service","old-example.com","1","0","1A2B3C4D-0000-4000-8000-000000000004"

Method B – macOS or Linux, command line. As root (or with sudo), print only the three variables that matter for each record (adjust the path for macOS):

grep -n -E '<variable name="(Name|Domain|Account_enabled)">' /opt/kerio/mailserver/users.cfg

The output groups the three lines of each record together, so records are easy to read off:

5:    <variable name="Name">helpdesk</variable>
6:    <variable name="Domain">example.com</variable>
7:    <variable name="Account_enabled">1</variable>
13:    <variable name="Name">service</variable>
14:    <variable name="Domain">old-example.com</variable>
15:    <variable name="Account_enabled">1</variable>

Method C – any platform, text editor. Open users.cfg read-only in a text editor and search for <variable name="Domain">. Each hit belongs to one account record; the Name line immediately above it and the Account_enabled line immediately below it complete the picture.

Interpreting the inventory. Compare every record's Domain value with the Name column of Configuration > Domains:

  • Records whose Domain matches a configured domain are the local accounts you already saw in Accounts > Users for that domain (helpdesk@example.com in the example; these are the DataSource=Internal rows of your export).
  • Records whose Domain is not a configured domain – typically a name that now appears only in the Aliases column, such as old-example.com – are the hidden accounts. Every one of them with Account_enabled = 1 is consuming a license seat.

The numbers should now reconcile exactly: enabled DataSource=LDAP rows from your exports + enabled users.cfg records (all domains, hidden or not) = the Dashboard created figure. In the example: 12 enabled directory-mapped accounts + 1 enabled local account in example.com + 3 enabled local records in old-example.com = 16 created, while Accounts > Users shows 12 + 1 = 13. If your numbers do not reconcile after this step, the remaining difference has another cause and this article does not apply to it.

Step 3 – Decide what to do with each hidden account

Before changing anything, decide for each hidden record whether the account is genuinely no longer needed. These records are usually old service, scanner, archive, or test accounts from the former setup. Confirm with whoever ran the former setup that no device or application (multifunction printers, backup or monitoring jobs, ticketing systems) still signs in as <name>@<old-domain>. Because disabling is reversible, the cost of being wrong is low: the account can be re-enabled with the same procedure.

Disabling is the right first action because it is fully reversible and immediately releases the seat: a disabled account cannot sign in and any forwarding configured on it stops working, but its mailbox contents and settings are preserved and come back the moment the account is re-enabled. If a hidden account turns out to be needed after all, set its Account_enabled value back to 1 using the same procedure as below.

Note: Deleting the raw <listitem> blocks from users.cfg is not a documented procedure and is not needed to free the license seats. This article only covers disabling the records.

Step 4 – Disable the hidden accounts

Because the accounts cannot be reached through the administration interface, you disable them by changing their Account_enabled value directly in users.cfg – the same edit the Account is enabled checkbox performs for visible accounts. Kerio Connect reads this file when it starts and writes its configuration back to it while it runs, so the service must be fully stopped before you edit the file; otherwise your change is ignored or overwritten. Perform these steps during your maintenance window.

  1. Stop the Kerio Connect service and make sure it has fully stopped (on Windows the tray icon shows a red X and the tooltip Kerio Connect is stopped; on Linux with systemd, systemctl status kerio-connect.service reports it inactive):
  2. Back up the file. Copy users.cfg to a safe location outside the installation directory (for example users.cfg.before-cleanup). Keep this copy until you have verified the result.
  3. Open users.cfg in a text editor with administrative rights: Notepad run as administrator on Windows; nano or vim as root on macOS and Linux. Do not use a word processor, which may change the file's encoding or quoting.
  4. Locate each hidden record. Search for the login name from your inventory, then confirm you are in the right block by checking that the very next <variable name="Domain"> line shows the old domain name. Matching on both name and domain matters: the same login name may legitimately exist in your current domain as a different, visible account.
  5. Change the enabled flag in that block from
    <variable name="Account_enabled">1</variable>
    to
    <variable name="Account_enabled">0</variable>
    Change nothing else in the block. Repeat for every hidden record you decided to disable.
  6. Save the file, keeping the same file name, location, and encoding.
  7. Start the Kerio Connect service again: Start Kerio Connect from the tray icon or "C:\Program Files\Kerio\MailServer\mailctrl.exe" start on Windows; /usr/local/kerio/mailserver/KerioMailServer start on macOS; systemctl start kerio-connect.service, sudo service kerio-connect start, or /etc/init.d/kerio-connect start on Linux.

Step 5 – Verify the license count

  1. Log in to the administration interface. The login-time license warning should no longer appear.
  2. Open Status > Dashboard. The created figure in Number of active mailboxes: X (Y created) should have dropped by exactly the number of records you disabled (16 → 13 in the example) and should now equal the number of enabled accounts you can see across all domains in Accounts > Users. To add a new account, created must be strictly below Number of users allowed by the license; a server at exactly the limit is full.
  3. Open Accounts > Users. The You cannot add more users. status text at the bottom should be gone – it is replaced by You can add N more users. when only a few seats remain, and disappears entirely when more seats are free.
  4. Create or activate the account you originally needed. It should succeed without a license warning.

If the created figure did not change, the service was most likely still running when the file was saved, or the file was saved under a different name or location. Stop the service, confirm it is stopped, re-check the Account_enabled values in users.cfg, and start the service again. Your backup copy lets you revert at any time.

Why these records exist: domain renames and migrations

When you rename a domain in Configuration > Domains, Kerio Connect keeps the original name as an alias so that mail addressed to the old name is still delivered, and during the required restart it rewrites the domain name in the configuration files so that every account moves to the new name. See Renaming Domains in Kerio Connect.

Hidden records appear when that rewrite does not cover every account – for example when the rename fails part-way and the remaining steps are completed by hand, as described in Renaming a Domain in Kerio Connect Fails. Years later the exact history is often unknown; what matters is the result, which is exactly what this article describes: a small number of local account records still tagged with a domain name that no longer exists as a domain, invisible in the interface but enabled and licensed. If you move individual users between domains by hand, follow Moving Users to a Different Domain on the Same Kerio Connect Server. After any rename or manual domain change, run the inventory from Step 2 once to make sure no record was left behind.

<supportagent>

Ask the customer for the sanitized inventory (Method A CSV or Method B output) rather than the raw users.cfg, which contains password hashes. Reconcile with the Accounts > Users export: enabled rows with DataSource=LDAP + enabled users.cfg records (all domains) must equal the Dashboard created figure. If it does not reconcile, the cause is something other than orphaned local records and this article does not apply. The license and account-management scope here is Support-side; no engineering escalation is needed for a reconciled count.

</supportagent>

Frequently Asked Questions

1. The Dashboard shows 11 active but 16 created mailboxes. Is that the problem?
No. Active counts users who have signed in since the last server restart; created counts enabled accounts. Only created matters for the license, and only a gap between created and what you can see in Accounts > Users indicates hidden accounts.

2. I have only one domain. How can there be accounts in another domain?
The domain list shows currently configured domains. Account records in users.cfg carry a domain name as plain text, and nothing forces that name to be a configured domain. After a rename or migration, records can keep the old name; the old name then typically shows up only in the Aliases column, which the Domain drop-down never lists.

3. Does this only affect servers connected to Active Directory?
No. The hidden records are local accounts, and the counting behavior is the same on any server. A directory service connection only means part of your total comes from mapped accounts, which are counted the same way but are not stored in users.cfg.

4. Can I just delete the hidden accounts instead of disabling them?
Disabling is sufficient: disabled accounts do not count against the license, and deleting an already-disabled account frees no additional seat. Deleting the raw records from users.cfg is not a documented procedure and is not covered here.

5. Will disabling these accounts delete their mail?
No. Disabling keeps the mailbox contents and settings; the account simply cannot sign in and its forwarding rules stop. Re-enabling the account (setting Account_enabled back to 1 with the same procedure) restores it fully.

6. All my accounts are legitimate and in use. How do I get more seats?
Changes to the number of user seats are handled by your GFI partner or GFI Sales, not by technical support. See Modifying or Extending a Kerio Connect License Key. To find seats you can free up first, go to Accounts > Users, click the arrow next to a column name, select Columns > Last Login, and sort by that column to spot accounts nobody has used for a long time, as described in Removing Inactive Users from Your License.

7. Is this a bug that needs a product update?
No. The license counter is behaving as designed by counting every enabled account record. The condition is leftover configuration from an earlier domain change, and the fix is the configuration cleanup described above.

Choose files or drag and drop files
Was this article helpful?
Yes
No
  1. Ciprian Nastase

  2. Posted

Comments