feat(deb): package the server, and ask the questions that fail silently
DR-015, DR-016. §8 already shipped a static binary and an optional container; this adds the third form, and it packages the SAME binary the musl job proved static rather than building its own. Two builds of the same commit could diverge, and the whole point of that assertion is that the artifact an operator installs is the one that was checked. Built with dpkg-deb from an explicit staging tree rather than cargo-deb. debconf's `config` script and `templates` live in the control archive next to the maintainer scripts, and controlling that archive directly beats discovering what a wrapper will copy into it. dpkg-dev is on every Debian builder, so this adds no build dependency. Why debconf at all: two settings fail SILENTLY when unset. Without JRAY_TMDB_API_KEY every upload stays `pending` and is never listed; without JRAY_TRUSTED_PROXIES the X-Forwarded-For header is ignored, so every client shares one rate-limit bucket and every abuse report points at the proxy. Both leave a server that works and is quietly doing the wrong thing — the worst thing to leave to a README nobody reads. Three properties, each a way packaging usually goes wrong: The generated config is NOT a dpkg conffile. It is written from the debconf answers, so shipping it as one would make dpkg prompt on every upgrade about changes the package itself had made. Hand edits survive. postinst rewrites only the keys debconf manages; comments, ordering and any other setting are left alone. A blank key on reconfigure keeps the existing one. Otherwise pressing Enter through a dpkg-reconfigure would unpublish every future upload. The seeding guard is worth its comment, because the obvious version is wrong twice over. `config` seeds unanswered questions from the env file so a reconfigure shows what is actually in force. Seeding unconditionally overwrites a preseed — debconf-set-selections marks what it sets as seen — so every unattended install would quietly reconfigure itself back to whatever was on disk. Guarding on an empty value does not work either: server-id and bind carry template Defaults, so db_get returns "localhost" for a question nobody answered. The test is the `seen` flag, which is the actual question being asked. Purge keeps the database, knowingly departing from the expectation that purge removes everything. Manifests are the output of real CV compute on media the operator may no longer have, and §8 says federation is explicitly not a backup. Destroying that during an `apt purge` is not a trade worth making for tidiness; postrm names the path instead. The nginx example is documentation, not installed configuration. The proxy usually runs on a different host from the server, so a file dropped into this machine's nginx would be in the wrong place — and §8 leaves the edge to the operator deliberately. Verified by running it, not by reading it: a full lifecycle in a bookworm container — build, preseeded install, mode-600 env file, key absent from debconf's database afterwards, `systemd-analyze verify` on the unit, the installed binary answering /health and /ready, reconfigure preserving both the key and an unmanaged setting, and purge leaving the database. It failed on the seeding bug above the first time, which is why that guard exists. CI runs the same checks against every build. TRACES: DR-015, DR-016 | PR-004
This commit is contained in:
@@ -1510,6 +1510,13 @@ addresses.
|
||||
|
||||
- Ship a **single static binary** (musl target) plus the SQLite file. Optional
|
||||
container image, but neither Docker nor Compose should be required.
|
||||
- Ship a **Debian package** as well (DR-015). It is a third distribution form
|
||||
alongside the raw binary and the container, not a replacement for either: it
|
||||
packages the *same* musl binary CI has already proved static, so what an
|
||||
operator installs is byte-identical to the artifact that was verified.
|
||||
Published to the Gitea Debian registry, so `apt install jray-server` and
|
||||
ordinary upgrades work, and attached to the release for operators who would
|
||||
rather not add a third-party apt source.
|
||||
- Put all database access behind a **thin repository trait** rather than
|
||||
scattering queries through handlers. This is what keeps the Turso/Postgres
|
||||
options above cheap, and it localises the single-writer serialization
|
||||
@@ -1532,6 +1539,46 @@ addresses.
|
||||
plain file copy of a live WAL database). Manifests represent real CV
|
||||
compute; federation (§9a) gives partial resilience but is not a backup.
|
||||
|
||||
### First-run configuration — DR-016
|
||||
|
||||
The settings an operator must get right are not discoverable from the binary,
|
||||
and two of them fail *silently* when unset: without `JRAY_TMDB_API_KEY` every
|
||||
upload stays `pending` and is never listed, and without `JRAY_TRUSTED_PROXIES`
|
||||
the `X-Forwarded-For` header is ignored, so every client shares one rate-limit
|
||||
bucket and every abuse report points at the proxy. Both produce a working
|
||||
server that is quietly doing the wrong thing — the worst kind of default to
|
||||
leave to a README.
|
||||
|
||||
So the package **asks**, at install time, via debconf: public hostname, listen
|
||||
address, trusted proxies, TMDB key, contact, and whether to publish the peer
|
||||
directory. It is re-runnable with `dpkg-reconfigure jray-server`, and
|
||||
preseedable for unattended installs.
|
||||
|
||||
Three properties this has to hold, each of which is a way packaging usually
|
||||
goes wrong:
|
||||
|
||||
- **The generated config is not a dpkg conffile.** It is written from the
|
||||
debconf answers, so shipping it as a conffile would make dpkg prompt on every
|
||||
upgrade about changes the package itself had made.
|
||||
- **Hand edits survive.** Only the keys debconf manages are rewritten;
|
||||
comments, ordering and any other setting are left alone, so editing the file
|
||||
directly and running `dpkg-reconfigure` later do not fight.
|
||||
- **A blank API key on reconfigure keeps the existing one.** Otherwise pressing
|
||||
Enter through a reconfigure would silently unpublish every future upload.
|
||||
|
||||
The database is **not** removed on purge, which knowingly departs from the
|
||||
usual expectation. Manifests are the output of real CV compute on media the
|
||||
operator may no longer have, and federation is explicitly not a backup;
|
||||
destroying that during an `apt purge` is not a trade worth making for
|
||||
tidiness. `postrm` says where the file is and leaves the decision to the
|
||||
operator.
|
||||
|
||||
An example nginx site ships in `/usr/share/doc/jray-server/examples/` rather
|
||||
than being installed into any nginx configuration directory. The proxy commonly
|
||||
runs on a *different* host from the server, so a file dropped into this
|
||||
machine's nginx would be in the wrong place — and §8 leaves the edge to the
|
||||
operator deliberately.
|
||||
|
||||
---
|
||||
|
||||
## 9. JRay plugin integration
|
||||
|
||||
Reference in New Issue
Block a user