# FabledCurator Self-hosted media curation — gallery, ML tagging, and subscription-driven downloading in one app. Part of the FabledSword family. Combines what was [ImageRepo](https://git.fabledsword.com/bvandeusen/ImageRepo) (gallery, ML, importer) and [GallerySubscriber](https://git.fabledsword.com/bvandeusen/GallerySubscriber) (gallery-dl wrapper, subscriptions, credential capture) into a single product. ## Status In production. `main` is continuously deployed — every merge to `main` builds and publishes `:latest` images, so whatever is on `main` is what is running. Day-to-day work happens on `dev`, which publishes `:dev` images. ## What's in here Five deployable pieces, built by `.forgejo/workflows/build.yml`: | Piece | Built from | Image | Role | | --- | --- | --- | --- | | **Web / workers** | `Dockerfile` | `fabledcurator` | Quart API + the built Vue SPA in one image. `entrypoint.sh` picks the role: `web`, `worker`, `scheduler`. The `maintenance-long` service is a second `worker` pinned to the long-running maintenance queue. | | **ML worker** | `Dockerfile.ml` | `fabledcurator-ml` | Same app, plus `requirements-ml.txt` — tagging and embedding models that run in-container. | | **GPU agent** | `agent/Dockerfile` | `fabledcurator-agent` | Optional desktop-GPU worker (`agent/`). Leases jobs over **HTTP only** — never touches the database or Redis. Run it for a burst, stop it to reclaim the card. See `agent/README.md`. | | **Firefox extension** | `extension/` | signed XPI | MV3 extension: pushes platform session cookies into FC and adds a creator as a Source in one click. AMO-signed on both `dev` and `main` (one signature per extension change, shared by the two channels), bundled into that channel's web image and served from Settings → Maintenance. See `extension/README.md`. | | **Data** | — | `pgvector/pgvector:pg16`, `redis:7-alpine` | Postgres with pgvector for embeddings; Redis as the Celery broker. | ## Quick start For local development and testing, just: ```bash docker compose up -d # UI: http://localhost:8080 ``` That uses sane dev defaults baked into `docker-compose.yml` and the dev override (`docker-compose.override.yml`, auto-merged) — local builds, DEBUG logging, exposed Postgres + Redis ports on the host. No `.env` required. For a production-like deployment, override the dev defaults via shell env or a `.env` file (see `.env.example` for the variable names) and use: ```bash docker compose -f docker-compose.yml up -d # (skips the override so containers pull registry images) ``` The GPU agent is deployed separately, on the machine with the card — `agent/docker-compose.yml`, not this stack. ## Deployment posture FabledCurator is designed to run inside a self-hosted homelab environment over plain HTTP. If you want TLS, terminate it at your reverse proxy. The app does not generate certificates, redirect to HTTPS, or set HSTS. ## CI / Forgejo setup Three workflows: `ci.yml` (lint, extension-version check, backend unit tests, frontend build, integration), `extension.yml` (extension lint, vitest, XPI content verification), and `build.yml` (sign + publish). **The toolchain each job runs in is its `container.image`, not its `runs-on` label.** `runs-on: python-ci` only schedules the job onto a runner; every job then names the image it actually wants. `ci-requirements.md` is the current, authoritative list of images and per-job installs — read that rather than a copy here, so the two can't drift. The repo expects one secret: - **`RELEASE_TOKEN`** — a Forgejo PAT with: - `write:package` + `read:package` — for `docker push` to `git.fabledsword.com` - `write:release` — for the `ext-` releases that cache the signed XPI - `write:issue` — for issue-management automation Generate at https://git.fabledsword.com/user/settings/applications. The injected `GITHUB_TOKEN` cannot be used because it lacks `write:package`. AMO signing additionally needs `MOZILLA_AMO_JWT_KEY` / `MOZILLA_AMO_JWT_SECRET`; it runs on `main` only and is cached per version, since AMO rejects a re-signed version. ## License Personal project; use at your own discretion.