License
The product ships with an RSA-signed license file (license.lic). The vendor
holds the private key; the application bundles only the public key and
verifies the signature on every start.
A license buys support, not features. The application is fully functional without one — you can add servers, edit alert rules, run index maintenance, everything. The license records who holds a support entitlement and how long it runs. The software itself is perpetual: when the support period ends, nothing stops working.
How licensing works
appsettings.json:Licensing:PublicKeyBase64— the vendor's RSA-2048 public key. Shipped with the binary. Don't change this unless the vendor reissues a new key generation.appsettings.json:Licensing:LicenseFilePath— path to the license envelope file. Defaultlicense.lic(next to the binary).- The license envelope is a small JSON document containing customer name, edition, support expiry date, and a base64 RSA signature. The app re-verifies the signature on every start and reports the result — it never blocks anything.
Installing a license
- The vendor sends you
license.lic. - Drop it next to the binary (Windows:
C:\Apps\SqlServerHealthMonitor\license.lic; Linux:/opt/sshm/license.lic). - Restart the app.
- Watch the startup log — you should see:
License: support for Acme Corp (edition Standard) runs until 2027-06-30, 392 days remaining. - Visit
/Settings/Licenseto verify the same info in the UI.
If the log says:
License: Invalid — signature mismatch. Support status unknown; no features are restricted.
…either the file is corrupted in transit, or the public key in appsettings.json
doesn't match the private key that signed the file. Re-download the license; if
that fails, the public key probably needs to be reissued by the vendor.
Rotating / renewing
A renewed license is a new license.lic file with a later ExpiresAt. Replace
the file and restart — no app version change needed.
You can also install a renewal via the UI: /Settings/License → upload the new
file. The change is hot — no restart required.
Generating a new license (vendor side)
Vendor workflow only — for the operator side this is "don't touch":
# Generate the keypair (one-time, vendor keeps the private half FOREVER).
# Writes license-private-key.xml to the current dir and prints the public key.
dotnet run --project tools/LicenseGenerator -- genkey
# Sign a license for a customer. Positional args:
# sign <private-key.xml> <customer> <expires-yyyy-mm-dd> [edition] [maxServers]
# maxServers: recorded in the envelope and shown on the license page, but NOT
# enforced — nothing in the product gates on it. 0 or omitted = unset.
dotnet run --project tools/LicenseGenerator -- sign \
license-private-key.xml "Acme Corp" 2027-06-30 Standard 0
# A license that names a server count (recorded only — nothing enforces it):
dotnet run --project tools/LicenseGenerator -- sign \
license-private-key.xml "Acme Corp (Demo)" 2099-12-31 Demo 3
# The signed file is written as license.lic in the current directory. Send it to
# the customer; paste the printed public key into appsettings.json:Licensing:PublicKeyBase64.
If the vendor loses the private key: every previously-issued license stays valid (existing installs continue to verify), but new licenses can't be signed unless you generate a new keypair and ship an updated build with the new public key. That's an outage for new sales until the next release goes out.
What happens without a license, or with an expired one
Nothing stops working. There is no read-only mode, no feature gate and no server cap — every function is available whether a license is installed or not. What changes is only what the product can tell you about your support entitlement:
| State | What you see |
|---|---|
| Valid | /Settings/License shows the customer, edition and remaining support days. No banner. |
| Missing | Nothing at all. An unlicensed install is a normal, supported state. |
| Expired | Administrators get an informational banner saying support ended on that date, and that features are unaffected. |
| Invalid / Tampered | Administrators get an informational banner saying the file could not be read, so the support status is unknown. |
If you are looking for the code: LicenseStatus in Services/LicenseService.cs carries
the rule in a comment, and deliberately exposes no flag that a page could gate on.