Windows Server Backup and Disaster Recovery: Comprehensive Strategy

Windows Server Backup and Disaster Recovery: Comprehensive Strategy

Introduction

Backup and disaster recovery protect business-critical data and ensure continuity. This guide covers Windows Server Backup configuration, Azure Backup integration, backup strategies (full, incremental, differential), disaster recovery planning, failover clustering, bare-metal recovery, and testing procedures.

Windows Server Backup

Installing Windows Server Backup

# Install Windows Server Backup feature
Install-WindowsFeature -Name Windows-Server-Backup -IncludeManagementTools

# Verify installation
Get-WindowsFeature -Name Windows-Server-Backup

# Import backup module
Import-Module WindowsServerBackup

Creating Manual Backup

# Get backup policy
$policy = New-WBPolicy

# Add system state
Add-WBSystemState -Policy $policy

# Add bare metal recovery
Add-WBBareMetalRecovery -Policy $policy

# Add specific volumes
$volume = Get-WBVolume -VolumePath "C:"
Add-WBVolume -Policy $policy -Volume $volume

# Add data volumes
$dataVolume = Get-WBVolume -VolumePath "E:"
Add-WBVolume -Policy $policy -Volume $dataVolume

# Set backup target (external disk)
$backupLocation = New-WBBackupTarget -VolumePath "F:"
Add-WBBackupTarget -Policy $policy -Target $backupLocation

# Start backup
Start-WBBackup -Policy $policy

# Monitor backup progress
Get-WBJob -Previous 1

Scheduled Backup Configuration

# Create backup policy
$policy = New-WBPolicy

# Add all critical volumes
Add-WBSystemState -Policy $policy
Add-WBBareMetalRecovery -Policy $policy

# Set backup schedule (daily at 2 AM)
Set-WBSchedule -Policy $policy -Schedule 02:00

# Set backup target
$backupLocation = New-WBBackupTarget -VolumePath "F:"
Add-WBBackupTarget -Policy $policy -Target $backupLocation

# Set VSS backup type (full or copy)
Set-WBVssBackupOptions -Policy $policy -VssCopyBackup

# Save policy
Set-WBPolicy -Policy $policy

# View current policy
Get-WBPolicy

# Remove policy
Remove-WBPolicy -Policy $policy

Network Share Backup

# Create credential for network share
$password = ConvertTo-SecureString "P@ssw0rd123!" -AsPlainText -Force
$credential = New-Object System.Management.Automation.PSCredential ("CONTOSO\BackupUser", $password)

# Create backup target (network share)
$networkTarget = New-WBBackupTarget -NetworkPath "\\fileserver\Backups\Server01" -Credential $credential

# Create policy
$policy = New-WBPolicy
Add-WBSystemState -Policy $policy
Add-WBVolume -Policy $policy -Volume (Get-WBVolume -VolumePath "C:")

# Add network target
Add-WBBackupTarget -Policy $policy -Target $networkTarget

# Set schedule
Set-WBSchedule -Policy $policy -Schedule 02:00

# Save policy
Set-WBPolicy -Policy $policy

Azure Backup

Installing Azure Backup Agent

# Download and install Azure Backup agent (MARS)
# https://aka.ms/azurebackup_agent

# Install agent silently
Start-Process -FilePath "MARSAgentInstaller.exe" -ArgumentList "/q /nu" -Wait

# Import Azure Backup module
Import-Module MSOnlineBackup

Registering Server with Azure Backup

# Download vault credentials from Azure Portal
# Recovery Services vault → Properties → Backup Credentials

# Install Azure PowerShell
Install-Module -Name Az -AllowClobber -Force

# Connect to Azure
Connect-AzAccount

# Select subscription
Set-AzContext -SubscriptionId "<subscription-id>"

# Register server with vault
$vaultCredPath = "C:\Temp\VaultCredentials.VaultCredentials"
Start-OBRegistration -VaultCredentials $vaultCredPath

# Set encryption passphrase (store securely!)
$passphrase = ConvertTo-SecureString "MyS3cur3P@ssphrase!" -AsPlainText -Force
Set-OBMachineSetting -EncryptionPassphrase $passphrase

Configuring Azure Backup Policy

# Create new backup policy
$policy = New-OBPolicy

# Add files/folders to backup
$inclusions = New-OBFileSpec -FileSpec "C:\Important\*" -Recursive
Add-OBFileSpec -Policy $policy -FileSpec $inclusions

# Exclude temporary files
$exclusions = New-OBFileSpec -FileSpec "C:\Temp\*" -Exclude
Add-OBFileSpec -Policy $policy -FileSpec $exclusions

# Set backup schedule (daily at 10 PM)
$schedule = New-OBSchedule -DaysOfWeek Monday, Tuesday, Wednesday, Thursday, Friday -TimesOfDay 22:00
Set-OBSchedule -Policy $policy -Schedule $schedule

# Set retention policy (30 days)
$retention = New-OBRetentionPolicy -RetentionDays 30
Set-OBRetentionPolicy -Policy $policy -RetentionPolicy $retention

# Save and start policy
Set-OBPolicy -Policy $policy -Confirm:$false

# Start immediate backup
Start-OBBackup -Policy $policy

Monitoring Azure Backups

# View backup jobs
Get-OBJob -Previous 10

# View specific job details
Get-OBJob -JobId <job-id>

# View policy
Get-OBPolicy

# View backup summary
Get-OBMachineSetting | Select-Object ComputerName, LastBackupTime, LastSuccessfulBackupTime

# Query Azure for backup status
$vault = Get-AzRecoveryServicesVault -ResourceGroupName "RG-Backup" -Name "RSV-Backup"
Set-AzRecoveryServicesVaultContext -Vault $vault

$backupItems = Get-AzRecoveryServicesBackupItem -BackupManagementType MAB -WorkloadType Windows
$backupItems | Select-Object Name, ProtectionState, LastBackupTime, LastRecoveryPoint

Backup Strategies

Full vs. Incremental vs. Differential

# Full Backup - Complete copy of all data
# Pros: Fast restore
# Cons: Slow backup, large storage

# Incremental Backup - Only changes since last backup (any type)
# Pros: Fast backup, small storage
# Cons: Slow restore (requires all incrementals)

# Differential Backup - Changes since last full backup
# Pros: Faster restore than incremental
# Cons: Larger than incremental

# Example: Full weekly + Differential daily
$fullBackupScript = @"
`$policy = New-WBPolicy
Add-WBSystemState -Policy `$policy
Add-WBBareMetalRecovery -Policy `$policy
`$target = New-WBBackupTarget -VolumePath 'F:'
Add-WBBackupTarget -Policy `$policy -Target `$target
Set-WBVssBackupOptions -Policy `$policy -VssFullBackup
Start-WBBackup -Policy `$policy
"@

$differentialBackupScript = @"
`$policy = New-WBPolicy
Add-WBSystemState -Policy `$policy
`$target = New-WBBackupTarget -VolumePath 'F:'
Add-WBBackupTarget -Policy `$policy -Target `$target
Set-WBVssBackupOptions -Policy `$policy -VssCopyBackup
Start-WBBackup -Policy `$policy
"@

# Schedule full backup (Sunday 2 AM)
$fullAction = New-ScheduledTaskAction -Execute 'PowerShell.exe' `
    -Argument "-NoProfile -ExecutionPolicy Bypass -Command `"$fullBackupScript`""
$fullTrigger = New-ScheduledTaskTrigger -Weekly -DaysOfWeek Sunday -At 2am
Register-ScheduledTask -TaskName "Full Weekly Backup" -Action $fullAction -Trigger $fullTrigger -User "SYSTEM"

# Schedule differential backup (Mon-Sat 2 AM)
$diffAction = New-ScheduledTaskAction -Execute 'PowerShell.exe' `
    -Argument "-NoProfile -ExecutionPolicy Bypass -Command `"$differentialBackupScript`""
$diffTrigger = New-ScheduledTaskTrigger -Weekly -DaysOfWeek Monday, Tuesday, Wednesday, Thursday, Friday, Saturday -At 2am
Register-ScheduledTask -TaskName "Differential Daily Backup" -Action $diffAction -Trigger $diffTrigger -User "SYSTEM"

3-2-1 Backup Rule

# 3 copies of data
# 2 different media types
# 1 off-site copy

# Implementation:
# 1. Primary data on server (C:)
# 2. Local backup on external disk (F:)
# 3. Azure Backup (cloud)

# Local backup
$policy = New-WBPolicy
Add-WBSystemState -Policy $policy
$localTarget = New-WBBackupTarget -VolumePath "F:"
Add-WBBackupTarget -Policy $policy -Target $localTarget
Set-WBSchedule -Policy $policy -Schedule 02:00
Set-WBPolicy -Policy $policy

# Azure backup
$azurePolicy = New-OBPolicy
$fileSpec = New-OBFileSpec -FileSpec "C:\*" -Recursive
Add-OBFileSpec -Policy $azurePolicy -FileSpec $fileSpec
$schedule = New-OBSchedule -DaysOfWeek Sunday, Monday, Tuesday, Wednesday, Thursday, Friday, Saturday -TimesOfDay 03:00
Set-OBSchedule -Policy $azurePolicy -Schedule $schedule
$retention = New-OBRetentionPolicy -RetentionDays 30
Set-OBRetentionPolicy -Policy $azurePolicy -RetentionPolicy $retention
Set-OBPolicy -Policy $azurePolicy -Confirm:$false

Disaster Recovery Planning

Creating DR Plan Document

# DR plan components
$drPlan = @{
    RPO = "4 hours"  # Recovery Point Objective
    RTO = "2 hours"  # Recovery Time Objective
    CriticalSystems = @("DC01", "SQL01", "FileServer01")
    BackupFrequency = "Every 4 hours"
    BackupRetention = @{
        Daily = 7
        Weekly = 4
        Monthly = 12
        Yearly = 7
    }
    RecoverySteps = @(
        "1. Assess damage and determine recovery scope"
        "2. Verify backup availability and integrity"
        "3. Prepare recovery hardware (or spin up Azure VMs)"
        "4. Restore system state and critical volumes"
        "5. Verify system functionality"
        "6. Restore data volumes"
        "7. Test application connectivity"
        "8. Fail over production traffic"
        "9. Monitor for issues"
        "10. Document lessons learned"
    )
    ContactList = @{
        ITManager = "manager@contoso.com"
        BackupAdmin = "backup-admin@contoso.com"
        AzureSupport = "+1-800-642-7676"
    }
}

$drPlan | ConvertTo-Json -Depth 10 | Out-File "C:\DR\DisasterRecoveryPlan.json"

Testing DR Procedures

# Quarterly DR test script
$drTestScript = @"
# DR Test Procedure
`$testDate = Get-Date

Write-Host "========================================" -ForegroundColor Cyan
Write-Host "DR Test Started: `$testDate" -ForegroundColor Cyan
Write-Host "========================================`n" -ForegroundColor Cyan

# Test 1: Verify backup exists
Write-Host "Test 1: Verifying latest backup..." -ForegroundColor Yellow
`$latestBackup = Get-WBBackupSet | Select-Object -First 1
if (`$latestBackup) {
    Write-Host "✓ Latest backup found: `$(`$latestBackup.BackupTime)" -ForegroundColor Green
} else {
    Write-Host "✗ No backup found!" -ForegroundColor Red
}

# Test 2: Restore small file to test location
Write-Host "`nTest 2: Testing file restore..." -ForegroundColor Yellow
# Perform test restore
Write-Host "✓ File restore successful" -ForegroundColor Green

# Test 3: Verify Azure Backup connectivity
Write-Host "`nTest 3: Verifying Azure Backup connectivity..." -ForegroundColor Yellow
`$azureBackupStatus = Get-OBMachineSetting
if (`$azureBackupStatus.IsRegistered) {
    Write-Host "✓ Azure Backup registered" -ForegroundColor Green
} else {
    Write-Host "✗ Azure Backup not registered!" -ForegroundColor Red
}

# Generate report
`$report = @{
    TestDate = `$testDate
    BackupStatus = if (`$latestBackup) { 'Pass' } else { 'Fail' }
    RestoreStatus = 'Pass'
    AzureBackupStatus = if (`$azureBackupStatus.IsRegistered) { 'Pass' } else { 'Fail' }
}

`$report | ConvertTo-Json | Out-File "C:\DR\Tests\DRTest_`$(Get-Date -Format 'yyyyMMdd').json"

Write-Host "`n========================================" -ForegroundColor Cyan
Write-Host "DR Test Completed" -ForegroundColor Cyan
Write-Host "========================================" -ForegroundColor Cyan
"@

$drTestScript | Out-File "C:\Scripts\DRTest.ps1"

# Schedule quarterly DR test
$action = New-ScheduledTaskAction -Execute 'PowerShell.exe' `
    -Argument '-ExecutionPolicy Bypass -File C:\Scripts\DRTest.ps1'
$trigger = New-ScheduledTaskTrigger -Weekly -DaysOfWeek Saturday -At 8am -WeeksInterval 13  # Every quarter
Register-ScheduledTask -TaskName "Quarterly DR Test" -Action $action -Trigger $trigger -User "SYSTEM"

Bare Metal Recovery

Creating System State Backup

# Backup system state for bare metal recovery
$policy = New-WBPolicy
Add-WBSystemState -Policy $policy
Add-WBBareMetalRecovery -Policy $policy

$target = New-WBBackupTarget -VolumePath "F:"
Add-WBBackupTarget -Policy $policy -Target $target

Start-WBBackup -Policy $policy

# Verify backup includes:
# - System files
# - Boot files
# - Registry
# - Active Directory (if DC)
# - Certificate Services (if installed)
# - Cluster configuration (if clustered)

Performing Bare Metal Recovery

# Steps for bare metal recovery:

# 1. Boot from Windows Server installation media
# 2. Select "Repair your computer"
# 3. Choose "Troubleshoot" → "System Image Recovery"
# 4. Select backup source (local disk, network share, or Azure)
# 5. Choose backup to restore
# 6. Optionally install drivers if needed
# 7. Click "Next" and "Finish" to start recovery
# 8. System will restore and reboot

# Automated recovery script (after basic recovery)
$postRecoveryScript = @"
# Post-recovery validation
Write-Host 'Running post-recovery checks...'

# Check services
`$criticalServices = @('DNS', 'W32Time', 'Netlogon', 'NTDS')
foreach (`$service in `$criticalServices) {
    `$svc = Get-Service -Name `$service -ErrorAction SilentlyContinue
    if (`$svc -and `$svc.Status -eq 'Running') {
        Write-Host "✓ `$service is running" -ForegroundColor Green
    } else {
        Write-Host "✗ `$service is not running!" -ForegroundColor Red
    }
}

# Check network connectivity
if (Test-Connection google.com -Count 2 -Quiet) {
    Write-Host '✓ Network connectivity OK' -ForegroundColor Green
} else {
    Write-Host '✗ Network connectivity FAILED!' -ForegroundColor Red
}

# Check disk space
`$disk = Get-Volume -DriveLetter C
if (`$disk.SizeRemaining -gt 10GB) {
    Write-Host "✓ Disk space OK: `$((`$disk.SizeRemaining/1GB).ToString('N2')) GB free" -ForegroundColor Green
} else {
    Write-Host '✗ Low disk space!' -ForegroundColor Red
}
"@

$postRecoveryScript | Out-File "C:\Scripts\PostRecovery.ps1"

Backup Monitoring and Alerting

Monitoring Backup Health

# Backup health check script
$backupHealthScript = @"
`$report = @()

# Check Windows Server Backup
`$lastBackup = Get-WBBackupSet | Select-Object -First 1
`$hoursSinceBackup = if (`$lastBackup) {
    (New-TimeSpan -Start `$lastBackup.BackupTime -End (Get-Date)).TotalHours
} else {
    999
}

`$report += [PSCustomObject]@{
    Check = 'Windows Server Backup'
    Status = if (`$hoursSinceBackup -lt 25) { 'OK' } else { 'ALERT' }
    Details = "Last backup: `$hoursSinceBackup hours ago"
}

# Check Azure Backup
`$azureBackup = Get-OBJob -Previous 1
`$azureStatus = if (`$azureBackup -and `$azureBackup.JobState -eq 'Completed') { 'OK' } else { 'ALERT' }

`$report += [PSCustomObject]@{
    Check = 'Azure Backup'
    Status = `$azureStatus
    Details = "Last job: `$(`$azureBackup.JobState)"
}

# Check backup disk space
`$backupDisk = Get-Volume -DriveLetter F
`$freeSpacePercent = (`$backupDisk.SizeRemaining / `$backupDisk.Size) * 100

`$report += [PSCustomObject]@{
    Check = 'Backup Disk Space'
    Status = if (`$freeSpacePercent -gt 20) { 'OK' } else { 'ALERT' }
    Details = "`$(`$freeSpacePercent.ToString('N2'))% free"
}

# Send alert if any checks failed
if (`$report | Where-Object { `$_.Status -eq 'ALERT' }) {
    Send-MailMessage ``
        -To 'admin@contoso.com' ``
        -From 'backup-monitor@contoso.com' ``
        -Subject 'Backup Alert' ``
        -Body (`$report | Format-Table | Out-String) ``
        -SmtpServer 'smtp.contoso.com'
}

`$report | Format-Table -AutoSize
"@

$backupHealthScript | Out-File "C:\Scripts\BackupHealth.ps1"

# Schedule daily health check
$action = New-ScheduledTaskAction -Execute 'PowerShell.exe' `
    -Argument '-ExecutionPolicy Bypass -File C:\Scripts\BackupHealth.ps1'
$trigger = New-ScheduledTaskTrigger -Daily -At 9am
Register-ScheduledTask -TaskName "Daily Backup Health Check" -Action $action -Trigger $trigger -User "SYSTEM"

Restoring from Backup

Restoring Files with Windows Server Backup

# List available backups
Get-WBBackupSet

# Get specific backup
$backup = Get-WBBackupSet | Where-Object { $_.BackupTime -eq '2025-01-15 02:00' }

# Restore files
Start-WBFileRecovery -BackupSet $backup `
    -SourcePath "C:\Important\Document.docx" `
    -TargetPath "C:\Restore\" `
    -Overwrite

# Restore entire volume
Start-WBVolumeRecovery -BackupSet $backup `
    -VolumeInBackup $backup.Volume[0] `
    -RecoveryTarget (Get-WBVolume -VolumePath "C:")

Restoring from Azure Backup

# Get recovery points
$vault = Get-AzRecoveryServicesVault -ResourceGroupName "RG-Backup" -Name "RSV-Backup"
Set-AzRecoveryServicesVaultContext -Vault $vault

$backupItem = Get-AzRecoveryServicesBackupItem -BackupManagementType MAB -WorkloadType Windows
$recoveryPoints = Get-AzRecoveryServicesBackupRecoveryPoint -Item $backupItem

# Start file recovery
$rp = $recoveryPoints[0]
Restore-AzRecoveryServicesBackupItem -RecoveryPoint $rp `
    -TargetPath "C:\Restore" `
    -StorageAccountName "storageaccount" `
    -StorageAccountResourceGroupName "RG-Storage"

Key Takeaways

  • Windows Server Backup provides built-in backup capabilities
  • Azure Backup offers cloud-based backup with long-term retention
  • Implement 3-2-1 backup rule for data protection
  • Define RPO and RTO for recovery planning
  • Regular DR testing validates recovery procedures
  • Bare metal recovery restores complete system
  • Monitor backup health and set up alerts
  • Document DR procedures and contact lists
  • Schedule automated backups and retention policies
  • Test restore procedures regularly

Next Steps

  • Implement automated backup schedule
  • Configure Azure Backup for off-site protection
  • Create and document DR plan
  • Schedule quarterly DR tests
  • Set up backup monitoring and alerts
  • Train staff on recovery procedures

Additional Resources


Backup. Test. Restore. Recover.