← ЧПП

ЧПП се напишани на англиски и холандски; се прикажуваат на англиски.

ЧПП

App catalogue and download tokens

FAQ › Profile server › Apps and downloads · Nederlands

What is it?

The app catalogue on the profile server tells EUZOS PCs which apps exist (Chromium first, also Server Admin srvadmin), which version, and where the signed package is. The packages themselves live on the package server download.euzos.eu, shared by sandbox and production. Only a PC that got a download token from a profile server may download, and only a logged-in PC gets one. The security is in the package signature, not in the server or the URL: a lying server or CDN can make an installation fail, but never make the PC install anything other than a signed package of that app.

How do I…?

How does a PC find and install an app?

  1. GET /api/apps/<name> (public, no token): beschikbaar + name, version, size, SHA-256, description URLs and package URLs; or niet_beschikbaar. If the server hands out tokens, a line downloadbasis=https://download.euzos.eu/ follows.
  2. POST /api/apps/token?token=<pc-token> with app= and versie= → a download token (2 hours).
  3. GET https://download.euzos.eu/<app>/<version>/<FILE> with Authorization: Bearer <token>; Range resumes an interrupted download.
  4. The PC checks the description with SIGNPUB.TXT, the version against HAAL.TXT, that the description matches the catalogue exactly, and the SHA-256 and block hash of the package.

On the PC: apps catalog chromium shows what the server says; apps install chromium installs via the catalogue.

How do I put an app in the catalogue?

On the profile server (only via the CLI; there is no API to change the catalogue, and every change goes into the admin log):

euzos-profielserver --config <conf> app-set chromium --version <n> --size <bytes> \
    --sha256 <hex> --url https://download.euzos.eu/chromium/<n>/CHROMIUM.APP \
    [--url <mirror>/CHROMIUM.APP] [--package https://<…>/CHROMIUM.PAK]

tools/chromium/install.sh --create builds and signs the package and prints this command with version, size and SHA-256 filled in. app-set checks every field like the PC does and warns about a lower version. The admin page has the same (App catalog).

How do I publish a package on download.euzos.eu?

From the Mac: server/download/deploy/publiceer.sh <dir>/<NAME>.APP. It takes <NAME>.APP, .sig and the package named in pakket=, reads the version from the .sig, checks size and SHA-256, uploads to /srv/euzos-pakketten/<app>/<version>/ (never overwriting an existing version) and prints the app-set command.

How do I remove an app?

app-delete <name>; PCs then hear niet_beschikbaar.

How do I get a download token by hand (for tests)?

download-token <app> <version> on the profile server: a 2-hour token for account "beheer", recorded in the admin log.

How do I revoke a download token?

On the package server: sudo euzos-download revoke <jti> [comment] (adds the jti to the blocklist; old name intrek). The admin page's Download tokens page records the request and shows this command. A token lives at most 2 hours anyway.

How do I add the key of a new environment (e.g. PROD) to the package server?

On the profile VPS: download-key-create (refuses if the file exists) and note the printed line <kid> <public key>; add it to the package server's key list (/etc/euzos-download/sleutels.txt). Removing that line invalidates all tokens of that kid at once.

Why does my PC get 401 from the package server?

No token, a bad signature or an expired token (geen_token, handtekening, verlopen). 403 means revoked (ingetrokken) or a token for another app or version (ander_pad); 404 a path that does not match the pattern (pad). An older PC that skips downloadbasis= sends no token and gets 401.

Details

Catalogue fields: versie is the version in the signature (first 8 bytes of <NAME>.APP.sig); grootte and sha256 describe the package; beschrijving is the signed description URL (ends in /<NAME>.APP); pakket the package URL (empty: next to the description). At most 4 URLs of each: the first first, the rest are mirrors. Only https://, at most 512 characters. App names: a-z, 0-9, -, at most 8 characters (apps::valid_name). Throttled at 30 requests per minute per network.

Workplace server: when a PC asks for the catalogue from the network of a signed-in workplace server, two more lines follow: werkplek=https://<lan address>:8445/ and werkplek-tls=<SHA-256 of its SPKI>. The PC then tries the workplace server first (same paths, pinned TLS key, same token) and falls back to the catalogue URLs on any error.

Download token (ezdl1.<kid>.<app>.<version>.<exp>.<jti>.<account>.<sig>): kid = sbx-/prod-/lok- + 8 hex of the public key; exp Unix time (2 hours, download_token::DURATION); jti 32 random hex; account a keyed SHA-256 of the account id (not reversible); sig Ed25519 over EUZOS-downloadtoken-v1\0 + everything before the last dot. Only the current catalogue version gets a token, never an older one. Limits: 20 per account per hour (PER_ACCOUNT), 60 per network per hour (PER_NET).

Download key: an Ed25519 key per environment, only on the profile VPS (download_key_file, mode 0600/0640, never in git). Without it /api/apps/token is 404.

Server Admin: the app srvadmin only gets a download token for an account with admin rights (server admin role or organisation admin; workplace_admin::may_server_admin).

The package server (server/download, binary euzos-download) sits behind Caddy (forward_auth) on localhost and lets a request through only if: the method is GET/HEAD and the path is /<app>/<version>/<file>; the token's kid is known and its signature valid; exp has not passed and is at most 2 h + 5 min ahead; the jti is not on the blocklist; app and version match the path. Key list and blocklist are re-read within a second after a change. The journal logs IP, outcome, jti, account hash, kid, path and Range, never the token.

Reference

CLI commands

Profile server (euzos-profielserver):

CommandArgumentsWhat it does
apps—the catalogue (as GET /api/apps)
app-set<name> --version <n> --size <bytes> --sha256 <hex> --url <https://…/NAME.APP> [--url <mirror>]… [--package <https://…>]…add or replace an app
app-delete<name>remove an app
download-key-create—create this environment's download key; prints the line for the key list
download-key—show kid and public key
download-token<app> <version>a token for admin work and tests

Legacy names: app-zet, app-wis, downloadsleutel-maak, downloadsleutel, downloadtoken; flags --versie, --grootte, --pakket.

Package server (euzos-download):

CommandArgumentsWhat it does
start[--address <ip:port>] [--keys <file>] [--blocklist <file>]run the token check (default 127.0.0.1:8091)
revoke<jti> [comment]put a token on the blocklist (legacy intrek)
keys—list the known key ids (kid) (legacy sleutels)

Legacy flags: --adres, --sleutels, --zwarte-lijst.

Functions and modules

Function / moduleRole
euzos_profileserver::apps::list, one, valid_nameGET /api/apps, GET /api/apps/<name>
euzos_profileserver::download_token::fetchPOST /api/apps/token
euzos_profileserver::download_token::Key (create, read, kid, key_line, account_hash, token)the download key and token creation
euzos_profileserver::workplace::download_tokentokens for a workplace server (eze_ token)
server/download (euzos-download)the token check behind Caddy
Kernel: kernel/src/app_store.rs (catalog, install_catalog, Access), kernel/src/app_install.rs; euzos_install::apps::read_catalogthe PC side

Config files

Profile server configuration:

KeyMeaning
download_key_file (legacy download_sleutel_bestand)the Ed25519 download key; without it tokens are off
download_base (legacy download_basis)https://download.euzos.eu/; only together with download_key_file; gives the downloadbasis= line

Package server: /etc/euzos-download/sleutels.txt (per line <kid> <public key hex>, the keys of SBX and PROD; no secrets) and /etc/euzos-download/zwarte-lijst.txt (revoked jtis). Files on disk: /srv/euzos-pakketten/<app>/<version>/<FILE>.

On the PC: \EOS\FW\HAAL.TXT (last installed versions, the lower bound) and \EOS\FW\SIGNPUB.TXT (the public signing key).

On-disk config keys and typed confirmation words are English since 27-10-2026 (for example WIS-… → WIPE-…, omgeving= → environment=; docs/ENGLISH.md); the Dutch names stay accepted. The profile server's wire formats (pc line protocol, signed profile, signed phone messages, settings keys) stay Dutch.

API endpoints

MethodPathLegacy Dutch pathPurpose
GET/api/apps—the whole catalogue (public)
GET/api/apps/<name>—one app (public)
POST/api/apps/token?token=<pc-token>—a download token
POST/api/workplace/v1/download-token?token=eze_…/api/werkplek/v1/downloadtokena download token for a workplace server
GET, HEADhttps://download.euzos.eu/<app>/<version>/<FILE>—the package server (Bearer token)

Protocol messages and formats

GET /api/apps/chromium
beschikbaar                      (or: niet_beschikbaar + naam=…)
naam=chromium
versie=<n>
grootte=<bytes>
sha256=<64 hex>
beschrijving=https://…/CHROMIUM.APP      (1 to 4)
pakket=https://…/CHROMIUM.PAK            (0 to 4)
downloadbasis=https://download.euzos.eu/ (if tokens are on)
werkplek=https://<lan>:8445/             (from a workplace network)
werkplek-tls=<64 hex>

POST /api/apps/token?token=<pc-token>
app=chromium
versie=<n>
→ ok / token=ezdl1.… / verloopt=<Unix time> / duur=7200
→ 400 reden=ongeldig | 401 reden=token | 404 reden=onbekend | 404 (tokens off)
  | 429 reden=te_vaak + wacht= | 503

Package server answers: 200/206 (file), 401 geen_token|handtekening|verlopen (with WWW-Authenticate: Bearer), 403 ingetrokken|ander_pad, 404 pad.

See also