Files
homelab-optimized/docs/superpowers/specs/2026-04-24-pinchflat-design.md
Gitea Mirror Bot 48bfce60e7
Some checks failed
Documentation / Build Docusaurus (push) Failing after 5m7s
Documentation / Deploy to GitHub Pages (push) Has been skipped
Sanitized mirror from private repository - 2026-04-24 08:27:14 UTC
2026-04-24 08:27:14 +00:00

147 lines
7.7 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Pinchflat Test Deployment — Design
**Date:** 2026-04-24
**Status:** Approved, awaiting implementation plan
**Scope:** Evaluate Pinchflat (YouTube auto-archiver) on Atlantis as a lightweight test before deciding whether to adopt permanently.
## Goal
Run Pinchflat on Atlantis long enough to evaluate its channel-subscription UX and download quality on real 4K monitors. Keep the test cheap to throw away: no SSO, no reverse proxy, no DNS entry, no Kuma monitor, no Portainer stack registration until we decide to keep it.
## Non-Goals
- Media-server integration (user does not use Jellyfin; no Plex integration planned for this test)
- Authentik SSO / NPM proxy / `*.vish.gg` hostname / Kuma monitor — all deferred to a "promotion to prod" follow-up if we keep it
- Exposure outside the LAN
- GitOps / Portainer stack registration
## Architecture
Single container on Atlantis, port-published on the LAN. No dependencies on other services.
```
┌──────────────────────────────────────┐
│ Atlantis (Synology, 192.168.0.200) │
│ │
LAN browser ──► │ :8945 pinchflat │
│ │ │
│ ├─► /config (NVMe) │
│ │ /volume2/metadata/docker2│
│ │ /pinchflat/config │
│ │ │
│ └─► /downloads (SATA) │
│ /volume1/data/media │
│ /youtube/ │
└──────────────────────────────────────┘
```
## Components
### 1. Container
- **Image:** `ghcr.io/kieraneglin/pinchflat:latest`
- **Container name:** `pinchflat`
- **Network:** default bridge. Port published `8945:8945` (Pinchflat default, verified free on Atlantis via `ss -tlnp`).
- **Not joined to `media2_net`** — nothing else talks to Pinchflat, no benefit to a static IP on the arr bridge.
- **User/group:** PUID=1029, PGID=100 (Synology `dockerlimited:users` — matches existing media ownership so Plex/SMB can read the output folder later if we decide to integrate).
- **Env:** `TZ=America/Los_Angeles`, `UMASK=022`.
- **Security:** `security_opt: [no-new-privileges:true]`.
- **Restart:** `unless-stopped`.
- **Watchtower:** default (enabled). Fine for a test running `:latest`.
- **Healthcheck:** HTTP GET `/` on port 8945, 30s interval (Pinchflat's web UI is the only interface).
### 2. Storage
- **Config volume:** `/volume2/metadata/docker2/pinchflat/config``/config` (NVMe, matches repo convention).
- **Downloads volume:** `/volume1/data/media/youtube/``/downloads` (SATA RAID6, new folder alongside `movies/`, `tv/`, etc.).
- No cache volume needed — Pinchflat writes directly to destination.
### 3. Compose file
- **Path:** `hosts/synology/atlantis/pinchflat/docker-compose.yml`
- **Matches conventions observed in** `hosts/synology/atlantis/youtubedl.yaml` and `hosts/synology/atlantis/arr-suite/docker-compose.yml`.
- Not referenced by any existing Portainer stack. Not in any `networks:` definition shared with other services.
### 4. Pinchflat runtime defaults (configured in web UI on first launch)
Applied globally; overridable per-channel.
- **Output template:** `/downloads/{{ source_custom_name }}/{{ upload_yyyy_mm_dd }} - {{ title }}.{{ ext }}`
- Produces `/downloads/Veritasium/2024-03-12 - Why planes don't fly faster.mkv` etc.
- One folder per channel, date-prefixed files for chronological sort, no fake S01E01 naming.
- **Resolution cap:** 4K (best available up to 2160p). User has 4K monitors; 4K channels get 4K, others fall back naturally.
- **Container format:** MKV (required for clean VP9/AV1 playback — YouTube does not encode 4K in H.264).
- **Thumbnails:** on (cheap, useful in file managers).
- **Subtitles:** on (any available language, SRT sidecar files).
- **Chapters:** on (embedded in MKV).
- **NFO files:** off (only useful for Plex/Kodi/Jellyfin; not needed here).
## Deployment & Test Workflow
1. Create branch `feat/pinchflat` off `main`.
2. Add `hosts/synology/atlantis/pinchflat/docker-compose.yml` and a stub `docs/services/individual/pinchflat.md` (~20 lines: what it is, current test status, URL).
3. Commit, push branch.
4. SSH to Atlantis, clone/checkout the branch to a throwaway working copy under `/volume1/homes/vish/pinchflat-test/`.
5. `docker compose up -d` from the working copy.
6. Pre-create `/volume1/data/media/youtube/` with `dockerlimited:users` ownership (or let Pinchflat create it on first download — either works).
7. Open `http://192.168.0.200:8945` in a browser, walk through initial setup, apply the defaults from §4.
8. Subscribe to 25 test channels. Let it run for several days.
9. Decide:
- **Keep:** merge branch to `main`, register new Portainer GitOps stack pointing at the committed compose path, expand docs, stop the hand-run container, re-`up` via Portainer.
- **Drop:** `docker compose down -v` on Atlantis, `rm -rf /volume2/metadata/docker2/pinchflat /volume1/data/media/youtube`, delete the branch.
## Data Flow
```
YouTube ──► Pinchflat (yt-dlp) ──► /downloads/<Channel>/<date> - <title>.mkv
└─► /config/pinchflat.db (SQLite: subscriptions, download history)
```
No downstream consumers during the test. Files live on the filesystem; user browses via SMB / file manager / direct playback.
## Error Handling
- **Download failures** (age-restricted, geo-blocked, deleted videos): Pinchflat surfaces these in its web UI with retry buttons. No external alerting during the test.
- **Disk fill:** `/volume1/data` has ample headroom, but 4K with many channels can grow fast. If it becomes a concern, lower the global cap to 1080p or set per-channel caps.
- **Container crash:** `restart: unless-stopped` brings it back. No monitoring during the test phase — we'll notice if the UI doesn't load.
- **`:latest` breaking change:** Watchtower enabled. If an update breaks something, we roll back by pinning to a prior digest in the compose file.
## Testing
Manual, UI-driven:
- **Smoke:** container comes up, web UI loads, ingests a single video from a pasted URL.
- **Subscription:** channel subscription polls correctly, new uploads appear within the polling interval.
- **Quality:** 4K-capable channel produces a 2160p MKV; 1080p-only channel produces a 1080p MKV.
- **Sidecar files:** subtitles and thumbnails present next to the MKV.
- **Permissions:** output files are `dockerlimited:users`, readable via SMB.
- **Persistence:** restart container, state survives.
## Open Questions
None — design approved.
## Promotion Path (if kept)
Out of scope for this spec, but the follow-up to "keep" would include:
- Register GitOps stack in Portainer from the committed compose path
- Add Authentik proxy provider + NPM proxy host for `pinchflat.vish.gg`
- Add Kuma monitor (HTTP `http://192.168.0.200:8945`)
- Pin image to a specific version digest instead of `:latest`
- Expand `docs/services/individual/pinchflat.md` with full operational runbook
## Rollback Plan
Throw-away test. Rollback is:
```bash
ssh atlantis
cd /volume1/homes/vish/pinchflat-test
docker compose down -v
sudo rm -rf /volume2/metadata/docker2/pinchflat /volume1/data/media/youtube
cd ~ && rm -rf pinchflat-test
```
Then `git branch -D feat/pinchflat` and `git push origin --delete feat/pinchflat`. Zero impact on any production stack since nothing references this compose file.