A speed test that runs inside the machine it measures

A throughput number is a claim about a path, and a path has two ends. If both ends are the same host, or if one end is a one-vCPU machine that is busy running everything else, the number is mostly a measurement of the machine. It will happily report a fast link over a bad one. The header of internal/api/speedtest.go puts it bluntly:

1
// a speed test running inside the machine it is measuring is not a speed test

Where the bytes actually travel

The browser in the tunnel moves bytes to and from the tunnel endpoint — the host every client tunnel terminates on, served by this same binary under its clientsv probe role. The downlink is streamed from there; the uplink is counted there.

The portal is deliberately the other half. It serves the page, owns the session, mints the short-lived proof the far end requires, and writes the one result row. It does not move the bytes. That distinction is the design: the edge host is one vCPU that also serves the site, the admin console, monitoring and CI, and its load moves the throughput measured through it by a factor of several.

The far end is a deliberately minimal role of the same binary: no database, no session, no cookies, no templates, no history, no write path. Two routes carry the load, and both are pure copy work:

1
2
3
block := speedBlock()                          // 1 MiB, incompressible, repeated

n, err := io.Copy(io.Discard, io.LimitReader(r.Body, cap+1))   // the uplink

Every byte the test moves is a byte the host copied: a one-vCPU host can saturate on the copy before the link does, so the ceiling is often the host, not the network. A finished test stores one row — two rates, the byte counts, the latency, the device and tier, and the time.

Auth without a usage log

An endpoint anyone can hit has to be authenticated, and the easy way is to give it an account and log it. A session cookie is host-only, so a browser cannot carry the portal’s session to another name — the far end needs its own credential, and it gets a short-lived bearer token instead of an account.

The portal mints it and the far end verifies it statelessly: HMAC-SHA256 over an expiry and a nonce, keyed by a secret both hosts read from the same sops file. The nonce makes two tokens minted in the same second different, so a leaked one is not replayable. The shipped TTL is 3 minutes, the far end accepts nothing with an expiry more than 15 minutes out, and 30 seconds of clock skew is absorbed.

There is no access log entry for any of it. The far end writes nothing, the fleet’s caddy skips the probe paths on the endpoint, and on the edge /api/speedtest/* is log_skipped next to a comment explaining why. One request line carries a byte count and a timestamp, and a few dozen of them are a per-test throughput measurement tied to an address.

The induced load is itself a denial-of-service surface on a small edge host, which is why the credential is short-lived and per-request rather than a long-lived key, and why there is a concurrency ceiling of 12 requests in flight. Over the ceiling the far end answers 503 and the page falls back to measuring at the portal — a stalling client degrades the test instead of parking the host. Stealing a token buys bandwidth, not access, and it buys it for minutes.

What a throughput figure needs next to it

Never present one number on its own. Say, at minimum:

What you can check

A short-lived token protects against replay, against correlation by value, and bounds the blast radius of a leak — it expires in minutes and grants a bounded transfer to one far end. It does not protect the host from a concurrent test saturating its CPU, which the concurrency ceiling caps as a degradation control rather than a defence.

What is recorded and what is not is on what we log; the policy it belongs to is what “no logs” can and cannot promise.

󰔟 Running the same kind of stack?
The tunnel this site is written from is the one I sell: WireGuard to a gateway in Montréal, three DNS postures, one price — and the same "check it yourself" habit as everything above.
[ CREATE ACCOUNT ] [ WHAT IS THE VPN ]
󰣨 ymrtech@ymrtech | 󰌠 NixOS | 󰍢 UTF-8