Upgrade
In-place upgrade procedure for a single-host install. Multi-instance setups (load balancer in front, two app hosts) are out of scope for this doc — flag that and we'll write it.
Before you start
- Read the release notes. Breaking-change versions are called out. Don't skip this.
- Take a backup. The database, and your
Encryption:Keyif you set one, per backup-and-restore. This is the only thing between you and a botched upgrade. - Block alerts during the maintenance window. Add a fleet-wide silence
under
/settings/silenceswith scope = all servers, all rules, for the expected outage window. Otherwise the brief offline time during the restart pages the on-call.
Procedure — Windows service
# 1. Stop the service
sc.exe stop "SqlServerHealthMonitor"
# 2. Copy the install folder for rollback
Copy-Item C:\Apps\SqlServerHealthMonitor C:\Apps\SqlServerHealthMonitor.backup-$(Get-Date -Format yyyyMMdd) -Recurse
# 3. Overlay the new binaries
# (don't delete the folder first — keep DataProtection-Keys + Certs subfolders untouched)
dotnet publish -c Release -r win-x64 --self-contained false -o C:\Apps\SqlServerHealthMonitor
# 4. Start it back up
sc.exe start "SqlServerHealthMonitor"
# 5. Watch the log for migration output and "Application started"
Get-Content C:\Apps\SqlServerHealthMonitor\logs\*.log -Tail 200 -Wait
Procedure — Linux systemd
sudo systemctl stop sshm
sudo cp -a /opt/sshm /opt/sshm.backup-$(date +%Y%m%d)
sudo -u sshm dotnet publish -c Release -r linux-x64 --self-contained false -o /opt/sshm
sudo systemctl start sshm
sudo journalctl -u sshm -f
Procedure — Docker
docker pull sqlserverhealthmonitor:NEW_TAG
docker stop sshm
docker rm sshm
docker run -d --name sshm \
-p 8443:8443 \
-v sshm-keys:/root/.local/share/SqlServerHealthMonitor \
-e ASPNETCORE_ENVIRONMENT=Production \
-e ConnectionStrings__DefaultConnection="..." \
sqlserverhealthmonitor:NEW_TAG
docker logs -f sshm
The named volume sshm-keys carries the DataProtection keys across the container
rebuild. Leave it out and everyone has to log in again after the upgrade; the encrypted
connection strings are unaffected either way.
What happens at start-up
The app applies EF Core migrations automatically when
DatabaseSettings:EnableAutomaticMigrations is true (the default). On a
clean start you'll see something like:
Applying migration '20260603071304_RemoveSlackChannel'.
Applying migration '20260601...'.
If a migration fails the app exits with a non-zero code and the error in the log. The DB stays at the previous schema — you can roll back without surprises.
To run migrations manually (e.g. if automatic migrations are disabled):
# Need the matching EF Core CLI version
cd /opt/sshm
dotnet ef database update
Verifying the upgrade
After "Application started" in the log:
- Visit
/health/detailed— should beHealthyfor both checks. - Visit
/Settings/License— version updates here. Confirm. - Visit
/dashboard— server list populates within one refresh cycle. - Trigger a test notification under
/Settings/Notificationsfor each active channel. Don't assume "no errors in log" means "channels work" — they silently no-op when settings drift. - Remove the maintenance silence from step 3 of "Before you start".
Rolling back
If the upgrade misbehaves:
- Stop the service.
- Database: restore from the backup taken before the upgrade. EF Core
migrations are forward-only — you can't
downthem in production. - Binaries: swap back to the
.backup-YYYYMMDDfolder. - Restart.
This is why the database backup is non-negotiable.