APM v2.6.0

Linux static binaries compiled 2026-08-30. Copy, chmod +x, run. Zero dependencies.

← All releases

Windows Defender false positive — Microsoft Defender may flag APM binaries as Wacatac.B!ml. This is a known false positive: its ML heuristic misfires on statically compiled Go binaries and UPX-compressed executables. It has been reported to Microsoft for review. All other major antivirus engines report these files as clean — see the VirusTotal links below for full scan results.
Linux
x86_64 / amd64
apm-v2.6.0-x64 standard 8.7 MB
MD5: 43c8a4dab7e84b7d28c6752d0011af4a VirusTotal ↗
apm-v2.6.0-x64-upx UPX 2.7 MB
MD5: 89385f049e2f8cdb64c794710f7f5531 VirusTotal ↗
Linux
ARM64 / aarch64
apm-v2.6.0-arm64 standard 8.1 MB
MD5: e48d0196644e64e2adfe50b2ca8e3085 VirusTotal ↗
apm-v2.6.0-arm64-upx UPX 2.3 MB
MD5: 97bc1720a2daba080e84c8bc86164dc9 VirusTotal ↗
Linux
ARMv7 / armhf
apm-v2.6.0-armhf standard 8.4 MB
MD5: 21a3ea503214de70759e1ab64050f503 VirusTotal ↗
apm-v2.6.0-armhf-upx UPX 2.3 MB
MD5: b5e92edf971bf0349afd9ccce1997b01 VirusTotal ↗

v2.6.0 — a dead device is reported in seconds, not minutes

A force-powered-off WS device used to sit "online" for two minutes — the

worker heard nothing until the keep_alive idle deadline fired. Raw tcp://

was worse: minutes on an idle death, 15+ of them if data was in flight. On a

device dashboard that reads as a bug, because it is one.

dead_timeout — kernel-level dead-peer detection

`

worker {

server ws://0.0.0.0:9100;

dead_timeout 10000; # report a vanished client within ~10 s

}

`

Off by default. When set, every accepted ws/tcp client socket gets tuned TCP

keepalive (catches a peer that dies while the line is idle) plus

TCP_USER_TIMEOUT (catches one that dies with data in flight — which Linux

otherwise retransmits at for 15+ minutes). Probes are empty segments the

client's kernel answers: no library support, no app wakeup, works the same

for a browser and a microcontroller, and none are sent while real data flows.

Measured, real link-down against a live daemon: idle death → worker onClose

in 8.2 s (was 120 s); death mid-push → 10.5 s (was 15+ min); dirty FIN

→ 3 ms. Slow links are safe by construction — only total silence for the whole

window triggers, never slowness, so a wifi client behind three walls ACKs its

way to safety at any throughput. Reload applies it live to new connections

without touching children.

Every dirty WS disconnect leaked a socket — since v1.x

The WS "connection lost" path (read error, EOF without a close frame, idle

timeout — exactly the dead-device paths) notified the child and cleaned up the

session, but never closed the socket. One leaked fd per dirty disconnect for

ever, CLOSE_WAIT pile-up on bare-FIN closes, and a permanently wedged handler

goroutine when the child had unACKed data in flight (handleTCP had the same

wait-before-close ordering flaw). The connection-side cleanup now closes the

socket on every path. Verified: zero CLOSE_WAIT, daemon fd count returns to

baseline.

Full stories with the raw-Node baseline measurements are in the timestamped

notes beside this file. Verified with go build/vet/test, socket options

read back via getsockopt, and an end-to-end daemon + connector + virtual-switch

rig with real link-down.