EDR posture — MDE + Nessus
The single source of truth for which hosts carry which security agents and why. Group_vars comments state each group’s local facts and point here; this page holds the fleet-wide picture so it isn’t retold per file.
The one rule: MDE is a VM-only target
Every host MDE protects is a virtual-machine class (opentofu/fleet.tf
fleet_resource_class_spec). The 17 LXC system containers cannot carry it —
measured, not assumed:
uxie(container) installed and onboarded cleanly — licensed, org_id set, tag applied,antivirus_enforcement_level=real_time [managed], no conflicting applications — and protected nothing:real_time_protection_available: false,supplementary_events_subsystem: "no_supplementary_sensor".- VMs (
jean,levi) reportreal_time_protection_available: truewith anebpfsensor.
A system container shares the IncusOS host’s kernel, so MDE’s RTP sensor
(fanotify/eBPF) has nothing of its own to hook. The failure mode is not a
clean abort — it is an agent that onboards, reports licensed and healthy, and
protects nothing. That is why both the mde_agent role’s final assert and the
security_agents healthcheck require real_time_protection_available (the
sensor actually attached), not just real_time_protection_enabled (the policy
asked for it). The two fields diverging is the signal, on any host type.
The container half of the fleet — caddies, DNS, step-ca, garage, apt proxies, oci mirror, valkey — gets its EDR coverage (or doesn’t) at the IncusOS host layer. That is an ITSO/CyOps conversation, not a toggle in this repo.
Who is armed
mde_agent_enabled: true at group scope; the role self-gates, so unarmed
hosts are a no-op even when a play targets them.
| Group | Hosts | Notes |
|---|---|---|
docker_servers | jean, connie, eren, armin, mikasa, sasha (+ nidavellir via docker_rootless) | rootful/rootless split matters for any future exclusion |
backup_servers | backup1, backup2 | RTP over bulk borg I/O still unmeasured through a client push window |
k0s_cluster | 3 controllers + 8 workers | watch kubectl exec -it interactivity + etcd fsync on controllers (the failure shape that retired Falcon) |
haproxy_servers | atlas, prometheus, epimetheus | disk-quiet; each is a VRRP master, so serial: 1 matters |
lamp_databases | izanami, izanagi | likeliest tier to need an exclusion (/var/lib/mysql on a 20GiB block volume); measure unexcluded first |
idm_servers | huginn, muninn | the fleet IdP — gates all SSO, so a high-value endpoint; HA pair, so serial: 1 like the VRRP masters; kanidmd is disk-quiet, no exclusion expected |
That is 27 of the fleet’s 28 VMs. Not armed: logi (gpu class; in no group
beyond incus_instances — arm per-host when reachable).
Armed is not onboarded. Arming means the next baseline run that reaches the
host installs Defender, in whatever order the play gets there. Roll out with
the ops playbook instead — serial: 1, health assert between hosts:
ansible-playbook playbooks/ops/install-mde-agent.yaml -e mde_fleet=<host-or-group>Verify fleet-wide with make healthcheck TAGS=security-agents — the
mdatp onboarded row reports rtp=<enabled>/<available> and the sensor name.
Exclusions policy
None configured anywhere, deliberately: measure unexcluded first, or the cost
of the migration is never known. Known levers when data says otherwise
(mde_agent_exclusions in roles/mde_agent/defaults/main.yaml, applied via
the managed profile):
/var/lib/mysql— lamp_databases (AV-over-InnoDB latency)/var/lib/k0s/etcd,/var/lib/k0s/containerd— k0s controllers/workers- docker:
/var/lib/docker(rootful) vs the moby-home store (rootless) — an exclusion for one does not cover the other
The other agents
- CrowdStrike Falcon — decommissioned. The
falcon_sensorrole is remove-only (tasks/remove.yml), called bymde_agentbefore install (mde_installer.sh aborts on a conflicting fanotify holder) and byplaybooks/ops/remove-falcon-sensor.yaml. There is no install path. - Tenable Nessus — fleet-wide (
nessus_agent_enabled: trueingroup_vars/all.yaml), containers included; it has no kernel-sensor constraint. Link key invars/security-agents.sops.yaml.
Open items
- uxie cleanup: mdatp is still installed there from the container
experiment and reports into the tenant as a device that looks protected.
Remove it (
apt purge mdatpormde_installer.sh --remove) and have CyOps offboard the device record. - logi: unreachable at last healthcheck; arm + onboard once it’s back.
- Measurements owed: backup tier through a client push window; lamp query latency before/after; k0s exec interactivity under load.