Skip to content

Usage statistics (opt-in)

CertiStack tells Clift Cloud nothing unless you say yes. The statistics are off by default. Until you opt in, CertiStack makes no network connection for them at all, and an air-gapped controller never notices that the feature exists. This page is the whole statement: the five fields, what is never collected, how to see exactly what would be sent, when it is sent, how to turn it off, and how to have a record deleted.

Everything else CertiStack does on the network is unchanged: connections to the Proxmox VE and Proxmox Backup Server you name, SSH to the node you name, and probes to the guests in the isolated sandbox. The opt-in report described here is the only other connection, and it goes to one address.

The five fields

The report is exactly these five fields, as certistack telemetry show prints them:

{
  "install_id": "3f0c8a5e-6b1d-4e2a-9c47-0d5e1b7a92f4",
  "version": "0.1.0",
  "cluster_count": 2,
  "last_test_run": "2026-10-01",
  "business_use": false
}
Field Example What it is Why it exists
install_id 3f0c8a5e-6b1d-4e2a-9c47-0d5e1b7a92f4 A random UUID (version 4), made when you opt in. It is not derived from your hardware, host name, MAC or IP address, or user name. So an installation is counted once, not once per run, and a new report replaces its last one instead of adding to it.
version 0.1.0 The CertiStack version string: printable ASCII, at most 64 characters. To see which releases are in use, so a release is retired only when nobody runs it and testing goes where the users are.
cluster_count 2 How many distinct Proxmox VE clusters this installation has validated. To tell a lab from a fleet when deciding what to build. The count comes from a list of salted hashes kept only on your machine; the hashes are never sent, only how many there are.
last_test_run 2026-10-01 The UTC date of the last completed restore test. A date only, never a time of day. Empty until a test has completed. To see whether installations keep testing restores, which is the point of the product.
business_use false Your answer to "Do you use CertiStack for a business or commercial purpose?". To plan support and the commercial edition. The report holds nothing that identifies you or your organisation, so it cannot be used to contact or audit you.

Nothing else is in the request. A test holds the code to this table: the report is a struct of these five fields, the example above is the bytes it encodes to, and a change to either fails the build.

What is never collected

Host names, IP addresses and MAC addresses; VM names, VM IDs and the number of VMs; plan names and plan contents; node, cluster and storage names; Proxmox or PBS addresses, tokens, passwords, keys and fingerprints; file paths and user names; the operating system, locale and time zone; the time of day; report contents, probe results, and whether a test passed or failed. The cluster hashes and the salt stay in telemetry.json on your machine.

A test runs the run command to its end, with the controller stubbed, seeded with distinctive host names, addresses, VM names, tokens and paths, and fails if any of them, or any cluster hash, appears anywhere in the request: the request line, the headers, the user agent or the body.

See exactly what is sent

$ certistack telemetry show

prints the exact bytes that the next report would carry, and nothing else on standard output. When the statistics are off it says nothing is sent: disabled and why. certistack telemetry status says whether they are on or off, why, and where the state file is; when they are on, it also says where a report would go.

When it is sent

  • Only after a completed run (a pass or a fail) that tested at least one VM. Never from plan, doctor, init, validate, verify-report, report, schema, inspect or recover, and never from the PVE node: the temporary worker that run uploads does not report, and has no telemetry setting to read.
  • At most once every 24 hours for an installation. A run in between is recorded locally (a new cluster, a newer test date) and goes out with the next report.
  • As one POST to https://certistack.dev/api/telemetry with Content-Type: application/json and the user agent certistack-telemetry/<version>, which is the only user agent it ever uses. The standard proxy variables (HTTPS_PROXY, NO_PROXY) are honoured.
  • Within 3 seconds, end to end. There is no retry and a redirect is not followed. The answer is ignored, and at most 4 KiB of it is read.
  • The command waits for it at most 2 seconds after the verdict is out. A failure is silent (--debug shows it), and it never changes the exit status. A failed attempt counts as the day's attempt, so an unreachable server costs at most one short wait a day.

Turn it on or off

The first-run question

The first time you run run, plan, doctor or init at a terminal, CertiStack asks, on standard error:

Share anonymous usage statistics with Clift Cloud? Nothing but the five fields shown by `certistack telemetry show` is sent. [y/N]

and, only if you answer yes:

Do you use CertiStack for a business or commercial purpose? [y/N]

Enter, end of input and any answer but y or yes mean no, and the answer (no included) is stored, so the question is asked once. It is never asked when standard input or standard error is not a terminal, when CI is set, when an environment variable below has already decided, or by any other command, so a script, a scheduled job, the container and the appliance never see it and never enable anything.

Commands

Command Does
certistack telemetry status Says on or off, the reason, the state file and the endpoint.
certistack telemetry show Prints the exact JSON that would be sent now.
certistack telemetry enable [--business] Opts in. --business answers yes to the business question. Writes telemetry.json with a new random install ID.
certistack telemetry disable Opts out and forgets the install ID, the salt and the cluster hashes on this machine.
certistack telemetry reset Deletes telemetry.json: your answers and the install ID are forgotten and the first-run question is asked again.

Environment variables

Strongest first:

Variable Effect
DO_NOT_TRACK=1 Off, whatever else is set or stored. Any value but 0, false, no or off counts.
CERTISTACK_TELEMETRY=0, off, false or no Off, whatever is stored. A value that is not recognised also counts as off.
CERTISTACK_TELEMETRY=1, on, true or yes On for this process only, for CI and containers. Nothing is read from or written to disk: the install ID is random for each process, there is no memory of the last report, and business_use is false unless CERTISTACK_TELEMETRY_BUSINESS=1. If you already ran certistack telemetry enable, your stored install is used as it is.
(neither set) Your stored answer. Never asked is off.

CERTISTACK_TELEMETRY_URL replaces the address, for testing: https, or http for a loopback host only. A value that is not acceptable sends nothing; it never falls back to the default. These variables are read from the process environment only, never from an --env-file.

Where the answer is kept

telemetry.json in your per-user configuration directory, mode 0600 ($XDG_CONFIG_HOME/certistack/ or ~/.config/certistack/ on Linux, %AppData%\certistack\ on Windows):

Member Meaning
answered, enabled, business_use Your answers.
install_id The random UUID, present only while enabled.
salt A random per-install salt for the cluster hashes. Never sent.
clusters Salted SHA-256 hashes of the clusters you validated. Never sent; only their number is. At most 512 are kept, so the count stops at 512 (more would not fit the size limit of the file, which CertiStack enforces when it writes it as well as when it reads it).
last_test_run The date of your last completed test.
last_sent When a report was last sent (attempted), to keep to one a day.

A missing file means you were never asked, which is off. A file that cannot be read or does not make sense is off too: CertiStack neither crashes nor sends. A cluster is identified for the hash by the name of the node the run used, so validating one cluster from two of its nodes counts as two clusters until the report records the cluster's own name.

Every change to the file (a run recording itself, enable, disable, reset) takes an exclusive lock on an empty file beside it, telemetry.json.lock, for the moment of the change only, never during the network request. A run that read the file before you opted out therefore cannot write the old state back over your opt-out: it reads the file again under the lock, finds telemetry off or reset, and records and sends nothing. Two runs that finish together keep each other's clusters and share the one report a day allows. A change that cannot get the lock within a few seconds says so and changes nothing. A request already on its way when you opt out is not recalled. reset leaves the empty lock file. Where the platform or file system has no such lock (Windows, some network home directories) the changes are not serialized, and disable still works.

CI, containers, the appliance

  • A scheduled job, a CI system and a container have no terminal, so they are never asked and stay off. To opt a CI job in, set CERTISTACK_TELEMETRY=1 in its environment. To make sure one never reports, set DO_NOT_TRACK=1.
  • The controller container and the appliance start with an empty environment and no home directory to keep an answer in, so they send nothing. To opt in, add CERTISTACK_TELEMETRY=1 to the container's own environment: the environment: block of deploy/controller/compose.yaml, or docker compose run -e CERTISTACK_TELEMETRY=1. It is not read from controller.env: the controller loads that file itself, literally, and refuses any name that is not one of its own settings.

Retention and deletion

The server keeps the latest report for each install_id, and when it arrived: a new report replaces the old one. It stores no IP address and no user agent beyond the fixed string above. A record is deleted after 45 days without a report.

To have a record deleted sooner:

  1. Run certistack telemetry show and note the install_id.
  2. Run certistack telemetry reset (or disable). Nothing more is sent, and the ID is forgotten on your machine.
  3. Send the ID to Clift Cloud at [email protected] with the subject "Telemetry deletion". The ID is random and tied to nothing else, so it is the only way to find your record.

For an auditor

The product opens a connection for this report in one place: pkg/telemetry, called from run once the verdict is out and imported by no other package. The tests that hold the promises above are in pkg/telemetry and cmd/certistack/cmd_telemetry_test.go: nothing is requested while off, exactly the documented request while on, nothing of a run reaches the server, and nothing but run sends.