# Runbook: Open Dental — Verify a backup by test-restoring into an isolated Hyper-V VM **Applies to:** Any Open Dental cold backup produced by [`od-db-backup.md`](od-db-backup.md) (an `od-backup-` folder holding `data\`, `OpenDentImages\`, `FreeDentalConfig.xml`, `MANIFEST.txt`). **Goal:** Prove a backup is actually restorable and complete by restoring it into a **throwaway, network-isolated Hyper-V virtual machine** and running a short health checklist. A backup you have never restored is a guess. > [!IMPORTANT] > **Never restore over a live production database** — Open Dental warns this can cause irreversible data loss. The whole point of this runbook is to restore somewhere that *cannot* touch production: an isolated VM, off the office network. ([Open Dental — Backups](https://opendental.com/manual/backups.html)) **Cadence:** Test-restore **at least monthly**, and any time you change backup jobs, versions, or hardware. Open Dental recommends restoring to a machine **not connected to the office network** to verify quality. ([Open Dental — Manual Backups](https://www.opendental.com/manual/backupsmanual.html)) **Why Hyper-V:** it gives you that isolated machine on demand, with a **checkpoint** you revert after every test — so each verification starts from a known-clean baseline and the PHI-laden copy is destroyed when you're done. Any spare offline PC or a doctor's disconnected laptop works too; the steps are identical inside. **Placeholders:** | Placeholder | Meaning | |---|---| | `` | The `od-backup-` folder being verified | | `` | Open Dental version from `MANIFEST.txt` — must match on the VM | | `` | MySQL/MariaDB version from `MANIFEST.txt` — must match on the VM | | `` | The MySQL/MariaDB service name **inside the VM** | | `` | The VM's MySQL data directory (e.g. `C:\mysql\data`) | | `` | The VM's A-to-Z images folder (e.g. `C:\OpenDentImages`) | --- ## Phase 0 — Read the manifest first Open `\MANIFEST.txt`. Note **`Open Dental ver`** (``) and **`DB engine ver`** (``). You must install **matching** versions in the VM — a version mismatch either refuses to open or silently converts the database. ([Open Dental — Manual Backups](https://www.opendental.com/manual/backupsmanual.html)) ## Phase 1 — Build the isolated verification VM (once, then reuse) Do this one time; you'll revert to a checkpoint for every future test. 1. **Enable Hyper-V** on a Windows Pro/Enterprise/Server host (elevated PowerShell; reboots): ``` Enable-WindowsOptionalFeature -Online -FeatureName Microsoft-Hyper-V -All ``` 2. **Create an isolated network** so the VM can never reach the office network or the live database. In Hyper-V Manager → *Virtual Switch Manager*, create a **Private** (or **Internal**) switch — **not** External. Or leave the VM with **no network adapter** at all. > This isolation is the safety guarantee. An "External" switch would put the test VM on the practice LAN, where a mistake could reach production shares or the live DB. Don't. 3. **Create the VM** (Gen 2, enough RAM/disk for the database + images), install a supported **Windows** guest. 4. Inside the VM, install **MySQL/MariaDB ``** and **Open Dental ``** (matching the manifest). Do a normal Open Dental install so ``, ``, and a local `opendental` database exist. 5. Shut the VM down cleanly and take a **checkpoint** named `clean-baseline`. This is your reset point. ## Phase 2 — Get the backup into the VM (keep it offline) Copy `` into the VM **without** using the office network — e.g. Hyper-V Enhanced Session copy/paste, or attach the backup as a VHD/passthrough disk, or a scratch VHDX. The VM stays isolated the entire time. ## Phase 3 — Restore into the VM Run these **inside the VM**, elevated. This mirrors Open Dental's documented restore, adapted for our **whole-datadir** cold copy. 1. **Stop the database:** ``` net stop Get-Service # confirm Status = Stopped before touching files ``` 2. **Move the VM's existing data aside** (don't delete — lets you retry): ``` Rename-Item "" "-old" New-Item -ItemType Directory "" | Out-Null ``` 3. **Restore the whole data directory** from the backup — copy the **entire contents of the backup's `data\` folder**, not just `data\opendental\`: ``` robocopy "\data" "" /E /COPY:DAT /R:2 /W:5 ``` > For **InnoDB** you must restore the shared tablespace and logs (`ibdata1`, `ib_logfile*`) that live at the datadir root alongside the `opendental` folder — that's why we restore the whole `data\`, matching how [`od-db-backup.md`](od-db-backup.md) captured it. Restoring only the `opendental` subfolder yields a database that won't start. 4. **Restore the images:** ``` robocopy "\OpenDentImages" "" /E /COPY:DAT /R:2 /W:5 ``` 5. **Start the database:** ``` net start Get-Service # confirm Running ``` 6. **Launch Open Dental in the VM**, connecting to the **local** `opendental` database (localhost). Configure a fresh local connection — do **not** reuse the production `FreeDentalConfig.xml` connection string (it points at the real server). The captured `FreeDentalConfig.xml` is only a **reference** of production settings (e.g. the A-to-Z path). 7. If Open Dental reports it **can't find the images**, point the image path at ``: *Setup → Imaging / Image path* (the A-to-Z path stored in the database is production's; update it to the VM's local folder so restored images resolve). ## Phase 4 — Health checklist: is this backup good? Work top to bottom. **All must pass** for the backup to count as verified. - [ ] **Connects & opens** — Open Dental launches against the restored DB with **no connection or startup errors**. - [ ] **Version matches** — *Help → About* shows `` (no unexpected DB-conversion prompt). - [ ] **Database Maintenance is clean** — *Main Menu → Tools → Database Maintenance*, run **Check** (not Fix). It "checks the database for improper settings, inconsistencies, or corruption." Review the results for **unexpected** corruption/integrity errors. ([Open Dental — Database Maintenance](https://www.opendental.com/manual/databasemaintenance.html)) - [ ] **Recent data is present and current** — open the **Appointments** module on a recent production date; open 2–3 known patients; check a recent **payment/ledger** entry. Confirm the newest data lines up with production **as of the backup time** (proves the backup is current, not stale). - [ ] **Images actually open** — pick a patient known to have scanned docs/X-rays in the Imaging module and **open the files**. This proves the A-to-Z folder restored *and* the image path resolves — a DB-only restore silently loses every document. - [ ] **No missing modules/tables** — click through Chart, Family, Account, Imaging; watch for "table doesn't exist" / read-only errors. - [ ] *(Optional, deeper)* **Engine-level integrity** — from the VM's MySQL shell, `mysqlcheck -u root -p --check opendental` (or `CHECK TABLE`) to confirm no table-level corruption. ## Phase 5 — Record the result (keep as evidence) Log, outside the VM: **date verified**, `` timestamp, ``/``, each checklist item **pass/fail**, who ran it, and any Database Maintenance findings. This is your DR evidence for E&O / cyber insurance and HIPAA contingency-plan testing. > A **fail** on any item means the backup is not trustworthy — fix the backup job (not just this restore) and re-verify. Common causes: images folder never included; only `data\opendental\` copied (InnoDB won't start); backup taken hot without stopping the service; version drift. ## Phase 6 — Tear down / reset 1. In Open Dental, close out; **stop the MySQL service** in the VM before shutting down. > Open Dental warns: if a machine used to verify backups **sleeps while MySQL is running, it can corrupt the database.** Stop the service first. ([Open Dental — Manual Backups](https://www.opendental.com/manual/backupsmanual.html)) 2. **Revert the VM to the `clean-baseline` checkpoint.** This resets to a known-clean state for next time **and destroys the restored PHI copy**. 3. Never reconnect this VM to the office network with a restored database attached. --- ## Security note The moment you restore, the VM's virtual disk holds the **entire practice's PHI** — treat it exactly like production. Keep the VM **isolated** (Private/Internal switch or no NIC), keep the host and VHDX **encrypted** (BitLocker / encrypted VHDX), and **revert/destroy** the restored state when done so PHI doesn't linger on a test box. HIPAA applies to the copy just as much as to production. See the security note in [`od-db-backup.md`](od-db-backup.md) — on direct-connection setups the captured `FreeDentalConfig.xml` also holds the (reversibly obfuscated) DB password. ## References - Open Dental manual — Backups (overview; test-restore off-network): - Open Dental manual — Manual Backups (restore steps; verify on disconnected machine; sleep/corruption warning): - Open Dental manual — Database Maintenance (Check/Fix health tool): - Open Dental manual — Backup Tool: - Companion runbook — producing the backup: [`od-db-backup.md`](od-db-backup.md)