Skip to content

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) report real_time_protection_available: true with an ebpf sensor.

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.

GroupHostsNotes
docker_serversjean, connie, eren, armin, mikasa, sasha (+ nidavellir via docker_rootless)rootful/rootless split matters for any future exclusion
backup_serversbackup1, backup2RTP over bulk borg I/O still unmeasured through a client push window
k0s_cluster3 controllers + 8 workerswatch kubectl exec -it interactivity + etcd fsync on controllers (the failure shape that retired Falcon)
haproxy_serversatlas, prometheus, epimetheusdisk-quiet; each is a VRRP master, so serial: 1 matters
lamp_databasesizanami, izanagilikeliest tier to need an exclusion (/var/lib/mysql on a 20GiB block volume); measure unexcluded first
idm_servershuginn, muninnthe 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:

Terminal window
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_sensor role is remove-only (tasks/remove.yml), called by mde_agent before install (mde_installer.sh aborts on a conflicting fanotify holder) and by playbooks/ops/remove-falcon-sensor.yaml. There is no install path.
  • Tenable Nessus — fleet-wide (nessus_agent_enabled: true in group_vars/all.yaml), containers included; it has no kernel-sensor constraint. Link key in vars/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 mdatp or mde_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.