name: metacore services: # Backend service. Reachable on the pcs network as `metacore-app`. # Public ingress goes through the `metacore` hash-lock proxy below — this # service has no public Caddy labels and no exposed host ports. metacore-app: image: ghcr.io/worph/meta-core:1.0.20 container_name: metacore-app # Hard RAM cap, swap disabled (memswap_limit == mem_limit) → OOM # instead of swap. Both values must move together or swap comes back. # # Raised 768m -> 1536m (2026-08-26): on watch.nsl.sh the Redis working set # ran at 73-97% of 768m, i.e. one indexing burst away from an OOM kill that # takes the record store (and every service reading it) down with it. # 1536m puts steady state near 30%. mem_limit: 1536m memswap_limit: 1536m hostname: metacore-app restart: unless-stopped privileged: true cpu_shares: 50 expose: - 80 volumes: # Shared infrastructure state (leader election, Redis dump, service discovery). # Lives inside /DATA/AppData/metacore/ so CasaOS archives it on uninstall. - ${DATA_ROOT:-/DATA}/AppData/metacore/meta-core:/meta-core:rw # User's media directories — bind-mounted directly (no parent named volume, # so `docker volume rm` cannot recurse into these and wipe host data). - ${DATA_ROOT:-/DATA}/Downloads:/files/watch/downloads:ro - ${DATA_ROOT:-/DATA}/Media:/files/watch/media:ro # Application cache storage - ${DATA_ROOT:-/DATA}/AppData/metacore/cache:/data/cache # Plugin output — gateway/feeder-published artwork (posters, backdrops) # lands here via meta-core's WebDAV endpoint, and every record's # `filePath` points into it. This MUST be a bind mount: without it the # directory is the container's writable layer, so any `docker compose # up -d` that recreates metacore-app silently deletes every poster while # Redis keeps pointing at them. That is exactly what happened on # watch.nsl.sh on 2026-08-03 (270 files → 0), and it is the reason a # fraction of poster CIDs 404 with a healthy-looking record behind them. # metacore-app is the only service that mounts /files; the gateway and # feeders write here over HTTP, so this one mount covers all of them. - ${DATA_ROOT:-/DATA}/AppData/metacore/plugin:/files/plugin:rw environment: - BASE_URL=https://metacore-$APP_DOMAIN - TZ=$TZ # Runs as root for nginx, Redis, rclone mounts user: 0:0 healthcheck: test: ["CMD", "curl", "-sf", "http://localhost/health"] interval: 5s timeout: 3s retries: 30 start_period: 30s networks: - pcs # OIDC perimeter for the MetaCore dashboard. Self-registers as an OIDC client # with the platform's auth-registrar on first login (no secrets to manage). # # Naming convention (per appshield + auth-registrar): the proxy's # container_name MUST equal the URL-prefix of the public hostname, because the # registrar's redirect-URI allowlist is "" or "-*". # Our public URL is `metacore-${APP_DOMAIN}`, so the proxy container is named # `metacore` and the backend takes the `-app` suffix. metacore: image: ghcr.io/yundera/appshield:2.0.9 cpu_shares: 80 container_name: metacore hostname: metacore restart: unless-stopped user: "0:0" expose: - 80 environment: OIDC_REGISTRAR_URL: "http://auth-registrar:9092" BACKEND_HOST: "metacore-app" BACKEND_PORT: "80" LISTEN_PORT: "80" REDIRECT_HOST_SUFFIXES: "${APP_DOMAIN},${APP_PUBLIC_IP_DASH}.nip.io,${APP_PUBLIC_IP_DASH}.sslip.io" depends_on: - metacore-app labels: # Only /health bypasses hash-lock — inter-service traffic (/meta/*, # /webdav/*, /file/cid) flows over the pcs network from sibling apps # (metasort-app, metafuse-app, metastremio) directly to metacore-app # and never traverses the public proxy. # ---- metacore-${APP_DOMAIN} (gateway TLS) ---- caddy_0: metacore-${APP_DOMAIN} caddy_0.import: gateway_tls caddy_0.0_handle: "/health" caddy_0.0_handle.reverse_proxy: "metacore-app:80" caddy_0.1_handle: "" caddy_0.1_handle.reverse_proxy: "{{upstreams 80}}" # ---- metacore-IP.nip.io (gateway TLS) ---- caddy_1: metacore-${APP_PUBLIC_IP_DASH}.nip.io caddy_1.import: gateway_tls caddy_1.0_handle: "/health" caddy_1.0_handle.reverse_proxy: "metacore-app:80" caddy_1.1_handle: "" caddy_1.1_handle.reverse_proxy: "{{upstreams 80}}" # ---- metacore-IP.sslip.io (Let's Encrypt) ---- caddy_2: metacore-${APP_PUBLIC_IP_DASH}.sslip.io caddy_2.0_handle: "/health" caddy_2.0_handle.reverse_proxy: "metacore-app:80" caddy_2.1_handle: "" caddy_2.1_handle.reverse_proxy: "{{upstreams 80}}" networks: - pcs networks: pcs: name: ${APP_NET:-pcs} external: true x-casaos: architectures: - amd64 - arm64 author: Worph Team category: Media developer: Aptero Team description: en_us: | **The infrastructure foundation for the MetaMesh media management ecosystem.** MetaCore provides the shared services that power all MetaMesh applications: distributed leader election, Redis database, WebDAV file serving, remote mount management, and service discovery. **Key Features:** - **Leader Election** - Automatic flock-based leader election with failover support - **Redis Database** - Centralized metadata storage for all MetaMesh services - **WebDAV File Serving** - Cached file access for all services via HTTP - **Mount Management** - Add NFS, SMB, and rclone remote mounts from the dashboard - **File Watcher** - Monitors folders and notifies services of new files - **Metadata Editor** - Browse and edit file metadata stored in Redis - **Service Discovery** - Automatic registration and discovery of MetaMesh services - **OIDC Single Sign-On** - Dashboard protected by Yundera's built-in Authelia (auto-registered, no secrets to configure) **Install this FIRST** before MetaSort, MetaFuse, or MetaStremio. **Dashboard Features:** Service health, file watchers, mount management, metadata editor, KV browser fr_fr: | **La fondation d'infrastructure pour l'ecosysteme de gestion de medias MetaMesh.** MetaCore fournit les services partages qui alimentent toutes les applications MetaMesh : election de leader distribuee, base de donnees Redis, service de fichiers WebDAV, gestion de montages distants et decouverte de services. **Fonctionnalites Cles:** - **Election de Leader** - Election automatique basee sur flock avec support de basculement - **Base de Donnees Redis** - Stockage centralise des metadonnees pour tous les services - **Service de Fichiers WebDAV** - Acces aux fichiers en cache via HTTP - **Gestion des Montages** - Ajout de montages NFS, SMB et rclone depuis le tableau de bord - **Surveillance de Fichiers** - Surveille les dossiers et notifie les services des nouveaux fichiers - **Editeur de Metadonnees** - Parcourir et editer les metadonnees stockees dans Redis - **Decouverte de Services** - Enregistrement et decouverte automatiques des services - **SSO OIDC** - Tableau de bord protege par l'Authelia integre de Yundera (auto-enregistre, aucun secret a configurer) **Installez ceci EN PREMIER** avant MetaSort, MetaFuse ou MetaStremio. tagline: en_us: MetaMesh infrastructure - Leader election, Redis, WebDAV, and service discovery fr_fr: Infrastructure MetaMesh - Election de leader, Redis, WebDAV et decouverte de services title: en_us: MetaCore icon: https://cdn.jsdelivr.net/gh/Worph/MetaAppStore@main/Apps/MetaCore/icon.png screenshot_link: - https://cdn.jsdelivr.net/gh/Worph/MetaAppStore@main/Apps/MetaCore/screenshot-1.png - https://cdn.jsdelivr.net/gh/Worph/MetaAppStore@main/Apps/MetaCore/screenshot-2.png - https://cdn.jsdelivr.net/gh/Worph/MetaAppStore@main/Apps/MetaCore/screenshot-3.png thumbnail: https://cdn.jsdelivr.net/gh/Worph/MetaAppStore@main/Apps/MetaCore/thumbnail.png index: / store_app_id: metacore main: metacore is_uncontrolled: false tips: before_install: en_us: | **MetaCore is the foundation for the MetaMesh ecosystem.** Install this FIRST before MetaSort, MetaFuse, or MetaStremio. **What MetaCore can see:** it mounts your **`/DATA/Downloads`** and **`/DATA/Media`** folders **read-only** so it can watch them for new files and index what it finds. It cannot modify, rename or delete anything in them. Everything it writes stays in `/DATA/AppData/metacore/`. See `rationale.md` for the full breakdown. **Authentication:** The dashboard is protected by Yundera's built-in Authelia via OIDC. Sign in with your existing Yundera account when you open the dashboard for the first time. **After installation:** 1. Open the dashboard at `https://metacore-$APP_DOMAIN/` 2. Sign in via the Authelia portal that appears 3. Install MetaSort, MetaFuse, or MetaStremio as needed # 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/metacore/meta-core user: $PUID group: $PGID - path: /DATA/AppData/metacore/cache user: $PUID group: $PGID - path: /DATA/AppData/metacore/plugin user: $PUID group: $PGID - path: /DATA/AppData/metacore/plugin/share user: $PUID group: $PGID # Same string as the caddy_0 label, so the tile link and the route agree. webui-host: metacore-${domain} webui-path: "/"