Distributing clients and managing the fleet
Applies to: SimpleTwo 0.9.x · Checked: 19.10.2026
The coordinator distributes the clients itself: it holds the published builds, serves the download page and the update feeds. There is no separate distribution server.
1. The build registry
Each platform has an entry of one of two kinds:
| Entry | Kind | What it holds |
|---|---|---|
| iOS | link | TestFlight |
| Android | link | Google Play (internal testing) |
| Android (APK) | file | for devices without Play |
| macOS | file | a signed build |
| Windows, Linux | file | the slots exist, the builds do not in 0.9.x |
Files live in the data volume next to the database and survive a redeploy like every other piece of state. The upload limit is 512 MB: anything larger means the coordinator is being used as a file server by mistake.
That is a requirement, not an oversight: the person who needs to install a client cannot sign in yet. Everything you put here is readable by anybody who can reach the coordinator — and on the communications plane that is the internet.
2. Who publishes
A release pipeline publishes a build with a dedicated token, not with an administrator session: a CI job that can sign in as an administrator can do everything an administrator can, and all it needs is to replace one file. The token is created on first use and rotated from the console.
3. Update feeds
- macOS — the feed the app's built-in updater reads.
- Android — the same list in the format the app understands.
Both are served without authentication, for the same reason the downloads are.
4. Fleet monitoring
For every device the console shows the user, the platform, the app and OS versions, the connection state, an error counter and tunnel quality per location (is the node alive, latency, throughput). This is where "it does not work for one person" is told apart from "it broke for everybody", and the first place to look after shipping a new version.
App resource use
Every app samples its own process — memory and processor — every few seconds and sends a summary every five minutes with the rest of its telemetry: what it was busy with (idle, call, conference, upload, Drive, sync, tunnel), whether it was in the foreground, the device model and class (form and installed memory), and the thermal state and battery drain where the system reports them. Other apps and content are never measured.
The card Connectivity → Clients → App resource use shows:
- groups — by build, activity and device class: memory p50 / p95 / max in MB and processor p50 / p95 / max in percent of one core (100% is one core fully busy); p50 is what the app usually takes, p95 the sustained heavy end;
- regressions between builds — the newest build against the one before it on the same platform and activity: memory up by 15% or more, or processor by 25% or more;
- the heaviest devices — by memory or by processor, with the model, build and activity.
Memory compares within a platform, not across: iOS and macOS report the app's footprint, Android its resident memory, Windows its working set.
Sampling is switched off in Settings → Client telemetry ("Measure the apps' own memory and processor use"): the apps stop with their next report, in either telemetry mode.
Telemetry retention
How long the coordinator keeps what the apps send is set in the same place, Settings → Client telemetry → Retention:
| What | Default | Range |
|---|---|---|
| Resource measurements (five-minute summaries, with the user and device) | 7 days | 1–90 days |
| Resource daily summaries (build comparisons) | 90 days | 7–730 days, at least the measurements' |
| Resource measurements, row ceiling | 2 million | 100 thousand – 20 million |
| Diagnostic events (failures, traces, crashes) | 14 days | 1–90 days |
| Diagnostic hourly counts | 180 days | 7–730 days, at least the events' |
| Diagnostic events, row ceiling | 2 million | 100 thousand – 20 million |
At the row ceiling the oldest records give way to new ones even within their period. Records older
than a new period are deleted as soon as it is saved — shortening cannot be undone. Every change is in
the audit log (telemetry.retention, before and after). The App resource use analysis covers a period
no longer than the daily summaries are kept, and the heaviest devices only the last days within the
measurements' period.
5. Settings through MDM
Two things cannot be enabled from the app, and both are enabled by device management:
macOS: pre-approving the system extension. A com.apple.system-extension-policy profile removes
the "Login Items & Extensions" step, which nobody can perform across a fleet. Apple honours such a
profile only from an MDM the device is enrolled in (or supervised/DEP) — a manually installed
copy is ignored. The profile ships in the product repository under docs/mdm/.
Android: "no traffic without VPN". The app cannot turn this on itself — no tunnel parameter
does it; that is how the platform works. It is set either by the person (Settings → Network → VPN →
gear → "Always-on VPN" and "Block connections without VPN") or by MDM as device or work-profile
owner (setAlwaysOnVpnPackage with lockdownEnabled).
The macOS profile removes the extension approval step. Whether it survives the macOS 26 regression, where that step is broken even for a correctly signed build, is not verified. That is the first thing to test on one machine before promising it to a fleet.
Next
- Installing the app — the instructions for a person
- The access network — what a client receives after signing in