Reference

The update check

The one request Papyra makes on its own, what it sends, when, and what the project does with it.

Papyra has no tracking, analytics or crash reports. It makes one request of its own, once a day: a check for a newer version. It is optional. You can turn it off with one setting.

What it does

Your server asks versions.papyra.app for the newest release. If one is newer, admins see a warning icon beside the version in the sidebar, with a popup linking to the release notes. Other accounts never see it.

The whole client is UpdateCheck.cs. The whole server is papyra.versions.

Turning it off

Set this in your compose file and restart:

PAPYRA_UPDATE_CHECK_ENABLED: "false"

Papyra then never makes the request and never creates the install ID. The only cost is that admins won’t see the update notice, so watch the releases page yourself. Nothing else in Papyra changes. Your install simply isn’t counted.

What it sends

Four values, in the request address:

GET https://versions.papyra.app/latest.json?id=2d1f0c2e-…&v=1.0.0&arch=arm64&os=linux
ValueMeaning
idA random ID the server made the first time it asked, kept in .papyra/instance-id. Not derived from anything. It only says “the same install again”. Delete the file for a new one.
vThe version you run, e.g. 1.0.0. Dev images send theirs, e.g. 1.1.0-dev.abc1234.
archProcessor family: x64, arm64 or arm.
osOS family: linux, windows or macos.

Never sent: notes, titles, usernames, emails, your server’s name or address, number of accounts, or anything about how you use Papyra.

When it asks

  • Once a day, at a time of day fixed per install (derived from its ID). Check-ins spread across the day.
  • Never between 02:30 and 03:30 UTC. That hour is when the site is rebuilt from the day’s numbers.
  • A restart doesn’t ask again.
  • If a check fails, it retries after 1 hour, then 2, 4 and 6. The time a retry gets through becomes the install’s new daily time.

What the project keeps

  • Your IP address is never stored. Cloudflare turns the connection into a two-letter country code at its edge, and only that code reaches the counting code. The Worker has no request logs.
  • One row per install: ID, version, processor and OS family, country, the first and last time it checked in (to the hour), and on how many days (schema.sql).
  • Public numbers: installs counted, installs active in the last 30 days, and their countries, versions, processors and operating systems, at versions.papyra.app/stats.json. The home page shows only the total installs, next to the Docker Hub pull count.
  • Gaps: “active” is counted back from the newest check-in, not from today, so a few quiet days don’t drain it. Installs only ever go up, and the last good numbers are kept if the live ones can’t be worked out.

How accurate the count is

It is an estimate. Anyone can send a request that looks like an install, so the numbers are built to be hard to move rather than impossible to fake:

  • An install is counted once it has checked in on two different days, at least 24 hours apart. A new install shows up a day or two late.
  • A version number that was never released isn’t counted.
  • Only so many new installs are taken in each hour, and the total shown here can only rise by a limited amount a day, so a sudden jump appears gradually.
  • A check that is turned away isn’t an error for you. Papyra just asks again tomorrow.

The numbers can be too high by whatever someone is willing to run, and they are too low by every install that has the check turned off.

Why I count

It keeps me motivated to build more, and it feels good to see Papyra is being used. That, plus telling you about updates, is all it’s for. If you’d rather not be counted, turn it off; it’s your server.

A server with no release version (dotnet run, the test suite) never makes the request, so developing Papyra doesn’t count as installs.

Something wrong or missing? Improve this page on GitHub.