Gotta magnet ’em all. Seriously.
Magnemite watches for new Pokémon GO .apkm releases, caches them once on your server, and installs them across the fleet with per-device progress, automatic retries and canary rollouts.
# bring the stack up
docker compose up -d --build
# mint the first enrollment token
make seed
# bake the hub URL into a Magisk module
make module SERVER=https://agents.example.com
TOKEN=<token>
# flash once — every later update rides the socket
./scripts/enroll.sh dist/agent.zip -f hosts.txt- 1 → N
- boxes per rollout
- 1×
- download per release
- 0
- ports open on the LAN
- ~6 MB
- agent on the box
Why it exists
Built for the day the rollout goes wrong
Updating one box by hand is fine. The whole design is about the other hundred and ninety-nine.
No open ports
Boxes dial out over WSS. NAT, CGNAT and changing IPs are somebody else's problem, and nothing on the LAN is exposed.
Cached once
The hub downloads each .apkm a single time, hashes it, and Caddy streams it off the volume — Node never sits in the data path.
Canary first
A few boxes update alone. A failed canary parks the rollout at PAUSED instead of pushing a bad build to two hundred devices.
Retries by itself
Offline, stalled and failed jobs come back without anyone watching. The bytes already on disk make the retry cheap.
A fleet without hardware
The agent's -fake-root mode stubs pm and dumpsys only: downloads, hashes and .apkm extraction stay real.
Per-device tokens
Every box authenticates with its own bearer token, stored as a sha256. Downloads are gated on it at the edge.
Architecture
Four processes, on purpose
Two hundred device sockets have to survive a dashboard rebuild, so the socket server is not the dashboard.
- 01
agent
Go binary on each box. Dials out, never listens.
- 02
hub
Sockets, scheduler, source polling, cache-once.
- 03
edge
Caddy. Streams the bundles off the volume.
- 04
web
The dashboard you run rollouts from.
Three steps