This repository has been archived on 2026-05-20. You can view files and clone it, but cannot push or open issues or pull requests.
media-acquisition/CLAUDE.md
obsidian-ai d300d83ce1 init: media-acquisition pipeline scaffold
Self-hosted BitTorrent + arr-stack + catalog-update pipeline targeting
nullstone (Debian 13). Replaces the legacy onyx -> rsync -> import
round-trip.

Contents:
- README.md          headline + ASCII architecture diagram + quickstart
- CLAUDE.md          project rules (mirrors beta-flix style)
- .gitignore         secrets dirs (.env, gluetun, qbt config, ssh keys)
- .gitleaksignore    allowlist nullstone LAN addr + Tailscale CGNAT
- docs/architecture.md   the plan in detail (gluetun + qbt + arr + catalog)
- docs/migration.md  onyx-qbt -> nullstone-qbt runbook (3 phases)
- docs/trackers.md   tracker schema + IP-pinning + ratio notes (user-curated)
- compose/docker-compose.yml  gluetun v3.40 + qbt 5.0.5 (netns=gluetun) +
                              sonarr/radarr/prowlarr (hotio) + betaflix-catalog
- compose/.env.example       documented env-var template (no secrets)
- compose/traefik/arr.yml    file-provider for qbt/sonarr/radarr/prowlarr
                             .s8n.ru subdomains, LAN+TS only via
                             trusted-only@file + authentik-forwardauth@file
- catalog/catalog.py         Flask service, ~340 LoC, /sonarr + /radarr +
                             /healthz; pulls beta-flix, inserts alphabetic
                             row into MEDIA-LIST.md, writes run log, commits
                             + pushes as obsidian-ai. Idempotent via
                             payload-hash cache.
- catalog/Dockerfile         python:3.12-slim + git + tini
- catalog/requirements.txt   flask + jinja2 + requests + gitpython + pyyaml (pinned)
- catalog/templates/*.j2     run log + catalog row Jinja templates
- catalog/README.md          service docs
- scripts/migrate-onyx.sh    phase-2 helper (rsync + .torrent ship, dry-run by default)
- scripts/add-tracker.sh     Prowlarr API helper
- scripts/killswitch-test.sh gluetun kill-switch verification (3 steps)

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-20 01:15:43 +01:00

5.2 KiB

CLAUDE.md — media-acquisition

Read this at session start. Rules for managing the nullstone media-acquisition pipeline.

What this repo is

The BitTorrent + arr-stack + catalog-update pipeline that feeds the ARRFLIX library on nullstone (Debian 13, 192.168.0.100). Consumed by:

  • Jellyfin at tv.s8n.ru (container jellyfin-stock).
  • Catalog at git.s8n.ru/s8n/beta-flixplaybooks/import-media/MEDIA-LIST.md.

Source map

docs/architecture.md         Plan + reasoning. Read this BEFORE editing compose.
docs/migration.md            onyx-qbt → nullstone-qbt migration runbook.
docs/trackers.md             Tracker schema + IP-pinning risks (user-curated).
compose/docker-compose.yml   gluetun + qbt + sonarr + radarr + prowlarr + catalog.
compose/.env.example         Env template — secrets live in .env (gitignored).
compose/traefik/arr.yml      File-provider routing for arr stack.
catalog/                     betaflix-catalog Python service (Flask + webhooks).
scripts/                     migrate-onyx.sh, add-tracker.sh, killswitch-test.sh.

Deploy lifecycle

  1. Edit files locally under /home/admin/projects/media-acquisition/.
  2. Push to Forgejo (this repo's authoritative remote is git.s8n.ru/s8n/media-acquisition.git).
  3. On nullstone: cd /opt/docker/media-acquisition && git pull && docker compose up -d.
  4. CRITICAL — verify kill-switch after every gluetun change: bash scripts/killswitch-test.sh. If the second curl succeeds, you have a leak; tear down before re-trying.

Rules paid for in blood (mirrored from beta-flix where applicable)

Rule 1 — SSH user

user@nullstone. NOT admin@nullstone. AllowUsers was tightened 2026-05-03; uid 1000 only. Memory: [[feedback_nullstone_ssh_user]].

Rule 2 — Commit + push to my git

Authoritative remote is git.s8n.ru/s8n/media-acquisition.git (Forgejo). No GitHub mirror. Always git remote -v before push. Memory: [[feedback_always_commit_to_my_git]], [[feedback_check_remote_before_push]], [[feedback_my_git_is_forgejo]].

Rule 3 — Commit identity

  • Human commits: s8n <admin@s8n.ru>.
  • Bot/automation commits (e.g. catalog service, scripted edits): obsidian-ai <obsidian-ai@s8n.ru>.

Memory: [[user_git_identity]].

Rule 4 — Kill-switch is non-negotiable

Every change to gluetun service or VPN env vars MUST be followed by scripts/killswitch-test.sh. A torrent client leaking outside the VPN is the single failure mode that defines this project — do not "trust" the firewall based on config inspection. Run the test.

Rule 5 — No secrets in repo

.env, WireGuard keys, Forgejo PATs, deploy keys: all gitignored. Use .env.example to document variable names with placeholders. If you commit a secret by accident, rotate it (Proton WG: regenerate key, update gluetun; Forgejo PAT: revoke at git.s8n.ru/-/user/settings/applications).

Rule 6 — Tracker IP pinning

Private trackers may pin sessions to a single source IP. Switching from onyx public IP → Proton exit IP will trip them. Before adding a new tracker or migrating an old torrent, check docs/trackers.md for the per-tracker policy. Update docs/trackers.md whenever a new tracker is on-boarded.

/home/user/media is XFS, single device. Sonarr/Radarr "Use Hardlinks instead of Copy" = ON. Catalog service may use cp --reflink=always for divergent-perm scenarios (free inodes, zero block cost). Never cp plain; that doubles disk usage and breaks seeding atomicity.

Canonical naming

Catalog rows pushed to beta-flix/playbooks/import-media/MEDIA-LIST.md follow the ARRFLIX house style:

  • TV: Series Title (Year) — alphabetic by title, year tiebreaker.
  • Movies: Movie Title (Year) — alphabetic by title.
  • "Source / Version" column = raw Sonarr/Radarr sourceTitle (release name). Human edits to "Why on arrflix" stay; bot never overwrites that column.

The catalog service is append + merge only — never overwrites human-authored notes.

How to start a session

  1. Read this file.
  2. Read docs/architecture.md if working on compose or catalog code.
  3. Check git status and git remote -v (must show git.s8n.ru/s8n/media-acquisition.git).
  4. Owner says what they want; ship + verify kill-switch + commit to Forgejo.
  5. End every turn: commit + push to git.s8n.ru/s8n/media-acquisition.git.

Glossary

Term Means
ship / deploy git push to Forgejo → on nullstone, git pull && docker compose up -d. Kill-switch test on any gluetun change.
migrate Phase-2 onyx→nullstone runbook in docs/migration.md. Read scripts/migrate-onyx.sh first; dry-run mode mandatory.
add tracker scripts/add-tracker.sh <name> <url>; then update docs/trackers.md with IP-pinning policy + ratio requirements.
killswitch test bash scripts/killswitch-test.sh. NEVER claim "VPN works" without running this.
owner P (xynki.dev@gmail.com). Final say. Executive-override pattern from [[feedback_s8n_executive_override]] applies.