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.

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. Default license.lic (next to the binary).
  • The license envelope is a small JSON document containing customer name, edition, expiry date, and a base64 RSA signature. The app re-verifies the signature on every start and warns/blocks changes if it fails or is expired.

Installing a license

  1. The vendor sends you license.lic.
  2. Drop it next to the binary (Windows: C:\Apps\SqlServerHealthMonitor\license.lic; Linux: /opt/sshm/license.lic).
  3. Restart the app.
  4. Watch the startup log — you should see:
    License: VALID for Acme Corp (edition Standard, expires 2027-06-30, 392 days remaining).
    
  5. Visit /Settings/License to verify the same info in the UI.

If the log says:

License: Invalid — signature mismatch (changes restricted until installed via /settings/license)

…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: monitored-server cap; 0 or omitted = unlimited.
dotnet run --project tools/LicenseGenerator -- sign \
    license-private-key.xml "Acme Corp" 2027-06-30 Standard 0

# Server-limited license (e.g. a 3-server demo, far-future expiry so only the
# server count binds):
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 when the license is invalid

The dashboard still loads (you can still monitor — that would be cruel otherwise), but write actions are blocked until a valid license is installed:

  • Adding/editing/deleting servers
  • Editing alert rules
  • Editing notification settings
  • User/role management

A red banner is shown across every page with a link to /Settings/License.