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.
This commit is contained in:
Worph
2026-09-13 16:18:29 +00:00
parent 998eba19f4
commit 39f82e1f96
145 changed files with 12964 additions and 1 deletions
+293
View File
@@ -0,0 +1,293 @@
name: metafeederprowlarr
# =============================================================================
# MetaFeeder · Prowlarr — a STANDALONE Prowlarr feeder for MetaMesh.
#
# Bridges your **Prowlarr** indexers — Torznab/Newznab, torrent AND usenet — into
# MetaMesh, so releases surface in **MetaWatch**. Prowlarr is the separate store
# app (container `prowlarr:9696`) that aggregates the indexers.
#
# (The Tribler source used to ride in this same app; it was extracted into its
# own image + app — install **MetaFeeder · Tribler** for decentralized IPv8
# discovery. This app is now Prowlarr/Torznab-only.)
#
# Split out of the MetaGateway stack so the sources stay modular. Self-contained
# for enrichment: ships its own filename-parser + tmdb plugins.
#
# It needs, all reached over the shared `pcs` network:
# 1. the **Prowlarr** store app (`prowlarr:9696`) — the indexer source.
# 2. the shared **MetaCore** app (`metacore-app:9000`) — where resolved
# records + TMDB posters are stored; the shared **MetaShare** app then
# announces them to the swarm.
# The **MetaGateway** app must list this feeder's URL
# (`http://metafeederprowlarr-feeder:8080`) in its feeders config so it
# discovers + queries it (MetaGateway, MetaCore and this feeder share `pcs`).
#
# Everything is scoped under the `metafeederprowlarr-*` prefix + the
# per-stack `metafeederprowlarr` network + /DATA/AppData/metafeederprowlarr/
# data root, so it installs alongside the other Meta* apps with zero collisions.
# =============================================================================
services:
# ---------------------------------------------------------------------------
# metafeederprowlarr-feeder — the feeder (meta-feeder-torznab) running the
# Prowlarr/Torznab source. The gateway reaches it directly on `pcs` for
# discovery/query/compute; the human configures it through the AppShield gate
# below.
# ---------------------------------------------------------------------------
metafeederprowlarr-feeder:
# Image name is `meta-feeder-torznab` — the repo (and therefore the ghcr
# package, published as ${{ github.repository }}) was renamed. The old
# `meta-feeder-indexer` package still exists but is frozen at 1.0.23 and
# receives no further pushes. The APP keeps the `metafeederprowlarr` name.
image: ghcr.io/worph/meta-feeder-torznab:1.0.26
cpu_shares: 30
container_name: metafeederprowlarr-feeder
# Hard RAM cap, swap disabled (memswap_limit == mem_limit) → OOM
# instead of swap. Mirrors the dev sub-stack limits.
mem_limit: 512m
memswap_limit: 512m
hostname: metafeederprowlarr-feeder
restart: unless-stopped
user: "0:0"
expose:
- 8080
environment:
# INFRA-ONLY env (the "config: no env if in webui" rule). Operator config —
# Prowlarr indexers + API key, TMDB token / language, meta-core URL — is
# read from the persisted config.json (this feeder's config page behind the
# AppShield gate); env is only a deprecated first-boot seed. These env vars
# are wiring only: the enrichment sidecars, the enrich callback, the peer id
# and Prowlarr paging. meta-core defaults to the pcs
# `http://metacore-app:9000`; Prowlarr is reached as `prowlarr:9696`.
RUST_LOG: "info,meta_feeder=info,meta_feeder::store=debug"
# The peer id stamped into provenance.gateway_peer on every record this
# feeder self-publishes. It names the GATEWAY this feeder serves — not the
# feeder itself — so records are attributed to the gateway that fronts them
# (analytics group by it). Without it, it falls back to HOSTNAME.
META_GATEWAY_PEER_ID: "metagateway"
FILENAME_PARSER_URL: "http://metafeederprowlarr-filename-parser:8080"
TMDB_PLUGIN_URL: "http://metafeederprowlarr-tmdb:8080"
META_FEEDER_CALLBACK_URL: "http://metafeederprowlarr-feeder:8080/enrich/callback"
# LOAD-BEARING at meta-feeder-indexer:1.0.9 — NOT a restatement of the
# default: that build defaults the page size to 100. 20 is the pacing
# choice (results stream 20-at-a-time). META_GATEWAY_PROWLARR_MAX_DEPTH
# was dropped — its 500 did match the default.
META_GATEWAY_PROWLARR_PAGE_SIZE: "20"
TZ: "$TZ"
volumes:
# Persist feeder config (config.json saved via the config UI) + redb cache.
# Transient librqbit downloads go to the container's /tmp (off backup).
- ${DATA_ROOT:-/DATA}/AppData/metafeederprowlarr/state:/data/meta-feeder:rw
healthcheck:
test: ["CMD", "curl", "-sf", "http://localhost:8080/health"]
interval: 5s
timeout: 3s
retries: 10
start_period: 5s
depends_on:
# service_started (not _healthy): the plugin images ship no healthcheck.
metafeederprowlarr-filename-parser:
condition: service_started
metafeederprowlarr-tmdb:
condition: service_started
networks:
- metafeederprowlarr
- pcs
# ---------------------------------------------------------------------------
# Bundled enrichment plugins (self-contained). filename-parser per file; tmdb
# once per torrent — tmdb writes posters/backdrops to the gateway core's WebDAV.
# No healthcheck: these plugin images don't ship one (curl absent).
# ---------------------------------------------------------------------------
metafeederprowlarr-filename-parser:
image: ghcr.io/worph/metamesh-plugin-filename-parser:1.0.2
cpu_shares: 30
container_name: metafeederprowlarr-filename-parser
# Hard RAM cap, swap disabled (memswap_limit == mem_limit) → OOM
# instead of swap. Mirrors the dev sub-stack limits.
mem_limit: 256m
memswap_limit: 256m
hostname: metafeederprowlarr-filename-parser
restart: unless-stopped
expose:
- 8080
environment:
EMIT_TITLE_TAGS: "true"
networks:
- metafeederprowlarr
metafeederprowlarr-tmdb:
image: ghcr.io/worph/metamesh-plugin-tmdb:1.0.2
cpu_shares: 30
container_name: metafeederprowlarr-tmdb
# Hard RAM cap, swap disabled (memswap_limit == mem_limit) → OOM
# instead of swap. Mirrors the dev sub-stack limits.
mem_limit: 384m
memswap_limit: 384m
hostname: metafeederprowlarr-tmdb
restart: unless-stopped
expose:
- 8080
environment:
# Posters land in the gateway core (over pcs) so the ingester seeds them.
# LOAD-BEARING at metamesh-plugin-tmdb:1.0.0 — do NOT remove.
# Newer source derives WebDAV from the metaCoreUrl passed on each /process
# (GET /urls -> webdavUrlInternal), which is why the dev compose omits it. The
# PUBLISHED image predates that: without this var it logs "WebDAV client
# unavailable" and silently writes no posters/backdrops, so every record then
# fails meta-watch's poster gate. Drop only after re-tagging the plugin.
WEBDAV_URL: "http://metacore-app:9000/webdav"
volumes:
- ${DATA_ROOT:-/DATA}/AppData/metafeederprowlarr/tmdb-cache:/cache
networks:
- metafeederprowlarr
- pcs
# ---------------------------------------------------------------------------
# AppShield gate — the feeder's config UI (set the Prowlarr key, TMDB token)
# behind Yundera OIDC SSO. container_name == subdomain prefix. The gateway
# still reaches the feeder directly on `pcs` (this gate is for the human only);
# index → /config.
# ---------------------------------------------------------------------------
metafeederprowlarr:
image: ghcr.io/yundera/appshield:2.0.9
cpu_shares: 80
container_name: metafeederprowlarr
hostname: metafeederprowlarr
restart: unless-stopped
user: "0:0"
expose:
- 80
environment:
OIDC_REGISTRAR_URL: "http://auth-registrar:9092"
REDIRECT_HOST_SUFFIXES: "${APP_DOMAIN},${APP_PUBLIC_IP_DASH}.nip.io,${APP_PUBLIC_IP_DASH}.sslip.io"
BACKEND_HOST: "metafeederprowlarr-feeder"
BACKEND_PORT: "8080"
LISTEN_PORT: "80"
labels:
caddy_0: metafeederprowlarr-${APP_DOMAIN}
caddy_0.import: gateway_tls
caddy_0.reverse_proxy: "{{upstreams 80}}"
caddy_1: metafeederprowlarr-${APP_PUBLIC_IP_DASH}.nip.io
caddy_1.import: gateway_tls
caddy_1.reverse_proxy: "{{upstreams 80}}"
caddy_2: metafeederprowlarr-${APP_PUBLIC_IP_DASH}.sslip.io
caddy_2.reverse_proxy: "{{upstreams 80}}"
depends_on:
- metafeederprowlarr-feeder
networks:
- metafeederprowlarr
- pcs
networks:
metafeederprowlarr:
name: metafeederprowlarr
driver: bridge
pcs:
name: ${APP_NET:-pcs}
external: true
x-casaos:
architectures:
- amd64
- arm64
author: Worph Team
category: Media
developer: Aptero Team
main: metafeederprowlarr
webui_port: 80
index: /config
description:
en_us: |
**A standalone torrent + usenet feeder for the MetaMesh network.**
MetaFeeder · Prowlarr bridges your **Prowlarr** indexers
(Torznab/Newznab — torrent *and* usenet) into MetaMesh, so releases surface
in **MetaWatch**. It's the torrent/usenet source tier, split out of
MetaGateway so you can run only the feeders you want.
**Self-contained:** ships its own filename-parser + TMDB enrichment, so each
release gets a clean title, poster and plot.
**Source:**
- **Prowlarr** — Torznab/Newznab indexers, torrent or usenet (reached as
`prowlarr` on the shared network).
**Want decentralized discovery too?** Install **MetaFeeder · Tribler** — the
Tribler source now lives in its own app.
**Also requires:** **MetaGateway** — its meta-core stores the resolved
records and announces them to the swarm. The gateway must list this feeder
in its config.
fr_fr: |
**Un feeder torrent + usenet autonome pour le réseau MetaMesh.**
MetaFeeder · Prowlarr connecte vos indexeurs **Prowlarr**
(Torznab/Newznab — torrent *et* usenet) à MetaMesh pour qu'ils apparaissent
dans **MetaWatch**. C'est la couche de sources torrent/usenet, détachée de
MetaGateway pour n'exécuter que les feeders souhaités.
**Autonome :** embarque ses propres plugins filename-parser + TMDB.
**Source :** l'app **Prowlarr** (indexeurs Torznab/Newznab, torrent ou
usenet, atteinte comme `prowlarr`).
**Envie de découverte décentralisée ?** Installez **MetaFeeder · Tribler** —
la source Tribler est désormais une app dédiée.
**Nécessite aussi :** l'app **MetaGateway** (son meta-core stocke et annonce
les enregistrements).
tagline:
en_us: Standalone Prowlarr/Torznab (torrent + usenet) feeder for MetaMesh
fr_fr: Feeder Prowlarr/Torznab (torrent + usenet) autonome pour MetaMesh
title:
en_us: MetaFeeder · Prowlarr
icon: https://cdn.jsdelivr.net/gh/Worph/MetaAppStore@main/Apps/MetaFeederProwlarr/icon.png
thumbnail: https://cdn.jsdelivr.net/gh/Worph/MetaAppStore@main/Apps/MetaFeederProwlarr/thumbnail.png
store_app_id: metafeederprowlarr
is_uncontrolled: false
tips:
before_install:
en_us: |
**Install order:** install **MetaGateway** first, plus the **Prowlarr**
store app (Torznab/Newznab).
**After installing this app:**
1. In **Prowlarr**: complete its first-run wizard, add one or more
indexers (torrent or usenet), then copy the **API Key**
(Settings → General).
2. Open this app's config UI (the dashboard link). Paste the Prowlarr key
into the indexer's API-key field; optionally set a TMDB v4 token for
posters. Save — the feeder reloads automatically.
3. In **MetaGateway**, make sure this feeder is listed in its feeders
config (`http://metafeederprowlarr-feeder:8080`) so it gets
discovered.
**Authentication:** the config UI is protected by Yundera's Authelia (OIDC).
# Maison (Yundera dashboard) configuration. Read in preference to x-casaos.
# schema_version 2 is required for `folders`: an older Maison refuses the app
# outright rather than starting it without its directories.
x-compose-app:
schema_version: 2
# Created and chowned by Maison before any image is pulled, before any hook
# runs and before the containers start — on the first boot and every one after.
# Compose would otherwise create a missing bind source as a root-owned dir.
folders:
- path: /DATA/AppData/metafeederprowlarr/state
user: $PUID
group: $PGID
- path: /DATA/AppData/metafeederprowlarr/tmdb-cache
user: $PUID
group: $PGID
# Same string as the caddy_0 label, so the tile link and the route agree.
webui-host: metafeederprowlarr-${domain}
webui-path: "/config"
Binary file not shown.

After

Width:  |  Height:  |  Size: 136 KiB

+47
View File
@@ -0,0 +1,47 @@
# MetaFeeder · Prowlarr — Rationale
## What deviation / exception is being requested
`metafeederprowlarr-feeder` runs `user: 0:0`.
## Why it is necessary
The feeder publishes its resolved records to the shared MetaCore over HTTP and writes its
own service registration and plugin artwork through MetaCore's WebDAV endpoint. Those
writes land in directories created and owned by MetaCore's root-running container; a
uid-1000 process is refused. The feeder image also runs a small supervised process group
(fetcher + enrichment plugin clients) that expects to be able to signal its children.
## 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 feeder carries no
Caddy labels and publishes no host port, so it is reachable only from the `pcs` Docker
network.
- The container mounts **no user directories** — not `/DATA/Documents`, `/DATA/Downloads`,
`/DATA/Media` or `/DATA/Gallery`. Its only bind is its own state under
`/DATA/AppData/metafeederprowlarr/`, declared in `x-compose-app.folders` and owned `$PUID:$PGID`.
- `cpu_shares` set on every service; image tags pinned; no `:latest`.
- The enrichment sidecars (`-filename-parser`, `-tmdb`) run **unprivileged** — no `user:`
field, so Yundera starts them as `$PUID:$PGID`. `-filename-parser` is on the app-private
`metafeederprowlarr` bridge only; `-tmdb` also joins `pcs` because MetaCore calls back into
it, and it carries an app-prefixed `container_name` so it cannot collide with another
app's service in the shared DNS namespace. Neither carries Caddy labels or publishes a
host port.
## Alternatives considered and rejected
- **Run as `$PUID:$PGID`.** Writes into MetaCore's root-owned `/meta-core` tree and through
its WebDAV endpoint fail, and the feeder starts but silently publishes nothing.
- **Have MetaCore relax the ownership of its shared directory.** That would loosen
permissions for every MetaMesh app at once, which is strictly worse than one root
container with no user-data mounts.
- **Drop privileges after startup inside the image.** Upstream change; tracked, not
available in the shipped image.
## Data protection
The feeder holds no user media. Its entire state — configuration, cursor position, and
(where applicable) the TMDB cache — lives under `/DATA/AppData/metafeederprowlarr/`, which is the unit
Maison archives on uninstall and restores from backup, so an uninstall/reinstall with "keep
user data" resumes where it left off rather than re-indexing from scratch.
Binary file not shown.

After

Width:  |  Height:  |  Size: 136 KiB