LTE Modems, 2 Raspberry Pis, and a Headless Chromium Clicking Reboot 4k Times

hilgard1 pts0 comments

9 LTE Modems, 2 Raspberry Pis, and a Headless Chromium Clicking Reboot 4,000 Times — Jan Hilgard<br>← Back to writing<br>The fleet: nine TP-Link M7000/M7200 LTE modems across two Raspberry Pis (one Pi 4, one Pi 5), connected via a Terminus 7-port USB 2.0 hub. Each modem physically labeled with its subnet identifier — the only way to keep modem identity stable across reboots, because the firmware reports an identical fake serial number for every device.On this pageThe setup, in one paragraph<br>What this solves<br>Why this exists<br>The fleet<br>Carrier split<br>Why two Pis instead of one<br>The architecture surprise: no policy routing<br>How clients reach a specific modem<br>The rotation engine: Playwright clicks Reboot<br>The six-step cycle<br>Live observability<br>The pm2 anti-pattern that works<br>The watchdog: why "just reboot" isn't enough<br>Production gotchas<br>Every M7200 has the same fake USB serial<br>Modems briefly impersonate Google during reboot<br>The 12 Mbit/s USB bottleneck<br>RSA-encrypted login on a $30 modem<br>Memory and thermal headroom<br>The production numbers<br>A note on getting blocked, in practice<br>What I'd do differently, and what I won't change<br>Alternatives I evaluated before building this<br>Where this architecture stops making sense<br>What it powers<br>Honest limitation: the pool is not 100% available<br>Latency, cost, and architecture

The setup, in one paragraph

Two Raspberry Pis run a pool of nine TP-Link MiFi LTE routers as a rotating residential-IP proxy fleet for my AI products. Each modem appears on its Pi as its own USB network interface; each modem has its own GOST HTTP-proxy instance bound to that interface; clients reach the pool over WireGuard. Every five minutes (give or take), a headless Chromium instance — supervised by pm2 — logs into each modem's web admin UI, clicks Reboot , watches it bounce, and verifies through ipify that the carrier handed it a new public IP. When something fails, an escalating recovery ladder takes over: nmcli down/up, then USB power-cycle through sysfs authorized toggling, then — if it were enabled — a host reboot. It isn't enabled. The fleet has been running for nearly four weeks straight with zero throttling and zero crashes, having completed roughly 4,000 reset cycles and pushed close to a terabyte through the WireGuard tunnel.

That's the system. The rest of this post explains the parts of it that I find interesting after running it in production: a few architectural decisions that turned out smaller than I expected they would be, and a few details that turned out larger.

What this solves

The setup is built around three properties: residential IPs that anti-bot systems can't reliably block, consumer-hardware cost economics, and high availability without a managed service or a complex cluster.

The first comes from cellular CGNAT. Mobile carriers hide individual subscribers behind dynamic pools of public IPs that anti-bot vendors are structurally reluctant to ban — too many real users live there. Run nine independent SIMs across two carriers and rotate their public addresses every twelve minutes or so, and you have an IP pool that anti-bot mitigation can't fit into its usual "one IP, one identity, one rate limit" model. In practice, individual modems get rate-limited constantly — that's what triggers the rotation in the first place — but the pool as a whole has never been blocked. Querying public sites, Google included, is functionally unblockable from this setup.

The second comes from refusing to pay residential proxy vendors per gigabyte. Two Raspberry Pis and nine consumer MiFi modems amortize against any comparable commercial residential proxy service in well under a year. The dominant ongoing cost is the SIMs themselves, which I run on flat-rate consumer plans.

The third is the cheapest property to get right: it falls out of running the pool across two Pis. If one node crashes, gets a kernel update, or needs hardware maintenance, the other carries the load with four or five modems instead of nine. It's high availability through redundancy, not through coordination — no cluster manager, no shared state, no failover orchestration. Each Pi is independently operational. The cost is one extra Raspberry Pi.

Why this exists

I build AI products. Two of them — Advanty and Discury — consume large amounts of public web data: ad creative inventories, product listings, social discussion threads. The pattern is familiar to anyone doing this kind of work in 2026: most of the high-value pages are behind Cloudflare, Datadome, or Akamai bot-mitigation layers that flag datacenter IPs immediately. You either pay one of the commercial residential proxy vendors at $X per gigabyte, or you find another way to put requests on IPs that look organically residential.

Cellular carriers, it turns out, are the other way. Mobile traffic in most countries hides individual subscribers behind carrier-grade NAT (CGNAT), and the pool of public IPs that CGNAT rotates over is exactly the kind of "residential" address space anti-bot...

modems reboot modem pool residential raspberry

Related Articles