Backup & restore
The two-sentence summary: back up the monitoring database, and — if you set your own
Encryption:Key — back up that key with it. The database holds everything the product
knows; the encryption key is the only artifact that cannot be recreated, because without it
the encrypted columns in that database can never be read again.
What to back up
| What | Why | Default location |
|---|---|---|
| Monitoring database | All configuration, server inventory, alert rules, history, audit log, encrypted secrets | Wherever your monitoring SQL Server lives |
Encryption:Key, if you set one |
The AES-256 key that decrypts connection strings and notification secrets. Lose it and those columns are unrecoverable | appsettings.json, an environment variable, or your secret store — wherever you put it |
| License file | RSA-signed license envelope | Path from appsettings.json:Licensing:LicenseFilePath (default license.lic next to the binary) |
appsettings.json + any environment-specific overlay |
Connection string and bootstrap config | Next to the binary, or /app in the container |
| HTTPS certificate | Your CA-issued certificate, if you installed one | SecuritySettings:CertificatePath, or the certificate folder |
| DataProtection keys folder | Convenience only — see below | Windows: %LOCALAPPDATA%\SqlServerHealthMonitor\DataProtection-KeysLinux: ~/.local/share/SqlServerHealthMonitor/DataProtection-Keys |
Skip bin/, obj/ and wwwroot/lib/ — the installer reproduces them.
Which key actually matters
Two different key systems are in play, and only one of them is critical.
The encryption key (Encryption:Key) is the critical one. Connection strings to
monitored servers and notification secrets (Microsoft 365 credentials, PagerDuty routing key,
Teams webhook) are stored under an enc:v2: envelope: AES-256-GCM with a fixed key. That key
comes from Encryption:Key if you configured one, otherwise from a default built into the
application. Using the built-in default means there is nothing extra to back up — but it also
means anyone holding a copy of the binary can decrypt a stolen database, so the encryption
protects a leaked database-only backup and nothing more. If that is not good enough for
you, set your own 32-byte base64 key — and from that moment on, treat it exactly like a
database backup. There is no recovery path if it is lost.
The DataProtection keys folder is no longer critical. The framework still uses it for
authentication cookies, antiforgery tokens, the self-signed HTTPS certificate, and for
reading any leftover enc:v1: payloads from older versions. Losing it logs everyone out and
regenerates the self-signed certificate — annoying, not fatal. Your encrypted columns survive,
because they are enc:v2: under the fixed key. Older documentation (and older versions of
this page) described this folder as the artifact that must never be lost; that has not been
true since the move to enc:v2:.
On startup the application re-encrypts any row that is still enc:v1: or bare plaintext onto
the current envelope. A row it cannot decrypt is left untouched and logged, never
overwritten — so a missing legacy key costs you that one value, not the column.
Backup cadence
- Database — the same cadence as your other production databases, typically nightly FULL plus hourly LOG.
- Encryption key, license,
appsettings.json— once per change. They are tiny, and they change only when you change them. - DataProtection keys folder — optional. Including it in a weekly pass saves your users a forced re-login after a host rebuild.
Restore procedures
After losing the monitoring database
- Restore the database to the same or a different SQL Server.
- Update
ConnectionStrings:DefaultConnectionif the server or database name changed. - Make sure the same
Encryption:Keyis configured as before — or none, if you were using the built-in default. - Restart. Encrypted columns decrypt immediately.
After losing the DataProtection keys folder (database intact)
- Restart. New keys are generated.
- Everyone is signed out and has to log in again.
- If you were using the self-signed certificate, a new one is generated — clients that pinned or manually trusted the old one need to trust the new one.
- Monitoring, connection strings and notification secrets are unaffected.
After losing your own Encryption:Key (database intact)
This is the worst case, and it only applies if you configured a key of your own.
- The application starts, but every value encrypted under the lost key fails to decrypt. Connection strings come back empty, so every monitored server shows as unreachable; notification channels fail.
- The startup pass logs each row it could not decrypt and leaves the ciphertext in place. Nothing is silently destroyed — but nothing can be read, either.
- Recovery is manual re-entry:
/Servers→ edit each server → paste the connection string again → Save./Settings/Notifications→ re-enter each channel's secret → Save.
- Set a new
Encryption:Key(or drop the setting to fall back to the built-in default) before re-entering anything, so the new values are written under a key you still have.
There is no shortcut. That is why the key belongs in your backup plan.
After losing everything
- Fresh install per deployment.
- Restore the monitoring database.
- Restore
appsettings.jsonincludingEncryption:Key, or follow the manual re-entry above if the key is gone.
Verifying your backup covers the key
If Encryption:Key is set in appsettings.json, confirm the file itself is in the backup set
— not just the database:
Select-String -Path "C:\Apps\SqlServerHealthMonitor\appsettings.json" -Pattern '"Key"'
If the key comes from an environment variable or a secret store instead, confirm that store is backed up and that you can actually read the value back. A key you cannot retrieve is a key you have lost.
Disaster-recovery rehearsal
Once a year, or before any major upgrade:
- Restore the monitoring database and
appsettings.jsonto a staging host. - Point the staging instance at a non-production network so it cannot page anyone for real.
- Confirm:
- the dashboard loads;
- the server list connects — which proves the connection strings decrypted;
- the test buttons under
/Settings/Notificationssucceed — which proves the channel secrets decrypted.
- Tear down staging.
If the connection test fails on a restored copy while it works in production, your backup is missing the encryption key. Fix that before you need it.