Digital Garden

The Job Redesign of a 2014 MacBook Pro: When the Truth Behind the Taking-Off Fan Was Dismantled, Docker Was Replaced by Three Native Binaries

2026-10-18 · ~10 min read · Self-Hosted Gateway · Architecture Decisions · NewAPI · Old Hardware Reuse · Deployment Topology

A 2014 13-inch Retina MacBook Pro, dual-core i5, 8GB of soldered memory, 256G SSD. The question asked was “can my old Mac be a VPS”, and the answer took a full circle to land — because three separate questions were wrapped inside it, and each one’s answer is different.

I. Old Mac as VPS: The Idea Does Not Hold

Start with the outer shell. A VPS is by definition “a machine with a public IP in a datacentre”. A MacBook at home still sits behind carrier NAT — this machine has no public IPv6 at all, its NIC address is the fd7a:115c:a1e0::/48 private range, and IPv4 is most likely unobtainable too. The tunnel still has to be tunnelled; the Mac’s chassis solves nothing.

Its correct role is an always-on, low-power home server — solving “the service dies when the main PC shuts down”, not solving public access. The two needs are often conflated, but their cost and safety implications are entirely different.

An incidental observation: the owner mentioned the old Mac is also the CI build machine. That strengthens its positioning rather than weakening it — a machine already on a 7×24 post absorbing a few more lightweight processes is far more realistic than treating it as a VPS.

II. The Mandatory Rewritten by an Architectural Constraint

Next came the turning point. The owner said: sometimes the phone’s VPN port gets occupied, and Tailscale must use the VPN port.

The question hit the mark, and the answer is not something configuration can route around: this is not a port conflict, it is that phone systems allow only one VPN at a time. Android’s VpnService and iOS’s NEPacketTunnel each have a single VPN configuration slot, and Tailscale, WireGuard, Clash and Shadowrocket are all fighting for that one position — so switching to WireGuard collides identically. Desktops have no such limit; Tailscale coexists with other VPNs there. But phones cannot.

The conclusion rewrites itself: under the phone constraint, Tailscale as the phone’s primary access route is inherently unreliable. To let the phone connect at any time, only a public HTTPS direct connection works — the “public internet” plan first asked about moved from optional to mandatory. With a bonus: the phone already carries a proxy VPN most of the time, and a public endpoint reached through the proxy is more stable, so the two needs do not fight.

III. Cost and Selection: Only One Decisive Variable

Four public-internet options were laid out — Cloudflare Tunnel (zero cost, free HTTPS and DDoS protection, home IP fully hidden, but the free tier has a 100-second origin timeout, the 524, and long streaming output may be cut), overseas VPS plus reverse proxy (roughly ¥35-70/month, most balanced), domestic light cloud (¥50-100/month plus ICP filing), and home public IP direct exposure (domain cost only but basically infeasible, with the entire home network facing scanners).

And selection really has only one decisive variable: whether you will use reasoning models whose first token takes over 100 seconds. That class of model, which thinks for a long time before emitting, makes Cloudflare’s free-tier 524 recur periodically, and this is a timeout between CF’s servers and your home — whether the phone carries a proxy cannot save it. Without reasoning models, the free tier is entirely sufficient.

IV. Where to Deploy: One Channel Pointing at a Local Container Changed the Answer

“So where do I deploy NewAPI?” — the question looks simple, but the answer depends on a fact easily skipped. The database was copied out and read directly, which turned up two things: channel 10 (workbuddy) points at http://host.docker.internal:7863, the local workbuddy2api container; and workbuddy2api’s credentials live in C:\Users\Min\workbuddy2api\auths, bind-mounted in.

Those two facts decide the answer. NewAPI has a local upstream dependency and cannot leave the home network alone — a VPS cannot reach the home 7863. Moving workbuddy2api along means its auths directory holds login credentials for the upstream service, which will very likely fail or trigger risk control after moving to a VPS’s public IP; that risk is uncontrollable. Add that the user count is currently 1, so “for others to use” remains a hypothetical need, and tens a month is spent in vain.

The old Mac is the right answer: it stays inside the home network, the public IP is unchanged, the workbuddy channel and credentials work as-is; NewAPI’s database and workbuddy2api’s three mounts are directory-copy-level migrations, with not one configuration line changed; low power, able to run 7×24, and the main PC can shut down freely from then on.

V. It Is the Fan Taking Off, and the Culprit Is Not Hermes

The owner’s worry landed at last on one sentence: by taking off I mean the fan taking off, mine is a 2014 MacBook Pro, 8+256 plus an old dual-core i5, and I am deciding between the desktop Hermes and the CLI, but I am only used to the desktop.

First dismantle where the load actually goes. Hermes’s work is orchestrating API calls — waiting for network returns, parsing JSON, near-zero CPU when long-polling idle, and the fan is silent. What actually eats CPU and memory is three things, all stacked on by you: the desktop Electron companion (a resident renderer process, sluggish and hot on dual-core Haswell plus a slow SSD), Docker Desktop (an entire Linux VM in the background, eating another 1-2GB on an 8GB machine, and CI builds make it take off for sure), and Hermes’s browser control (the machine will scream when browser automation really runs).

So the correct division is CLI resident plus WebUI as the GUI: run hermes gateway start headless and resident on the Mac, quiet and memory-frugal; when you want a graphical interface, use the WebUI and open it in a browser — rendering happens in your phone’s or that 5090 PC’s browser, while the Mac only serves a lightweight page, zero extra load, reachable via Tailscale from the main PC, indistinguishable in experience from the desktop. Do not install the desktop Electron companion on this machine: sluggish, hot and loud, all three at once.

VI. No Public Exposure Needed: Long-Polling Rewrote the Whole Project

The real turning point came from verifying the Hermes project itself. It is confirmed as NousResearch/hermes-agent, one command from the official installer, managing Python 3.14 and Node itself. And .env.example holds a point decisive for the architecture: Telegram long-polls by default — with TELEGRAM_WEBHOOK_URL unconfigured it is long-polling, and webhook is only for cloud deployments like Fly.io and Railway.

Long-polling means the Mac initiates outbound connections to Telegram — no public IP needed, no CF Tunnel, no port mapping, nothing to install on the phone. You message the bot from any device and that is all.

That is, the big project of “making NewAPI public” first asked about can be skipped entirely for the core use of “commanding an agent anytime”. CF Tunnel is needed in only one case: you also want phone apps like Cherry Studio to connect to NewAPI directly.

VII. Final Form: Zero Containers, Four Native Processes

On that Mac, Docker was also sentenced to death, for three reasons, the third decisive: memory (Docker Desktop is an Electron app plus an entire Linux VM, eating 1.5-2GB for free on an 8GB machine, on which you also run CI builds), system (the 2014 MBP officially supports up to Catalina, and Docker Desktop’s support for it stops at very old versions), and most critically — all three services ship official macOS native binaries:

The three together take about 500MB resident, leaving the rest to CI. Watch the 256G disk too — external expansion or regular cleanup. Docker’s ecological niche on the Mac is replaced by four launchd plists — auto-start on boot, auto-restart on crash, lighter than compose.

One thing to watch: NewAPI’s jump from the calciumion era to the QuantumNous era is a major version leap, so back up that 90MB SQLite before switching, and verify channels and tokens are still there after startup.

VIII. One Life-or-Death Line

The architecture is set, but one line must not be crossed: TELEGRAM_ALLOWED_USERS takes only your own TG user ID. If the bot token leaks without a whitelist, you have handed a Mac shell capable of executing code to a stranger, burning your quota. The NewAPI token Hermes uses is created separately, with a limit; the Mac’s SSH stays off the public internet, managed via the existing Tailscale.

Three rules were also set before the old Mac takes its post: keep it plugged in year-round, remove the battery or cap charging at 60-80 percent, since swelling damages keyboard and trackpad; prevent sleep, use caffeinate for closed-lid operation, and it must not sleep during CI builds; cooling, clean the dust and replace the thermal paste before it takes the post.

A 2014 machine ended up with a post it did not expect for itself: not a VPS, but a zero-container, four-process resident orchestrator that shakes hands with the outside world through long-polling. The fan no longer takes off — because this time nobody finally stacked Electron on top of it.

Comments

← Digital Garden