Getting Defender for Endpoint onto Ubuntu 26.04 (When Microsoft Says It Can't)

I wanted Microsoft Defender for Endpoint on the Ubuntu node that runs my k3s homelab. The node is on 26.04 — the newest LTS — and Microsoft’s supported list for Defender on Linux stops at 24.04. That’s not a hard block, it’s a “you’re on your own” warning, and on a homelab I’m fine being on my own. So I ran the deployment tool anyway.

It does install. But it fought me in three specific ways, none of which the docs mention, and two of which are the tool actively getting in its own way. If you’re onboarding a too-new Ubuntu — or you just want to understand why the Defender deployment tool can fail with an error that has nothing to do with the real problem — here’s the whole run.

The portal flow has changed

First, a small thing that’ll trip you up before you start: the onboarding page in the Defender portal isn’t what most guides show. There’s no “Linux Server” option any more. It’s now System → Settings → Endpoints → Device management → Onboarding, the operating-system dropdown just says Linux, and instead of a “deployment method” you get a set of download buttons. The current recommendation is the Defender deployment tool — one package that installs and onboards. Grab that (GatewayLinuxDefenderDeploymentTool.zip).

The prerequisite check is honest, at least

Extract it, and the first useful thing the tool does is a --pre-req run:

text
[v] detected: ubuntu 26.04 resolute (debian)
[v] scaled: 18.04
[!] Warning: The OS ubuntu 26.04 (x86_64) is not officially supported.
[v] All prerequisite passed

So it knows it’s on unsupported ground, quietly decides to treat 26.04 as an 18.04 baseline (scaled: 18.04 — remember that line, it matters later), warns you, and passes. Fair enough. Onward.

Red herring #1: no unzip

Minimal Ubuntu doesn’t ship unzip, so the extract step just dies with Command 'unzip' not found. Two-second fix (sudo apt install -y unzip), but worth flagging because it’s the first of several things that look like a Defender problem and aren’t.

Red herring #2: the “apt is busy” that never clears

This one’s my favourite, because I did it to myself and it’s a genuinely good lesson. apt was briefly locked by unattended-upgrades, so I wrote a wait loop that watched for the process to finish. It never finished. The loop ran for minutes against a lock that was actually free.

The cause: I checked for the process with pgrep -x unattended-upgr. But Linux truncates process names (comm) to 15 characters, and there’s a permanently-running daemon called unattended-upgrade-shutdown --wait-for-signal whose name truncates to exactly unattended-upgr. My check matched that — a process that sits alive for the whole uptime — so it could never exit, no matter what apt was doing.

The lesson: don’t infer apt’s state from a process name. Check the lock itself:

bash
sudo fuser /var/lib/dpkg/lock-frontend   # silent = free

If that’s silent, apt is free, whatever pgrep thinks.

Bug #1: the GPG key fetch dies with exit 127

Now the real install. It gets partway and stops dead:

text
[>] configuring the repository
[>] GPG key check: packages.microsoft.com
[x] unable to fetch the gpg key (exit code: 127)
[x] Installer script error

Exit 127 is “command not found.” The tool, running in its 18.04-scaled mode, tries to add Microsoft’s signing key the old way — and the old way used apt-key, which modern Ubuntu removed years ago. So the command it reaches for simply isn’t there, and it bails before installing anything. That’s why mdatp doesn’t exist afterwards: it never got that far.

Bug #2: the tool clobbers its own repo

Knowing the key handling was the problem, I set up the Microsoft repo correctly by hand — imported the key to a keyring and pointed the source at it — and re-ran with --use-local-repo to tell the tool to use what was already there. New error:

text
[!] unable to refresh the repos properly (exit code: 100)
[x] unable to install MDE (exit code: 100)

Exit 100 is apt failing. And here’s the kicker — when I looked at what my Microsoft source actually said now, the tool’s first run had overwritten it:

text
deb [arch=amd64] https://packages.microsoft.com/ubuntu/18.04/prod bionic main

It had replaced my good, key-referenced 24.04 entry with an 18.04 “bionic” one that has no signed-by= clause at all. So apt couldn’t verify it:

text
Err: https://packages.microsoft.com/ubuntu/18.04/prod bionic InRelease
  The following signatures couldn't be verified: NO_PUBKEY EB3E94ADBE1229CF
E: The repository ... is not signed.

Unsigned repo → apt disables it → the only Microsoft repo is now dead → mdatp can’t be found:

text
E: Unable to locate package mdatp

Three symptoms — a key error, a repo error, a missing package — and one cause: the tool downgraded and de-keyed its own package source.

The fix

Restore a proper, signed repo entry pointing at 24.04 (the newest Microsoft actually publishes), with the key referenced explicitly:

bash
# import Microsoft's signing key to a keyring
curl -sSL https://packages.microsoft.com/keys/microsoft.asc \
  | sudo gpg --dearmor -o /usr/share/keyrings/microsoft-prod.gpg

# point the source at that keyring, at the 24.04 repo
echo 'deb [arch=amd64 signed-by=/usr/share/keyrings/microsoft-prod.gpg] \
https://packages.microsoft.com/ubuntu/24.04/prod noble main' \
  | sudo tee /etc/apt/sources.list.d/microsoft-prod.list

sudo apt-get update

apt-cache policy mdatp now shows a candidate version — proof the package is reachable again. Then run the tool one more time, telling it to use the repo that’s already there so it doesn’t reconfigure (and re-break) anything:

bash
sudo bash defender_deployment_tool.sh --use-local-repo
text
[>] installing MDE
[v] Installation complete!
[v] Onboarded

--use-local-repo is the whole trick: it stops the tool touching the source list, which is the thing that keeps breaking.

Confirming it actually worked

bash
mdatp health --field healthy    # true
mdatp health --field licensed   # true
mdatp health --field org_id     # your tenant GUID

Then the standard EICAR test to prove detections flow — curl the harmless test file and watch mdatp threat list pick it up. It appears in the Defender portal under Assets → Devices within about fifteen minutes, health state Active.

What I’d tell you before you start

  • Always pass --use-local-repo if you’ve set the repo up yourself, and re-check /etc/apt/sources.list.d/microsoft-prod.list after any tool run — it will happily overwrite a working entry with a broken one.
  • Exit 127 = a missing command, not a Defender fault. On modern Ubuntu it’s the removed apt-key.
  • Exit 100 = apt. Look at your sources before you look at anything else.
  • 26.04 works, but it isn’t supported. It’s a homelab call. On a production endpoint I’d stay on 24.04 and avoid the whole detour — the newest kernel and an untested eBPF sensor aren’t worth the support conversation you’d have if something went sideways.

None of this is in the docs because the docs assume a supported OS where the happy path holds. Step off it and you find the seams — which, honestly, is half the fun of running your own lab.