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

  1. Read the release notes. Breaking-change versions are called out. Don't skip this.
  2. Take a backup. The database, and your Encryption:Key if you set one, per backup-and-restore. This is the only thing between you and a botched upgrade.
  3. Block alerts during the maintenance window. Add a fleet-wide silence under /settings/silences with 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:

  1. Visit /health/detailed — should be Healthy for both checks.
  2. Visit /Settings/License — version updates here. Confirm.
  3. Visit /dashboard — server list populates within one refresh cycle.
  4. Trigger a test notification under /Settings/Notifications for each active channel. Don't assume "no errors in log" means "channels work" — they silently no-op when settings drift.
  5. Remove the maintenance silence from step 3 of "Before you start".

Rolling back

If the upgrade misbehaves:

  1. Stop the service.
  2. Database: restore from the backup taken before the upgrade. EF Core migrations are forward-only — you can't down them in production.
  3. Binaries: swap back to the .backup-YYYYMMDD folder.
  4. Restart.

This is why the database backup is non-negotiable.