We’ve all been there. You deploy a fresh Veeam Backup & Replication server, everything looks green, and the backups start flying. Then, a few days later, you notice the console is sluggish. Maybe a merge operation takes three times longer than it should, or a SureBackup job times out for no obvious reason.
You start investigating, open Task Manager, and spot high CPU usage. Checking the processes, you see Microsoft Defender consuming a large chunk of your resources. Immediately it becomes clear that it’s scanning something it shouldn’t, so now it’s time to check what exclusions you should’ve had in place.
Antivirus software and backup infrastructure don’t always get along. Backup tools do exactly what AV is built to stop. They open thousands of files, read them fast, touch huge archives, and push a lot of traffic. When Microsoft Defender decides to real-time scan a 4TB .vbk file every time Veeam touches it, performance doesn’t just dip, it falls off a cliff. And of course, Defender finds nothing. It just slows everything down while looking.
I’ve seen brand new VBR servers feel like they’ve been built on 10-year-old hardware. Attempts to browse backups freeze and take forever. I’ve clicked through the Windows Security UI 57 times (yes, I counted) to manually add every path from Veeam KB1999. It’s the list: every process, folder, and file extension to allowlist. Doing it by hand is tedious, error-prone, and a waste of time I’d rather spend on actual backup problems.
So I built Set-VeeamDefenderExclusions.ps1.
Why Another Script?#
I didn’t want to reinvent the wheel. Before writing anything, I looked at what the community already had. Most existing solutions fall into two main buckets:
Current Scripting Gaps#
| Solution Type | Pros | Cons |
|---|---|---|
| “Quick and Dirty” | Fast to run; simple logic. | No idempotency; misses newer components (PostgreSQL) or version-specific paths. |
| “Interactive” Menus | Comprehensive; good for one-off manual work. | Bad for automation; can’t be used in deployment pipelines or RMM tools because they require user input. |
I needed something in the middle: fully scriptable, safe to run multiple times, and smart enough to understand a server’s role.
The Challenge: It’s Not Just One List#
Veeam infrastructure is modular. A one-size-fits-all exclusion list adds unnecessary noise and reduces security. For example, a dedicated proxy doesn’t need exclusions for Enterprise Manager, so why add them? The script needed to understand roles.
Set-VeeamDefenderExclusions.ps1#
This script is infrastructure-aware. You declare what the server does and it builds the exclusion list accordingly. The full code and documentation are on GitHub:
1. Role-Based Configuration#
You tell the script what the server is, and it builds exclusions dynamically.
.\Set-VeeamDefenderExclusions.ps1 -Role BackupServer, BackupInfrastructureAvailable roles:
- BackupServer: Veeam Backup & Replication Server (catalog folders, configuration database paths)
- EnterpriseManager: Veeam Backup Enterprise Manager (installation folders, catalog, logs)
- Console: Veeam Backup & Replication Console (installation folders, temp directories, per-user data)
- ProtectedGuest: Guest OS of protected Windows VMs (Application-Aware Processing, Guest File System Indexing, SQL Log Backup, Persistent Agent; requires feature flags like
-EnableGuestProcessing,-EnableSQLLogBackup) - RestoreTarget: Guest OS used as file-level restore target (temporary Veeam VSS support folders)
- BackupInfrastructure: Proxy, Repository, WAN Accelerator, Mount Server, etc.
2. Intelligent Auto-Detection#
Hardcoded paths don’t age well. The script queries the registry for the real install paths for the VBR Catalog and NFS Root. It also runs a package detection scan for components like WAN Accelerator or CDP Proxy.
If it finds WAN Accelerator, it refuses to continue until you define the cache path. I’m not letting you accidentally scan 500GB of dedupe data. It also handles version differences (v12 vs. v13) and correct x86/x64 transport paths.
3. PostgreSQL Awareness#
With PostgreSQL now the default, database exclusions matter. The -IncludePostgreSQL switch finds the version, locates the data directory, and excludes the process path.
4. Process Scanning#
Instead of maintaining a static list of .exe names, the script scans the Veeam installation directories and adds every executable it finds. This makes it resilient against minor updates and new helper tools.
5. Safety First: Idempotency and WhatIf#
Before adding anything, the script checks Get-MpPreference. If an exclusion already exists, it skips it. This keeps logs clean and avoids duplicate entries. It also supports -WhatIf so you can preview changes.
.\Set-VeeamDefenderExclusions.ps1 -Role BackupServer -IncludePostgreSQL -WhatIfRequirements#
Before running the script, keep these “gotchas” in mind:
- Run PowerShell as Administrator - The
Add-MpPreferencecmdlets require elevated permissions. - Microsoft Defender must be active - The script uses native Defender cmdlets that require the WinDefend service to be running.
- Policy-managed environments - If exclusions are managed via GPO, Intune, or Microsoft Defender for Endpoint policies, local changes may fail or revert. Check with your security team if you’re unsure.
How to Use It#
I’ve designed the syntax to be simple and flexible depending on your specific deployment needs.
Standard All-In-One VBR server:
.\Set-VeeamDefenderExclusions.ps1 -Role BackupServer -IncludePostgreSQLRepository server:
The -IncludeRepositoryExtensions switch adds file type exclusions (.vbk, .vib, etc.) that repositories need but proxies don’t. Note that these are global extension exclusions, not scoped to specific folders. For more targeted exclusions, use the -BackupFilesPath parameter to scope exclusions to your repository directories.
.\Set-VeeamDefenderExclusions.ps1 -Role BackupInfrastructure -IncludeRepositoryExtensionsUndo everything:
The -Remove switch reverses the logic. It removes only the Veeam-specific exclusions defined by the roles you specify, leaving other exclusions alone.
.\Set-VeeamDefenderExclusions.ps1 -Role BackupServer -RemoveYou can verify exclusions were added by checking: (Get-MpPreference).ExclusionPath
Making It Work#
I’ve been through enough “why is this merge taking 6 hours?” moments to know that manual exclusion lists don’t scale. You make the list once, miss something, and spend the next three months troubleshooting intermittent slowdowns.
Run it once during deployment. Run it again after updates. The idempotency means you can safely include it in your deployment automation or post-upgrade runbooks. We trust Veeam to protect our data, so the environment needs to let it do its job.
If you hit an edge case I missed, open an issue on GitHub or leave a comment here. I want this to work everywhere.




