- 01What you are building
- 02Hardware: Dell PowerEdge, PERC, 4 SSDs, NICs
- 03RAID configuration (with selector)
- 04iDRAC — do this before the OS install
- 05Installing Windows Server 2022
- 06Network: virtual switches and NIC binding
- 07Enabling Hyper-V
- 08VM build: SQL Server 2022
- 09VM build: KEPServerEX
- 10Connecting KEPServerEX to SEL RTAC over DNP3
- 11VM build: SCADA / engineering workstation
- 12VM build: Linux utility
- 13Time sync — why this matters for DNP3
- 14Backup and recovery
- 15Commissioning checklist
01 — What you are building
One Dell PowerEdge server, single host, running Windows Server 2022 with the Hyper-V role. Four VMs sit on top: a SQL Server 2022 historian, a KEPServerEX gateway, a SCADA engineering workstation, and a small Linux utility VM. The KEPServerEX VM polls a SEL RTAC over DNP3 on the plant LAN and forwards data to SQL on the management vSwitch. The SCADA workstation reads from SQL and from KEPServerEX OPC UA. Everything is on one physical box. This is the architecture that runs most utility-scale solar plants under about 50 MW.
Failover Clustering, Hyper-V Replica to a second host, and Storage Spaces Direct are different architectures and are out of scope for this article. Single-host is appropriate for most utility-scale solar plants under about 50 MW where the SCADA disruption window during a hardware fault is bounded by a maintenance contract, not by zero downtime. Larger plants and plants with stricter SLAs should pair this article with a clustering plan.
02 — Hardware: Dell PowerEdge, PERC, 4 SSDs, NICs
Spec sheet for a typical plant SCADA host. Adjust by tag count and historian retention requirement.
| Component | Spec | Why |
|---|---|---|
| Chassis | Dell PowerEdge R650 or R660 (1U) | 1U fits a typical plant comms rack. R750/R760 (2U) if you need extra drive bays for archive growth. |
| CPU | Single Xeon Silver 4314 (16 core / 32 thread) or Gold 6326 (16 core) | Hyper-V plus four VMs comfortably fits one socket. Dual socket is overkill on a small plant and adds NUMA scheduling complexity. |
| RAM | 64 GB ECC DDR4/DDR5 minimum (128 GB on larger plants) | 16 GB SQL + 8 GB KEPServerEX + 8 GB SCADA + 4 GB Linux + 16 GB host overhead and disk cache. ECC is non-negotiable on a SCADA box. |
| RAID controller | PERC H755 (current gen) or H965i (NVMe-capable) | Hardware RAID with battery-backed cache. Do not use the embedded Intel VROC controller; Windows Server treats it as software RAID and you lose write-back caching. |
| Storage | 4 × 960 GB or 1.92 TB enterprise SSDs (SAS or NVMe) | RAID 10 across the four gives ~2× drive write performance, single-drive fault tolerance, fast rebuild. RAID layout selector below. |
| NICs | 4 × 1 GbE (built-in) or 2 × 10 GbE + 2 × 1 GbE | One physical NIC each for plant LAN, management, engineering, and iDRAC. Never share iDRAC with production. |
| Power | Dual redundant PSU, each on a different UPS feed | Both PSUs on the same UPS gives you no protection against UPS failure. |
| iDRAC | iDRAC9 Enterprise license (included on most R650 SKUs) | Required for virtual media, virtual console, and remote power cycling. Basic iDRAC is not enough. |
On Dell servers the integrated LOM (LAN-on-motherboard) ports are sometimes shared between iDRAC and OS traffic by default. In F2 BIOS Setup → iDRAC Settings → Network, change "NIC Selection" to Dedicated. If you leave it on shared LOM, iDRAC traffic and your plant LAN ride the same cable and you have not actually separated management from production.
03 — RAID configuration
Four SSDs gives three reasonable layouts. The selector below shows the tradeoffs. Pick one before installing the OS; reconfiguring RAID after install means rebuilding the box.
RAID Layout Selector — 4 × SSD
The recommendation for a typical plant SCADA host is RAID 10. Rebuild time on a failed SSD is shorter, write performance is high (SQL log writes love this), and you tolerate one drive failure with capacity for a second-drive failure in the right pair. If historian retention is unusually large and you cannot grow the box, RAID 5 buys you 50% more usable space at the cost of slower writes and longer rebuild.
Configuring RAID 10 via PERC CLI
The Dell PERC CLI tool (perccli64 on Windows, perccli on Linux pre-OS environments) is more reproducible than the iDRAC GUI walkthrough because the syntax doesn't change with firmware revisions. The commands below assume the PERC is at controller index 0 (the default on a single-controller box).
# List physical drives so you know your enclosure and slot IDs
perccli64 /c0 show all
# Create a RAID 10 virtual disk across slots 0:0, 0:1, 0:2, 0:3
# wt = write-through during creation, change to wb (write-back) after BBU verifies
perccli64 /c0 add vd r10 drives=32:0,32:1,32:2,32:3 wt ra direct
# After the BBU (battery-backed cache) reports good, switch to write-back
perccli64 /c0/v0 set wrcache=wb
# Initialize fully (not fast init) before putting data on it
perccli64 /c0/v0 start init full
# Check progress
perccli64 /c0/v0 show initialization
If the PERC battery is missing, expired, or reporting degraded, write-back cache means a power loss can lose acknowledged writes. SQL Server treats those writes as committed. The result is database corruption that does not show up until the next checkpoint. Verify BBU status with perccli64 /c0/bbu show all before enabling write-back, and have a replacement battery on the shelf.
04 — iDRAC, before the OS install
Do this in F2 BIOS Setup on first boot, before you have any OS on the box. If you skip it and install Windows first, you will be redoing it from a freshly racked server in a noisy comms room.
root / calvin is published on every shodan scan result. Change it before the box has internet access, not after. Set a 20+ character random password and store it in the site password vault, not on a sticky note in the rack.05 — Installing Windows Server 2022
Mount the Windows Server 2022 ISO through iDRAC virtual media. From your laptop: iDRAC web interface → Virtual Console → Virtual Media → Map ISO. Boot the server from virtual CD/DVD. The install runs normally from here.
- Edition: Standard with Desktop Experience. Datacenter only makes sense if you intend to run more than two Windows VMs on the same host (Datacenter licenses unlimited VMs on the host hardware). For this build, Standard is enough.
- Partitioning: Let the installer use the entire RAID virtual disk. Do not pre-partition. The installer creates the system partition, recovery partition, and the C: drive. You will add a data volume after the OS is up.
- Local administrator password: Site password vault, 20+ characters. Never reuse a password across plants.
After first boot:
# Rename the host to something predictable
Rename-Computer -NewName "PLANT01-SCADA01" -Restart
# After reboot, set the time zone (UTC on plant servers is the safest default,
# but if your historian reports in local time, pick the plant local zone)
Set-TimeZone -Id "UTC"
# Install all current updates before adding any roles
Install-Module PSWindowsUpdate -Force -SkipPublisherCheck -AllowClobber
Get-WindowsUpdate -AcceptAll -Install -AutoReboot
# Disable IE Enhanced Security (it gets in the way of downloading drivers from Dell)
$AdminKey = "HKLM:\SOFTWARE\Microsoft\Active Setup\Installed Components\{A509B1A7-37EF-4b3f-8CFC-4F3A74704073}"
Set-ItemProperty -Path $AdminKey -Name "IsInstalled" -Value 0
06 — Network: virtual switches and NIC binding
Decide your physical NIC layout before building any vSwitch. The architecture diagram in §01 shows the target. Confirm each physical adapter shows up in Windows and is named obviously.
# See current adapters and their MACs
Get-NetAdapter | Select-Object Name, MacAddress, LinkSpeed, Status
# Rename them so they are not "Ethernet 1" through "Ethernet 4"
Rename-NetAdapter -Name "Ethernet" -NewName "NIC-Plant"
Rename-NetAdapter -Name "Ethernet 2" -NewName "NIC-Mgmt"
Rename-NetAdapter -Name "Ethernet 3" -NewName "NIC-Eng"
# (NIC 4 is the iDRAC port — not visible in Windows, lives behind the BMC)
# Build the three virtual switches
New-VMSwitch -Name "vSwitch-Plant" -NetAdapterName "NIC-Plant" -AllowManagementOS $false
New-VMSwitch -Name "vSwitch-Mgmt" -SwitchType Internal
New-VMSwitch -Name "vSwitch-Eng" -NetAdapterName "NIC-Eng" -AllowManagementOS $true
# Verify
Get-VMSwitch | Format-Table Name, SwitchType, NetAdapterInterfaceDescription
The -AllowManagementOS $false on the plant switch is deliberate: the host operating system does not need an IP on the plant LAN. Only the VMs that participate in plant traffic (KEPServerEX) get vNICs there. This keeps Windows Update traffic and corporate network activity entirely off the plant VLAN.
Some SCADA configurations and time-sensitive protocols misbehave when Hyper-V allows VMs to spoof MAC addresses. After you attach the KEPServerEX VM to vSwitch-Plant, set Set-VMNetworkAdapter -VMName KEP01 -MacAddressSpoofing Off and confirm. Leave it on only if you intentionally use a virtual IP that floats between VMs (you probably do not).
07 — Enabling Hyper-V
# Install the Hyper-V role with the management tools
Install-WindowsFeature -Name Hyper-V -IncludeManagementTools -Restart
# After reboot, set a sensible default location for VHDX files
Set-VMHost -VirtualMachinePath "D:\VMs" -VirtualHardDiskPath "D:\VHDX"
# Confirm
Get-VMHost | Select-Object VirtualMachinePath, VirtualHardDiskPath
The data volume (D:) is the volume you build on the RAID-10 array after Windows is up. Use Disk Management or the PowerShell New-Volume cmdlet to format it NTFS with 64 KB allocation unit size — SQL Server, Hyper-V, and large-file workloads all benefit from 64 KB clusters.
08 — VM build: SQL Server 2022
SQL Server is the historian backbone. KEPServerEX will write to it through ODBC or the Industrial Data Forwarder; the SCADA workstation reads from it for reports and trends.
Create the VM
$vm = "SQL01"
$path = "D:\VMs\$vm"
# Generation 2 = UEFI + Secure Boot, required for modern Windows VMs
New-VM -Name $vm -Generation 2 -MemoryStartupBytes 16GB -Path $path `
-NewVHDPath "D:\VHDX\$vm-OS.vhdx" -NewVHDSizeBytes 80GB -SwitchName "vSwitch-Mgmt"
Set-VMProcessor -VMName $vm -Count 4
Set-VMMemory -VMName $vm -DynamicMemoryEnabled $false -StartupBytes 16GB
# Add a second VHDX dedicated to SQL data files
New-VHD -Path "D:\VHDX\$vm-DATA.vhdx" -SizeBytes 500GB -Fixed
Add-VMHardDiskDrive -VMName $vm -Path "D:\VHDX\$vm-DATA.vhdx"
# Add a third VHDX for SQL log files (separate physical-like volume keeps log I/O off data I/O)
New-VHD -Path "D:\VHDX\$vm-LOG.vhdx" -SizeBytes 100GB -Fixed
Add-VMHardDiskDrive -VMName $vm -Path "D:\VHDX\$vm-LOG.vhdx"
Start-VM -Name $vm
SQL Server runs on dynamic VHDX and the SCADA world will hum along fine. It also writes 4 KB pages all day, every day, and the dynamic VHDX has to grow its file as you write. Fixed-size VHDX pre-allocates the full disk, removes that growth overhead, and gives predictable I/O latency. On a SCADA box with deterministic alarm requirements, fixed is the right choice for SQL data and log VHDX. The OS VHDX can stay dynamic.
Install SQL Server 2022 Standard
Inside the VM, mount the SQL Server 2022 ISO. The GUI installer works, but a configuration file install is reproducible and is what should go in the site runbook. Save the following as ConfigurationFile.ini on the SQL01 VM:
[OPTIONS]
ACTION="Install"
ENU="True"
QUIET="True"
QUIETSIMPLE="False"
UpdateEnabled="True"
ERRORREPORTING="False"
USEMICROSOFTUPDATE="True"
FEATURES=SQLENGINE,FULLTEXT,CONN,BC,SDK,SQL_INST_MR,SQL_INST_MPY
HELP="False"
INDICATEPROGRESS="True"
X86="False"
INSTANCENAME="MSSQLSERVER"
INSTANCEID="MSSQLSERVER"
INSTANCEDIR="C:\Program Files\Microsoft SQL Server\"
INSTALLSHAREDDIR="C:\Program Files\Microsoft SQL Server\"
INSTALLSHAREDWOWDIR="C:\Program Files (x86)\Microsoft SQL Server\"
INSTALLSQLDATADIR="E:\SQLData"
SQLBACKUPDIR="E:\SQLBackup"
SQLUSERDBDIR="E:\SQLData"
SQLUSERDBLOGDIR="F:\SQLLog"
SQLTEMPDBDIR="E:\SQLData"
SQLTEMPDBLOGDIR="F:\SQLLog"
SQLSVCACCOUNT="NT Service\MSSQLSERVER"
SQLSVCSTARTUPTYPE="Automatic"
AGTSVCACCOUNT="NT Service\SQLSERVERAGENT"
AGTSVCSTARTUPTYPE="Automatic"
SQLSYSADMINACCOUNTS="BUILTIN\Administrators"
SECURITYMODE="SQL"
TCPENABLED="1"
NPENABLED="0"
BROWSERSVCSTARTUPTYPE="Disabled"
# Run the unattended install (replace SA_PASSWORD with the actual one from your vault)
.\setup.exe /ConfigurationFile=ConfigurationFile.ini /IAcceptSQLServerLicenseTerms /SAPWD="REDACTED" /PID="YOUR-LICENSE-KEY"
Inside SQL Server Management Studio after install, create the historian database with pre-grown files. Setting initial size to the expected one-year footprint avoids autogrow events during heavy DNP3 traffic, which can stall writes and bunch up SCADA alarms.
CREATE DATABASE PlantHistorian
ON PRIMARY (
NAME = 'PlantHistorian_data',
FILENAME = 'E:\SQLData\PlantHistorian.mdf',
SIZE = 50GB,
MAXSIZE = 400GB,
FILEGROWTH = 5GB
)
LOG ON (
NAME = 'PlantHistorian_log',
FILENAME = 'F:\SQLLog\PlantHistorian_log.ldf',
SIZE = 10GB,
MAXSIZE = 50GB,
FILEGROWTH = 1GB
);
GO
ALTER DATABASE PlantHistorian SET RECOVERY SIMPLE;
GO
09 — VM build: KEPServerEX
KEPServerEX (now formally Kepware Server, but everyone calls it KEPServerEX) is the protocol gateway. It speaks DNP3 to the RTAC, OPC UA to the SCADA workstation, and ODBC to SQL.
Create the VM
$vm = "KEP01"
New-VM -Name $vm -Generation 2 -MemoryStartupBytes 8GB -Path "D:\VMs\$vm" `
-NewVHDPath "D:\VHDX\$vm-OS.vhdx" -NewVHDSizeBytes 80GB
Set-VMProcessor -VMName $vm -Count 4
Set-VMMemory -VMName $vm -DynamicMemoryEnabled $false -StartupBytes 8GB
# KEPServerEX needs two vNICs: one on plant LAN to talk DNP3 to the RTAC,
# one on management to serve OPC UA and ODBC
Add-VMNetworkAdapter -VMName $vm -SwitchName "vSwitch-Plant" -Name "Plant"
Add-VMNetworkAdapter -VMName $vm -SwitchName "vSwitch-Mgmt" -Name "Mgmt"
Set-VMNetworkAdapter -VMName $vm -Name "Plant" -MacAddressSpoofing Off
Start-VM -Name $vm
Install and harden KEPServerEX
Inside the KEP01 VM, install Windows Server 2022 Standard or Windows 10/11 Pro (KEPServerEX runs fine on either; Server is preferred for licensing alignment). Then install KEPServerEX with the DNP Master Suite and OPC UA Server features selected. Defaults are fine until you get to OPC UA security — those defaults are not safe.
scada-read with read-only access, scada-historian with read access to history tags only. Do not reuse passwords across plants and do not put service accounts in the OPC UA admin group.C:\ProgramData\Kepware\KEPServerEX\V6\user_data\default_project.opf. Back this up to the NAS nightly. After every config change, save a copy with a date suffix. The day this file gets corrupted you will be glad it has 30 backups.10 — Connecting KEPServerEX to SEL RTAC over DNP3
The central question of this article. The SEL RTAC presents itself on the plant LAN as a DNP3 outstation at a known IP address with a known DNP outstation address (the address you assigned in AcSELerator RTAC when you configured its DNP3 Server task). KEPServerEX is the DNP3 master that polls it.
This article assumes KEPServerEX is the DNP3 master and the RTAC is the outstation. That is the normal architecture when KEP is feeding a plant SCADA system from the RTAC. If you instead have the RTAC acting as a DNP3 master polling field devices and KEP picking up via Modbus or OPC, the configuration in this section does not apply. The SEL RTAC as Power Plant Controller article walks the master-RTAC scenario.
Step A: Confirm the RTAC outstation is configured
On the RTAC, AcSELerator RTAC must have a DNP3 Server (outstation) configured with:
- Listening on TCP port 20000 (default DNP3 over TCP port)
- An outstation DNP address (typically 1 for a single-plant configuration; document this)
- The point map you developed using the DNP3 point list design process
- Unsolicited responses configured for Class 1 events
Step B: Add the DNP3 Master channel in KEPServerEX
- Open KEPServerEX Configuration. Right-click "Connectivity" → New Channel.
- Driver: DNP Master Ethernet. (Requires the DNP Master Suite license.)
- Channel name:
RTAC_DNP3 - Default Datatypes: leave as defaults; KEP figures these out from the point map.
- On the network interface page, bind the channel to the IP address that lives on the plant vNIC, not the management vNIC. This forces DNP3 traffic out the correct interface.
Step C: Add the RTAC as a Device under that channel
| Setting | Value | Notes |
|---|---|---|
| Device Name | RTAC01 | Match the host name on the plant naming convention. |
| Device Model | DNP3 Outstation | Only option on a master channel. |
| IP Address | Static IP of the RTAC on plant LAN | Document this; do not leave the RTAC on DHCP. |
| TCP Port | 20000 | Default DNP3/TCP. Matches the RTAC listener. |
| Local Master Address | 3 | This is the DNP address KEP uses as the master. Must not collide with the outstation address. |
| Remote Slave Address | 1 | The DNP outstation address you set on the RTAC. |
| Request Link Status | 30 seconds | Heartbeat keepalive on the DNP3 data link layer. |
| Integrity Poll | Every 60 seconds (or longer) | Pulls every point's current value. Do not set this aggressively; it pulls everything. |
| Class 1 Poll | Disabled (use unsolicited) | Class 1 events should arrive unsolicited from the RTAC. |
| Class 2 Poll | Every 2 seconds | For analog updates with deadband-driven events. |
| Class 3 Poll | Every 30 seconds | For slow-changing analogs (temperatures, daily counters). |
| Unsolicited Mode | Enabled | Most important setting. KEP must send "Enable Unsolicited" on link establishment. |
Step D: Build the tag list
KEP's DNP3 driver can auto-build the tag list from the outstation's response to a class poll, or you can manually create tags matching the point list. Auto-build is faster on initial commissioning; manual is what you need for production because it forces you to document every tag's data type, deadband, and scaling.
# Example tag definitions (KEP CSV import format)
# Group_Variation maps to DNP3 object/variation as defined in IEEE 1815
Tag Name, Address, Data Type, Scaling, Notes
POI_Active_Power, Group32_Var3_Index0, Float, 1.0, AI3 from RTAC, kW
POI_Reactive_Pwr, Group32_Var3_Index1, Float, 1.0, AI3 from RTAC, kVAR
POI_Voltage_A, Group32_Var3_Index2, Float, 1.0, AI3, line-to-ground volts
Main_Bkr_52a, Group2_Var1_Index0, Boolean, , BI1 with timestamp
Q_Setpoint_Echo, Group32_Var3_Index10, Float, 1.0, AI3 echo of AO setpoint
Q_Setpoint_Cmd, Group41_Var3_Index0, Float, 1.0, AO3 to RTAC, kVAR
Trip_Plant_Cmd, Group12_Var1_Index0, Boolean, , BO1 SBO required
Step E: Verify the link is up and points are good
In KEP Configuration, right-click the device → Quick Client. The Quick Client opens an OPC UA browser that lets you watch tag values update in real time. What to look for:
- Quality Good on every tag. Quality Bad on a single tag points to a wrong index or wrong group/variation. Quality Bad on every tag points to a link-layer problem (wrong IP, wrong port, wrong master/outstation address pair).
- Values updating at the expected rate. If POI_Active_Power stays static for a minute then jumps, you are getting integrity polls only and unsolicited is broken.
- No "Master/Slave Address Mismatch" in the event log. This means KEP is sending master address X and the RTAC expects Y. Fix on whichever side is wrong.
Most KEP master implementations need to send a function code 20 (Enable Unsolicited Responses) every time the DNP link establishes. If the network bounces (switch reboot, cellular failover, RTAC restart), the master must re-issue the enable. KEP does this automatically with the right setting; verify by watching a DNP3 trace after a forced link drop. If the master does not re-enable, your Class 1 events fall back to integrity-poll-only and your fault timestamps come in 60 seconds late.
Step F: Forward to SQL
The Industrial Data Forwarder (IDF) plugin in KEPServerEX or the ODBC Client driver can write tag values into the historian database. IDF is the modern path. Configure an IDF Agent pointing at the SQL Server VM on the management network, with the agent's connection string targeting PlantHistorian and using SQL authentication with the scada-historian user. Throttle the write batch size — without throttling, a noisy DNP3 update can spike SQL log writes and cause queue back-pressure.
11 — VM build: SCADA / engineering workstation
This VM hosts the SCADA designer (Ignition Designer, GPM screens, or whatever platform the plant uses) and the operator-facing HMI. Spec: 4–8 vCPU, 16 GB RAM, 200 GB OS VHDX. Connect both vSwitch-Mgmt (to talk to KEP and SQL) and vSwitch-Eng (so operators can reach the screens from the engineering LAN). This VM has no plant LAN access — it never needs to talk DNP3 directly.
The HMI used by operators and the SCADA designer used to make changes both can live on this VM, but if your site has more than one SCADA engineer, give each a separate workstation VM. Two people editing the same project at the same time corrupts saves. One VM per engineer plus a shared production deployment is the working pattern.
12 — VM build: Linux utility
Smallest VM on the box — 2 vCPU, 4 GB RAM, 60 GB VHDX, single vNIC on vSwitch-Mgmt. Pick a long-term support distribution: Ubuntu Server 22.04 LTS or Debian 12. Three common roles for this VM:
- Mosquitto MQTT broker. If the plant publishes to a cloud SCADA or to N3uron's MQTT module, the broker runs here. See the N3uron MQTT bridge article for the publish-side configuration.
- InfluxDB or TimescaleDB historian. An alternative to SQL Server for plants that prefer open-source historians or need higher write throughput than SQL's row-store handles comfortably.
- Packet capture box. tcpdump or Wireshark on a mirrored switch port. When the plant has intermittent DNP3 link drops or GOOSE timing issues, having a Linux capture VM ready to record on demand is faster than scrambling to set one up during the incident.
13 — Time sync — why this matters for DNP3
DNP3 carries timestamps. SOE (sequence of events) records carry exact times for faults. If the RTAC clock and the SCADA host clock disagree by even a few seconds, your historian shows fault events out of order. Worse: if the Hyper-V host clock jumps backwards (it can, on first boot or after a sync correction), the VMs inherit that jump and SQL Server logs writes with timestamps earlier than the previous write. This can corrupt the transaction log.
What to configure
- Host: Point Windows Time service at a real NTP source. On a substation that means the GPS-synchronized substation clock (often a Meinberg or Tekron device) on the plant LAN, not
time.windows.com.w32tm /config /manualpeerlist:"10.x.x.x" /syncfromflags:manual /reliable:yes /update - VMs: Either disable Hyper-V Integration Services Time Sync and run NTP inside the VM, OR keep Integration Services Time Sync on and disable in-VM NTP. Not both. The two fighting each other gives unpredictable drift.
- Inside SQL VM: Confirm SQL Server's transaction log timestamps are monotonic after any clock correction.
SELECT MAX(begin_time) FROM sys.dm_db_log_info(DB_ID('PlantHistorian'))should never go backwards.
14 — Backup and recovery
Three layers to think about:
- Hyper-V VM-level backup. Windows Server Backup is free and works for single-host. Veeam Community Edition is free for up to 10 VMs and is what most plants use. Schedule full weekly, incremental nightly. Target a NAS on the management VLAN, not the same physical box.
- SQL Server native backup. Full database backup nightly, transaction log backup every 15 minutes during the day. Restore takes longer from VM snapshot alone than from SQL backups, because SQL knows how to roll forward.
- Config-level backup. The KEPServerEX project file, the SCADA project archive, AcSELerator RTAC project file. These are small and version-controllable. Push them to a Git repository on the engineering LAN or to the corporate file share. Restoring a plant from VHDX backup is hours; restoring from config-level backup onto a fresh OS is days. Both matter, for different recovery scenarios.
The most common backup failure is the discovery that the backup has been writing zeros for three months and nobody noticed. Once a quarter, restore a single VM from the latest backup onto a test partition. Boot it. Confirm SQL comes up and the database is consistent. If you can't do this exercise without taking the plant down, your DR plan does not work.
15 — Commissioning checklist
| Item | Verified |
|---|---|
| iDRAC on dedicated NIC, static IP, default password changed | ☐ |
| PERC RAID 10 healthy, BBU good, write-back enabled | ☐ |
| Windows Server 2022 installed, fully patched, host named | ☐ |
| Three virtual switches built; plant vSwitch has no host OS binding | ☐ |
| Hyper-V role installed; default VM and VHDX paths on data volume | ☐ |
| SQL01 VM up, SQL Server 2022 installed via config file, PlantHistorian DB created with pre-grown files | ☐ |
| KEP01 VM up, KEPServerEX installed with DNP Master Suite | ☐ |
| KEPServerEX OPC UA hardened: anonymous off, sign+encrypt on, real certificate, users created | ☐ |
| DNP3 channel and device configured, master/outstation addresses correct, unsolicited enabled | ☐ |
| Tag list imported or built; Quality Good on all live tags | ☐ |
| IDF or ODBC writing to PlantHistorian; first day's data visible in SQL | ☐ |
| SCADA workstation VM up, reads from KEP OPC UA and from SQL | ☐ |
| Linux utility VM up with intended role configured | ☐ |
| Time sync: host on substation NTP, VMs not double-syncing | ☐ |
| Veeam (or equivalent) backing up nightly; first restore tested | ☐ |
| KEP project file, SCADA project file, RTAC project file all in version control | ☐ |
| iDRAC alert path tested with a forced fan or PSU event | ☐ |
| BBU replacement on the shelf, NIC spares documented, RAID rebuild procedure printed and in the rack | ☐ |
→ Continue to SEL RTAC as Power Plant Controller · → N3uron MQTT bridge · → DNP3 Point List Design