Pinchflat — a self-hosted YouTube media manager: subscribe to channels or playlists and it automatically downloads new videos with yt-dlp, organizes them, and can serve podcast-style RSS feeds. Deployed as a host-networked Nomad service using SQLite with config and downloads volumes.
Needs nomad-pack on PATH. The script only adds the nomploy registry and runs this pack.
Source ↗ Project ↗ ★ 5.4k ⚑ Report an issue
Save as values.hcl, edit, then run:
# The name of the Nomad job.
job_name = "pinchflat"
# The Nomad namespace to deploy into.
namespace = "default"
# The datacenters to deploy to.
datacenters = ["*"]
# The Pinchflat container image. Pin a tag in production.
image = "ghcr.io/kieraneglin/pinchflat:latest"
# Host port for the Pinchflat web UI. The container listens on 8945.
port = 8945
# Container timezone (TZ), e.g. Europe/Bratislava.
tz = "UTC"
# Optional HTTP basic-auth username (BASIC_AUTH_USERNAME). Empty = no auth.
basic_auth_username = ""
# Optional HTTP basic-auth password (BASIC_AUTH_PASSWORD). Set together with the username.
basic_auth_password = ""
# Named volume for Pinchflat config (/config): the SQLite database and settings.
config_volume = "pinchflat_config"
# Named volume for downloaded media (/downloads).
downloads_volume = "pinchflat_downloads"
# Placement constraints. Pin to the node holding the volumes. On a nomploy cluster: attribute = "$${meta.nomploy_control_plane}", operator = "=", value = "true".
constraints = []
# Resources for the Pinchflat task.
resources = {
cpu = 500
memory = 512
}
| Name | Type | Default | Description |
|---|---|---|---|
| job_name | string | "pinchflat" | The name of the Nomad job. |
| namespace | string | "default" | The Nomad namespace to deploy into. |
| datacenters | list | ["*"] | The datacenters to deploy to. |
| image | string | "ghcr.io/kieraneglin/pinchflat:latest" | The Pinchflat container image. Pin a tag in production. |
| port | number | 8945 | Host port for the Pinchflat web UI. The container listens on 8945. |
| tz | string | "UTC" | Container timezone (TZ), e.g. Europe/Bratislava. |
| basic_auth_username | string | "" | Optional HTTP basic-auth username (BASIC_AUTH_USERNAME). Empty = no auth. |
| basic_auth_password key | string | "" | Optional HTTP basic-auth password (BASIC_AUTH_PASSWORD). Set together with the username. |
| config_volume | string | "pinchflat_config" | Named volume for Pinchflat config (/config): the SQLite database and settings. |
| downloads_volume | string | "pinchflat_downloads" | Named volume for downloaded media (/downloads). |
| constraints | list | [] | Placement constraints. Pin to the node holding the volumes. On a nomploy cluster: attribute = "$${meta.nomploy_control_plane}", operator = "=", value = "true". |
| resources | object | {
cpu = 500
memory = 512
} | Resources for the Pinchflat task. |
No variables match.
This pack stores data in 2 Docker named volumes:
pinchflat_configpinchflat_downloads
restic
# Run on the node hosting this pack. Point restic at your repo first: # export RESTIC_REPOSITORY="s3:https://<account>.r2.cloudflarestorage.com/<bucket>" # export RESTIC_PASSWORD="<repo-password>" # export AWS_ACCESS_KEY_ID=<key> AWS_SECRET_ACCESS_KEY=<secret> restic backup \ /var/lib/docker/volumes/pinchflat_config/_data \ /var/lib/docker/volumes/pinchflat_downloads/_data
rclone (sync to S3/R2)
rclone sync /var/lib/docker/volumes/pinchflat_config/_data backup:<bucket>/pinchflat_config rclone sync /var/lib/docker/volumes/pinchflat_downloads/_data backup:<bucket>/pinchflat_downloads
Paths assume the default Docker volume location (/var/lib/docker/volumes). Restore by stopping the job, restoring files into the same volume, and re-running the pack.
Pinchflat — a self-hosted YouTube media manager. Subscribe to
channels or playlists and it automatically downloads new videos with yt-dlp,
names and organizes them for your media server, and can expose podcast-style RSS feeds. Set-and-forget
archiving, unlike the manual metube pack.
Single host-networked Nomad service using SQLite with config and downloads volumes.
nomad-pack registry add nomploy https://github.com/Nomploy/nomad-packs
nomad-pack run pinchflat --registry=nomploy
| Variable | Default | Description |
|---|---|---|
port |
8945 |
Web UI port (PORT). |
tz |
UTC |
Container timezone (TZ). |
basic_auth_username / basic_auth_password |
"" |
Optional HTTP basic auth. Empty = no login. |
config_volume |
pinchflat_config |
/config — SQLite DB and settings. |
downloads_volume |
pinchflat_downloads |
/downloads — the media files. |
image |
ghcr.io/kieraneglin/pinchflat:latest |
Container image. Pin a tag in production. |
resources |
{ cpu = 500, memory = 512 } |
Task resources. |
Add a source (channel/playlist), set download options, and Pinchflat handles the rest on a schedule. Point a
media pack (jellyfin, navidrome) at the downloads volume. No auth by default — set the basic-auth vars
or keep it internal, and only download content you have the rights to. Pin the job to the node holding the
volumes with constraints.