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.
3.5 KiB
MetaShare — Rationale
What deviation / exception is being requested
metashare-apprunsuser: 0:0.- It publishes host port
4001/tcp(libp2p). - It mounts
/DATA/AppData/metacore/meta-core— another app's AppData directory. - 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
- MetaShare writes its service registration into
/meta-core/services/, a directory created and owned by MetaCore's root-running container. - 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-iptag so a user behind CGNAT or the mesh-router tunnel can see the limitation before installing. /meta-coreis the shared leader-election and service-discovery directory. MetaCore is a hard prerequisite of this app.- 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 thepcsDocker network. -
Every service declares
cpu_shares, and the memory-heavy ones a hardmem_limitwithmemswap_limitequal to it (swap disabled, so the container is OOM-killed rather than pushing the host into swap). -
Image tags are pinned; no
:latestanywhere 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.