Skip to main content

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:

EntryKindWhat it holds
iOSlinkTestFlight
AndroidlinkGoogle Play (internal testing)
Android (APK)filefor devices without Play
macOSfilea signed build
Windows, Linuxfilethe 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.

The download page and the files are public

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:

WhatDefaultRange
Resource measurements (five-minute summaries, with the user and device)7 days1–90 days
Resource daily summaries (build comparisons)90 days7–730 days, at least the measurements'
Resource measurements, row ceiling2 million100 thousand – 20 million
Diagnostic events (failures, traces, crashes)14 days1–90 days
Diagnostic hourly counts180 days7–730 days, at least the events'
Diagnostic events, row ceiling2 million100 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).

Test it on the first enrolled machine

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​