Updated config

This commit is contained in:
Worph
2026-09-30 12:03:18 +02:00
parent e53be5655e
commit 21df7e9910
15 changed files with 718 additions and 29 deletions
+59
View File
@@ -0,0 +1,59 @@
# MetaRead (shared backend) — Rationale
## What deviation / exception is being requested
1. `metaread-app` is **publicly routed with no AppShield sidecar**. It carries the
`caddy_*` labels itself.
2. `metaread-search` runs `user: 0:0` and publishes host port `4006/tcp` (libp2p).
3. The compose top-level `name:` is `metaread`, the same project id as the self-contained
`MetaRead` app in this store.
## Why it is necessary
1. meta-read has its **own** authentication: a secp256k1 keypair proven by signing a
challenge, with invite-only signup. Its router gates deny-by-default: a route not in
`open_routes()` answers 401. The open set is `/health`, `/api/config`, the
challenge/token pair, `/api/invite/check/:token` and `/api/image/:cid`. That is the "app's
own built-in auth" alternative the security checklist accepts. AppShield in front added a
second login and an OIDC redirect on every cover fetch, because `<img src>` cannot carry
an Authorization header. It also left the service worker's offline cache at the mercy of
a session cookie.
2. libp2p is not HTTP. Caddy cannot proxy it, and remote peers dial the advertised
multiaddr directly, so the port must be published and reachable inbound. The app carries
the reserved `needs-public-ip` tag.
3. The two MetaRead variants are alternatives, not companions. They share the project id
and the same `/DATA/AppData/metaread/` paths, so installing one over the other reuses the
same data. Only one may be installed at a time.
## Security mitigations in place
- meta-read's signature-challenge login is on by default, and signup is invite-only, so a
stranger reaching the public hostname cannot create an account.
- The `metaread-search` dashboard *is* behind an AppShield sidecar
(`ghcr.io/yundera/appshield:2.0.9`) with Authelia SSO; only the reader itself uses its own
gate.
- `metaread-app` runs unprivileged as `1000:1000` with a 512 MB hard memory cap and swap
disabled.
- The only published port is raw libp2p TCP; no HTTP port is published to the host.
- No user directories are mounted: no `/DATA/Documents`, `/DATA/Downloads`, `/DATA/Media`
or `/DATA/Gallery`.
- `cpu_shares` on every service; image tags pinned.
## Alternatives considered and rejected
- **AppShield in front of `metaread-app`.** Two identities for one user, plus the cover and
service-worker costs above.
- **Bundle a private MetaCore/MetaShare.** That is the self-contained `MetaRead` app. On a
box that already runs them, it doubles the memory footprint. It also gives the reader an
identity, a User Data Layer and a catalogue separate from MetaWatch's on the same box.
- **A distinct project id so both variants coexist.** They would fight over the same public
hostnames, the same `/DATA/AppData/metaread/` paths and host port 4006.
## Data protection
My List, Continue Reading, the session key and the invite book persist in
`/DATA/AppData/metaread/data`. The recovered cover blockstore and language prefs persist in
`/DATA/AppData/metaread/search-data`. Both are declared in `x-compose-app.folders` and
archived by Maison on uninstall. Because both MetaRead variants use those paths, switching
between them keeps the user's data. The MetaCore and MetaShare state this variant reads
belongs to those apps and is archived with them.