Deploy an EDR Agent on Windows, macOS, and Linux Without Breaking Dev Tools
For developers and platform engineers rolling out an EDR agent to mixed OS fleets. This shows a safe deployment pattern, exact install and verification commands, and the exclusions and rollout checks that prevent broken compilers, package managers, containers, and local databases.
TL;DR — Roll out the EDR agent in audit/monitor-only mode first, then add explicit exclusions for build caches, package-manager stores, container runtimes, and local database directories before enabling prevention. The most common cause of developer breakage is scanning or blocking high-churn paths like
node_modules, Docker/container storage, Gradle/Maven caches, and language toolchains. Reading time: ~5 min
Goal
When you are done, the EDR agent is installed and running on Windows, macOS, and Linux endpoints, reporting healthy status to your management plane, and developer workflows like builds, package installs, containers, IDE indexing, and local databases still work at normal speed.
Prerequisites
- EDR admin access with permission to create policies, download installers, and view endpoint status
- A pilot group of 3-10 developer machines across Windows, macOS, and Linux
- Local admin/root access on test endpoints
- PowerShell 5.1+ on Windows — check with
powershell -NoProfile -Command "$PSVersionTable.PSVersion" - macOS 13+ or 14+ with Terminal and
profilesavailable — check withsw_vers - Linux with
systemdand eitherdpkgorrpm— check withps -p 1 -o comm=andcat /etc/os-release - Your vendor-specific installer URL or package file, plus the enrollment token / customer ID / site key required by your EDR
- A list of developer-heavy paths to exclude from on-access scanning or prevention policy
Steps
Step 1: Create a pilot policy in monitor-only mode
In your EDR admin console, create a new policy assigned only to the pilot group.
Use these literal settings where your vendor exposes them:
- Prevention/blocking:
DisabledorDetect only - On-access file scanning:
Enabled - Network containment/isolation:
Disabled - Script/macro blocking:
Audit only - USB/device control:
Disabled - Tamper protection:
Enabledonly if you already have a tested uninstall process
Add path exclusions before installing the agent.
{
"windows": [
"%USERPROFILE%\\.nuget\\packages",
"%USERPROFILE%\\.m2\\repository",
"%USERPROFILE%\\.gradle\\caches",
"%LOCALAPPDATA%\\npm-cache",
"%LOCALAPPDATA%\\Yarn\\Cache",
"%LOCALAPPDATA%\\pip\\Cache",
"%LOCALAPPDATA%\\Docker",
"C:\\ProgramData\\Docker",
"C:\\ProgramData\\containerd",
"C:\\src\\*\\node_modules",
"C:\\Users\\*\\AppData\\Local\\Temp"
],
"macos": [
"$HOME/.npm",
"$HOME/.cache/yarn",
"$HOME/.pnpm-store",
"$HOME/.m2/repository",
"$HOME/.gradle/caches",
"$HOME/Library/Caches/pip",
"$HOME/Library/Developer/Xcode/DerivedData",
"/Users/*/Projects/*/node_modules",
"/Users/*/.docker",
"/var/lib/docker",
"/var/lib/containerd"
],
"linux": [
"$HOME/.cache/pip",
"$HOME/.npm",
"$HOME/.pnpm-store",
"$HOME/.m2/repository",
"$HOME/.gradle/caches",
"/var/lib/docker",
"/var/lib/containerd",
"/var/lib/containers",
"/tmp",
"/home/*/src/*/node_modules"
]
}
What you should see: the new policy exists, is assigned only to pilot endpoints, and shows the exclusions above in the policy details.
Step 2: Validate the installer URL and enrollment token before touching endpoints
Run a HEAD request from any machine that has network access to the installer source.
curl -I "https://edr.example.com/agent/installer"
Expected success shape:
HTTP/2 200
content-type: application/octet-stream
content-length: 12345678
Common bad redirect shape:
HTTP/2 302
location: /login
content-type: text/html
If you get redirected to login, use a direct package URL or download the installer from the admin console first.
What you should see: HTTP/2 200 or HTTP/1.1 200 OK, not a redirect to a login page.
Step 3: Install on Windows
⚠️ Do this on a pilot machine first. Some EDRs require a reboot or briefly restart network filter drivers.
Download and install from an elevated PowerShell session. Replace the URL, package name, and enrollment property names with your vendor’s actual values.
$InstallerUrl = "https://edr.example.com/agent/windows/agent.msi"
$Out = "$env:TEMP\agent.msi"
Invoke-WebRequest -Uri $InstallerUrl -OutFile $Out
Start-Process msiexec.exe -Wait -PassThru -ArgumentList "/i `"$Out`" /qn /norestart CUSTOMER_ID=abc123 ENROLLMENT_TOKEN=token123" | Select-Object ExitCode
Get-Service | Where-Object {$_.Name -match 'agent|edr|sensor'} | Format-Table Name,Status,StartType
Expected success shape:
ExitCode
--------
0
Name Status StartType
---- ------ ---------
VendorAgent Running Automatic
What you should see: installer exit code 0 and an agent service in Running state.
Step 4: Install on macOS
If your vendor provides a .pkg, install it with installer. If it requires a profile for system extensions or network content filtering, deploy that MDM profile before this step.
curl -L -o /tmp/agent.pkg "https://edr.example.com/agent/macos/agent.pkg"
sudo installer -pkg /tmp/agent.pkg -target /
sudo launchctl list | grep -i 'agent\|edr\|sensor'
If you need to confirm a system extension approval problem:
systemextensionsctl list
Expected success shape:
installer: Package name is Vendor Agent
installer: The install was successful.
123 0 com.vendor.agent
What you should see: The install was successful and a loaded launch daemon or system extension entry.
Step 5: Install on Linux
For Debian/Ubuntu:
curl -L -o /tmp/agent.deb "https://edr.example.com/agent/linux/agent.deb"
sudo dpkg -i /tmp/agent.deb
sudo systemctl enable --now vendor-agent
sudo systemctl status vendor-agent --no-pager -l
For RHEL/Rocky/Alma/Fedora:
curl -L -o /tmp/agent.rpm "https://edr.example.com/agent/linux/agent.rpm"
sudo rpm -Uvh /tmp/agent.rpm
sudo systemctl enable --now vendor-agent
sudo systemctl status vendor-agent --no-pager -l
Expected success shape:
● vendor-agent.service - Vendor EDR Agent
Loaded: loaded (/usr/lib/systemd/system/vendor-agent.service; enabled)
Active: active (running)
What you should see: Active: active (running) from systemctl status.
Step 6: Run developer workflow smoke tests on each OS
Use commands that hit the paths you excluded.
node --version
npm cache verify
python3 -m pip cache dir || pip cache dir
docker version
docker run --rm alpine:3.20 echo ok
On Java machines:
mvn -q -version
gradle -v
On Windows, if Docker Desktop is used:
docker version
docker run --rm mcr.microsoft.com/powershell:nanoserver-ltsc2022 pwsh -c "Write-Host ok"
What you should see: package-manager cache commands return a path, and the container test prints ok without hangs or access-denied errors.
Step 7: Promote from audit to prevention only after pilot is clean
After 24-48 hours with no build failures, package-manager corruption, IDE hangs, or container slowdowns, edit the pilot policy and change:
- Prevention/blocking:
Enabled - Script/macro blocking:
Enabledif your org requires it - Network containment/isolation: leave
Disabledfor developer endpoints unless you have a tested incident workflow
Then assign the policy to the next batch.
What you should see: newly assigned endpoints check in under the updated policy, and no spike appears in blocked events for compiler, package-manager, or container processes.
Verify it works
Check all three layers: service health, console enrollment, and workflow health.
Service/process checks:
# macOS/Linux
ps aux | grep -i 'agent\|edr\|sensor' | grep -v grep
# Linux
systemctl is-active vendor-agent
# Windows
Get-Service | Where-Object {$_.Name -match 'agent|edr|sensor'}
Expected success shape:
active
Console check: in your EDR admin console, the endpoint should show Online, the correct hostname, the pilot policy name, and a last check-in within the last few minutes.
Workflow checks:
time npm ci
time docker run --rm alpine:3.20 true
time python3 -m pip install --user requests
Expected result: commands complete normally, with no Permission denied, Operation not permitted, file in use, quarantined, or unexplained multi-minute stalls.
Common pitfalls
Installer URL points to an authenticated web page, not the package
Mistake: using the copy-pasted browser URL from the admin console session.
Symptom: curl -I returns a redirect or HTML.
HTTP/2 302
location: /login
Fix: use a direct package URL or download the installer file first and distribute that file.
Prevention mode enabled before exclusions exist
Mistake: turning on blocking on day 1.
Symptom: npm ci, gradle build, Docker image pulls, or IDE indexing become extremely slow or fail with access errors.
Fix: switch the policy to Detect only, add the cache/runtime exclusions, then retest before re-enabling prevention.
macOS system extension or network filter approval is missing
Mistake: installing the package without the required MDM profile or local approval.
Symptom: install says success, but the sensor never becomes fully healthy in the console.
Fix: deploy the vendor’s approved system extension / network content filter profile, then reinstall or restart the agent.
Linux package installs but service never starts
Mistake: package installed, but the host is missing a required kernel module, library, or systemd unit dependency.
Symptom: systemctl status vendor-agent shows failed or crash-looping.
Fix: read the exact error with journalctl -u vendor-agent -n 100 --no-pager, install the missing dependency, then sudo systemctl restart vendor-agent.
Excluding the wrong path level
Mistake: excluding the package-manager binary but not its cache/store directories.
Symptom: the command launches, but installs and builds are still slow because every extracted file is scanned.
Fix: exclude the high-churn directories like .m2/repository, .gradle/caches, .pnpm-store, Docker/containerd storage, and project node_modules paths.
Testing only service status, not actual developer workflows
Mistake: declaring success because the agent process is running.
Symptom: support tickets arrive later for slow builds, broken local DBs, or container failures.
Fix: run one real build, one package install, and one container start on every pilot OS before broad rollout.
This article was written by an AI system and published pending human review. Verify anything you intend to act on.
Have a project in mind?
Get an instant AI price estimate for it, or talk directly to our team.
One email a month on what we learn building with AI