Deploy the API
This is the production deployment path for the public Pinchana API stack. Use the development Compose file for local source work instead.
Host requirements
Section titled “Host requirements”- Linux host with Docker Engine and Compose plugin.
- Enough disk for the shared media cache and, if enabled, temporary DLP jobs.
- A provider WireGuard key for Gluetun.
- HTTPS reverse proxy/DNS for the public gateway origin.
- Firewall rules that keep scraper/control/DLP internal ports away from untrusted networks.
Clone and configure
Section titled “Clone and configure”git clone --recurse-submodules https://github.com/Pinchana/pinchana-api.gitcd pinchana-apicp .env.example .envchmod 600 .envReplace placeholder production credentials at minimum:
WIREGUARD_PRIVATE_KEY=REPLACE_WITH_PROVIDER_KEYGLUETUN_API_KEY=REPLACE_WITH_RANDOM_CONTROL_KEYPINCHANA_API_KEYS={"operator":"REPLACE_WITH_LONG_RANDOM_MACHINE_KEY"}Add Spotify credentials if that module is enabled for real use.
Pin released images
Section titled “Pin released images”Resolve the newest coherent API release before first startup and on later upgrades:
python scripts/update_rolling.py --env-file .env --dry-runpython scripts/update_rolling.py --env-file .envThis replaces the mutable discovery tags in .env with exact repository digests only after all selected services resolve to the same released CalVer.
If DLP should be deployed/updated too:
python scripts/update_rolling.py --env-file .env --dlp --dry-runpython scripts/update_rolling.py --env-file .env --dlpDo not mix independently chosen scraper image versions in production.
docker compose --env-file .env config --quietdocker compose --env-file .env up --detachdocker compose --env-file .env psHealth check:
curl --fail-with-body --silent --show-error http://127.0.0.1:8080/healthNetworking
Section titled “Networking”The gateway and normal scraper services share Gluetun’s network namespace. Service containers do not publish independent ports: blocks; the host mappings live on Gluetun.
Even if operational host mappings for module ports exist, expose only gateway port 8080 through the public reverse proxy. Keep module ports 8081–8089 and Gluetun control 8000 firewalled from the Internet.
Example public routing:
https://api.example.com -> 127.0.0.1:8080Terminate TLS at your reverse proxy and preserve normal HTTP range/request headers for media streaming.
Browser/Web configuration
Section titled “Browser/Web configuration”If a Pinchana Web deployment will use this API, configure the API’s browser verifier:
TURNSTILE_SECRET_KEY=REPLACE_WITH_PRIVATE_TURNSTILE_SECRETTURNSTILE_EXPECTED_HOSTNAME=pinchana.example.comTURNSTILE_EXPECTED_ACTION=turnstile-spin-v1TURNSTILE_SESSION_SECRET=REPLACE_WITH_AT_LEAST_32_RANDOM_CHARACTERSThe corresponding public Turnstile site key belongs on the Web deployment.
A self-hosted Web server using this API as its configured default origin does not require an instance certificate. A certificate is needed when this API should be accepted as a custom instance by a Web deployment that enforces project-issued instance trust.
Shorts cookies
Section titled “Shorts cookies”The Shorts service can consume cookie files from:
SHORTS_COOKIES_DIR=./secrets/yt-cookiesProduction Compose mounts that directory read-only to /run/pinchana-cookies.
For rootful Docker with the current image:
sudo install -d -o root -g root -m 0700 secrets/yt-cookiessudo chown root:root secrets/yt-cookies/cookies.txtsudo chmod 0600 secrets/yt-cookies/cookies.txtUse the Docker host user instead for rootless Docker. Never store cookie files in Git or backups that are not designed for secrets.
DLP deployment
Section titled “DLP deployment”DLP services are an optional Compose profile and should remain disabled publicly while infrastructure is prepared:
DLP_ENABLED=falseUse the production preflight and canary from DLP operations and security. Redis, DLP API, orchestrator, worker control paths, and the DLP worker network must remain internal.
The job root defaults to /srv/pinchana-dlp/jobs and is temporary, not backup data.
Updates
Section titled “Updates”Routine application update:
python scripts/update_rolling.py --env-file .env --dry-runpython scripts/update_rolling.py --env-file .envdocker compose --env-file .env up --detachIf changed environment variables must be applied to one service, recreate that service explicitly. For Gluetun, use Compose recreation rather than docker restart:
docker compose --env-file .env up --detach --force-recreate gluetunData worth preserving
Section titled “Data worth preserving”Treat these differently:
.envand mounted secrets — critical secret configuration; back up securely if your operational policy requires it.scraper-cache— disposable working cache, not authoritative data.- mobile session SQLite — persistent state only if you actively use mobile installation grants.
- DLP job directories/Redis — temporary and intentionally not backed up.
- instance certificate envelope — public certificate material, but protect the operational file from accidental modification; never deploy its signing private key.