Files
MetaAppStore/Apps/MetaShare/rationale.md
T
Worph 39f82e1f96 Import the MetaMesh app family from Worph/AppStore
23 apps (MetaCore, the library/network/client tiers and 13 MetaFeeder*)
move out of the general-purpose Worph/AppStore into their own store so the
MetaMesh family releases on its own cadence.

- asset URLs repointed to cdn.jsdelivr.net/gh/Worph/MetaAppStore@main
- store scaffolding added (category/recommend/featured lists, licence,
  contributing, gitattributes)
- psd-source/meta-icons-v2 icon generator follows the apps

MetaMCP stays in Worph/AppStore: it is third-party metatool-ai software,
not part of MetaMesh.
2026-09-13 16:18:29 +00:00

3.5 KiB

MetaShare — Rationale

What deviation / exception is being requested

  1. metashare-app runs user: 0:0.
  2. It publishes host port 4001/tcp (libp2p).
  3. It mounts /DATA/AppData/metacore/meta-core — another app's AppData directory.
  4. Six HTTP paths bypass the SSO gate and are proxied straight to the backend: /health, /api/peers*, /api/peer/*, /api/file/*, /api/search* and /api/services.

Why it is necessary

  1. MetaShare writes its service registration into /meta-core/services/, a directory created and owned by MetaCore's root-running container.
  2. libp2p is not HTTP. Caddy is an HTTP reverse proxy and cannot carry it, and remote peers resolve this node's public multiaddr from the kad-DHT and dial it directly. Without a published, inbound-reachable TCP port the node can only make outbound connections and never serves bytes to the swarm. The app therefore carries the reserved needs-public-ip tag so a user behind CGNAT or the mesh-router tunnel can see the limitation before installing.
  3. /meta-core is the shared leader-election and service-discovery directory. MetaCore is a hard prerequisite of this app.
  4. Those are the federation surface: remote MetaShare peers call them to enumerate peers, resolve records, search, and fetch blocks. A remote peer is a machine client with no cookie jar and no way to complete an interactive OIDC redirect, so gating them makes the app unable to federate at all — which is its only function. Every other path, including the whole dashboard, stays behind the gate.

Security mitigations in place

  • Public ingress terminates at the AppShield sidecar (ghcr.io/yundera/appshield:2.0.9), which gates every path behind the PCS's Authelia SSO over OIDC. The backend carries no Caddy labels and publishes no HTTP port to the host, so it is reachable only from the pcs Docker network.

  • Every service declares cpu_shares, and the memory-heavy ones a hard mem_limit with memswap_limit equal to it (swap disabled, so the container is OOM-killed rather than pushing the host into swap).

  • Image tags are pinned; no :latest anywhere in the stack.

  • The bypassed paths are read-only federation endpoints scoped to content the user has explicitly shared. They expose no configuration, no dashboard and no write operation, and they serve exactly what this node already publishes to the public swarm over libp2p — so gating them would protect nothing that the DHT does not already carry.

  • The published port speaks libp2p only. libp2p transport is authenticated and encrypted (Noise) and peer identity is a public key, so an unauthenticated dial cannot read anything the node has not chosen to publish to the swarm. The HTTP API stays on expose: behind AppShield.

Alternatives considered and rejected

  • Proxy libp2p through Caddy. Not possible: Caddy fronts HTTP, and the DHT advertises a raw TCP multiaddr.
  • Outbound-only / relayed transport. Works for reachability but not for serving: a node nobody can dial contributes no bytes, which is the app's entire function.
  • Run as $PUID:$PGID. Fails writing into MetaCore's root-owned /meta-core/services/.

Data protection

MetaShare's own store lives under /DATA/AppData/metashare/{config,data}/, declared in x-compose-app.folders and archived by Maison on uninstall. Only content the user has explicitly shared is published to the swarm; nothing under /DATA/Documents, /DATA/Downloads or /DATA/Media is mounted into this container at all.