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/README.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

4.3 KiB

media-acquisition

Self-hosted BitTorrent + arr-stack + canonical-import pipeline that lands torrents directly on nullstone, through a Proton WireGuard VPN with verified kill-switch, hardlinks files into the existing ARRFLIX library, and auto-commits catalog rows to git.s8n.ru/s8n/beta-flix.

Replaces the legacy onyx → rsync → nullstone round-trip.

Architecture

                                    +-----------------+
                                    |  Proton VPN     |
                                    |  (WireGuard)    |
                                    +--------+--------+
                                             | wg0
                                             v
+------------+   indexer queries   +-------------------+   torrent traffic
|  Prowlarr  |-------------------->|     gluetun       |<------------------+
+-----+------+   (via netns)       |  kill-switch fw   |                   |
      |                            +-------------------+                   |
      | search                       ^      ^     ^                        |
      v                              |      |     |                        |
+------------+   grabs    +----------+      |     +----------+             |
|  Sonarr/   |----------->|         qBittorrent (netns=gluetun)            |
|  Radarr    |            |  /home/user/media/_downloads/{incomplete,complete}
+-----+------+            +-------------------------------------------------+
      |                                                                    
      | OnImport webhook (POST /sonarr or /radarr)                          
      v                                                                    
+--------------------+                                                      
| betaflix-catalog   |--+ XFS reflink/hardlink into /home/user/media/{movies,tv}
| (Flask, Python)    |  |
+--------+-----------+  +--> Jellyfin (tv.s8n.ru) picks up new items
         |
         | git commit + push (obsidian-ai)
         v
+-----------------------------+
| git.s8n.ru/s8n/beta-flix    |
| playbooks/import-media/     |
|  MEDIA-LIST.md (updated)    |
|  runs/<slug>.md (new)       |
+-----------------------------+

Single XFS filesystem at /home/user/media → hardlinks / reflinks are free.

Quickstart

# Clone on nullstone
ssh user@nullstone
git clone https://git.s8n.ru/s8n/media-acquisition.git /opt/docker/media-acquisition
cd /opt/docker/media-acquisition/compose

# Configure
cp .env.example .env
${EDITOR:-vi} .env       # fill in PVPN_WG_PRIVKEY, PVPN_WG_ADDRESSES, FORGEJO_PUSH_TOKEN, etc.

# Bring up
docker compose up -d

# Verify VPN kill-switch (CRITICAL — do not skip)
bash ../scripts/killswitch-test.sh

# Sanity: pick a sacrificial legal torrent in qbt UI, confirm it lands in
# /home/user/media/_downloads/complete/ and arr stack hardlinks it.

Layout

README.md                  This file.
CLAUDE.md                  Project rules for Claude Code.
docs/
  architecture.md          The plan in detail. Decision log + reasoning.
  migration.md             onyx-qbt → nullstone-qbt migration runbook.
  trackers.md              Tracker schema + IP-pinning notes (user fills in).
compose/
  docker-compose.yml       Full stack: gluetun + qbt + sonarr + radarr + prowlarr + catalog.
  .env.example             All env vars documented.
  traefik/arr.yml          Traefik file-provider for *.s8n.ru subdomains (LAN+TS only).
catalog/
  catalog.py               Flask webhook receiver → beta-flix catalog updater.
  Dockerfile               python:3.12-slim base.
  requirements.txt         Pinned versions.
  templates/               Jinja2 templates for run logs and catalog rows.
  README.md                Catalog service docs.
scripts/
  migrate-onyx.sh          Phase-2 migration: rsync + .torrent mass-add.
  add-tracker.sh           Helper: add tracker to Prowlarr via API.
  killswitch-test.sh       Verify gluetun blocks traffic when VPN drops.
  • Plan: docs/architecture.md
  • Catalog target: git.s8n.ru/s8n/beta-flix (playbooks/import-media/MEDIA-LIST.md)
  • Jellyfin (consumer): tv.s8n.ru (jellyfin-stock container on nullstone)
  • Host docs: ai-lab/SYSTEM.md

Status

Scaffold. Live deploy pending VPN slot allocation + tracker IP-pinning review. Next step: fill in compose/.env and bring up gluetun + qbt only (no arr yet) to validate kill-switch.