81. pepsi-telemetry

The central, anonymous, opt-in feature-telemetry collector.

81.1. Role

pepsi-telemetry collects anonymous usage telemetry from Pepsi installations that opt in. It is a small HTTP server, deliberately separate from pepsi-httpd and shipped in its own Debian package, intended to run on one host — by default telemetry.pepsi.taler.net — behind an existing nginx or Apache front server. Run it with pepsi-telemetry serve.

A reporting Pepsi node is identified only by a random 256-bit system_id (no personally identifying information). The collector connects to the shared pepsi PostgreSQL schema as the pepsi-telemetry role and stores everything in the pepsi.telemetry table, counting usage per reported Pepsi version.

81.2. Features

  • Two open submission endpoints. POST /telemetry/features records which features a deployment has enabled (a snapshot: listed features become enabled, omitted ones disabled, with usage history retained), and POST /telemetry/usage accumulates per-feature usage counts (deltas, summed server-side). Both are unauthenticated — the only identity is the anonymous system_id — and bounded by MAX_BODY plus the front server’s rate limits.

  • Per-version counting. The version reported in each submission is part of the table key, so usage events are attributed to the Pepsi release that produced them and an upgrade accrues separate rows.

  • Public aggregate report. GET /telemetry/report returns per-feature rollups (distinct enabled deployments and total uses) with a per-version breakdown, as JSON. It never exposes an individual system_id, so it is safe to serve openly.

  • No TLS of its own. It serves plain HTTP on a UNIX socket (/run/pepsi-collector/pepsi-telemetry.sock, socket-activated via SERVE = systemd as shipped, or bound by the daemon itself with SERVE = unix) for a reverse proxy, or plaintext TCP for local testing. TLS is terminated by the fronting nginx/Apache.

81.3. Feature-stability table

The companion script contrib/update-feature-stability.sh fetches GET /telemetry/report and regenerates Feature stability, assigning each feature a tier from both how widely it is deployed and how heavily it is exercised (a feature must clear both thresholds for a tier):

  • stable — deployments ≥ 100 and total uses ≥ 100000

  • used — deployments ≥ 10 and total uses ≥ 1000

  • experimental — otherwise

The thresholds, source URL and output path are overridable via environment variables (see the script header).

81.4. Configuration

[pepsi-telemetry]: SERVE (unix/tcp/systemd) with the matching transport options (UNIXPATH/UNIXPATH_MODE/UNIXPATH_GROUP, or BIND_TO/PORT), MAX_BODY (default 65536), MAX_CONNECTIONS (default 128) and DB_POOL_SIZE (default 2). The database connection comes from the shared [pepsi-postgres] section. See Configuration and pepsi-telemetry(1).

81.5. Deployment

The Debian pepsi-telemetry package ships a systemd service and socket unit (serving on /run/pepsi-collector/pepsi-telemetry.sock), its configuration file /etc/pepsi-telemetry/pepsi-telemetry.conf, and reverse-proxy site files for both nginx and Apache, installed under their canonical site names:

/etc/nginx/sites-available/telemetry.pepsi.taler.net
/etc/apache2/sites-available/telemetry.pepsi.taler.net.conf

They arrive complete and disabled, already pointing at the socket the shipped units bind, so enabling one is only a symlink — there is no proxy path to fill in and so none to get wrong:

# nginx
$ ln -s ../sites-available/telemetry.pepsi.taler.net /etc/nginx/sites-enabled/
$ systemctl reload nginx

# Apache (a2ensite makes the same symlink)
$ a2enmod proxy proxy_http ssl ratelimit headers
$ a2ensite telemetry.pepsi.taler.net
$ systemctl reload apache2

Then provision a certificate for the host, and install the schema from the collector’s own file, which needs nothing but its [pepsi-postgres] section:

$ pepsi-setup -c /etc/pepsi-telemetry/pepsi-telemetry.conf schema

Package upgrades upgrade the schema the same way, and the collector refuses to start against a schema from another release until they have (see Upgrading). Both site files are conffiles, so local edits — a different server_name, say, for a private collector — survive package upgrades.

Change the socket path and it becomes one statement in four places: the .socket unit’s ListenStream=, the service’s RuntimeDirectory=, and the two site files (plus UNIXPATH in the collector’s own configuration, if you switch it to SERVE = unix). make check-telemetry-socket, which make check runs, compares them and fails the build if any two disagree — worth having, because a mismatch is invisible in testing and reaches production as nothing but a 502 from the front server.

The collector’s runtime directory belongs to it alone, and that is the point. It is not /run/pepsi (the mail pipeline’s, shared by pepsi-ingress, pepsi-httpd and the setup-apply doorbell), and it is not /run/pepsi-telemetry (the telemetry client’s, whose socket /run/pepsi-telemetry/socket is owned by pepsi). systemd gives a runtime directory to the declaring unit’s own User= — chowning it and its contents on every start — and, without RuntimeDirectoryPreserve=, removes it when that unit stops. So a directory shared between services running as different accounts ends up owned by whichever started last, and one service stopping deletes the sockets the others still have bound.

Distinct file names in a shared directory are not protection. Were the collector’s socket in the client’s directory, a host running both would work until the client next started; the collector’s socket would then be chowned to pepsi:pepsi, lose the www-data group the front server connects through, and every request would become a 502 — with the collector active, healthy and silent, having never seen a connection. Running the collector on a host of its own is still the intended deployment, but it is not what keeps the two apart.

81.6. See also

pepsi-telemetry-client (the per-host client that submits to this collector), pepsi-httpd, pepsi-setup, Feature stability, pepsi.conf(5).