kometa, tautulli and ombi reached plex by a hand-typed address - a public name, a HAL network gateway - which the mesh cannot keep true. Plex now provides plex-api at mesh scope and serves the server's port and scheme, so the mesh tells each consumer where it is. The port is written out rather than inferred: plex listens on five ports (the server and four discovery ones), and the mesh only infers a provision's port when a module listens on exactly one. No grants and no provisioner: the credential is the server owner's X-Plex-Token, which plex.tv issues and the mesh cannot mint. The operator accepts it as the pair credential for each consumer (ADR 0092); each consumer's step checks it against the server and writes nothing it refuses.
218 lines
4.5 KiB
JSON
218 lines
4.5 KiB
JSON
{
|
|
"module": "plex",
|
|
"version": "1",
|
|
"provides": [
|
|
{
|
|
"name": "plex-api",
|
|
"scope": "mesh"
|
|
}
|
|
],
|
|
"serves": {
|
|
"plex-api": {
|
|
"scheme": "http",
|
|
"port": 32400
|
|
}
|
|
},
|
|
"capabilities": [
|
|
"container-runtime"
|
|
],
|
|
"emits": [
|
|
"playback.started",
|
|
"playback.stopped",
|
|
"item.added"
|
|
],
|
|
"consumes": [
|
|
"*.download.completed"
|
|
],
|
|
"own-secrets": {
|
|
"broker": "/var/lib/mesh/plex/broker"
|
|
},
|
|
"listens": [
|
|
{
|
|
"name": "stream",
|
|
"port": 32400,
|
|
"protocol": "tcp",
|
|
"from": "mesh",
|
|
"why": "the server itself: the apps, streaming and the web player, direct and through its route"
|
|
},
|
|
{
|
|
"name": "gdm-1",
|
|
"port": 32410,
|
|
"protocol": "udp",
|
|
"from": "mesh",
|
|
"why": "G'Day Mate discovery: players on the same network find the server without signing in"
|
|
},
|
|
{
|
|
"name": "gdm-2",
|
|
"port": 32412,
|
|
"protocol": "udp",
|
|
"from": "mesh",
|
|
"why": "G'Day Mate discovery"
|
|
},
|
|
{
|
|
"name": "gdm-3",
|
|
"port": 32413,
|
|
"protocol": "udp",
|
|
"from": "mesh",
|
|
"why": "G'Day Mate discovery"
|
|
},
|
|
{
|
|
"name": "gdm-4",
|
|
"port": 32414,
|
|
"protocol": "udp",
|
|
"from": "mesh",
|
|
"why": "G'Day Mate discovery"
|
|
}
|
|
],
|
|
"accesses": [
|
|
{
|
|
"path": "/services/media/movies",
|
|
"mode": "read"
|
|
},
|
|
{
|
|
"path": "/services/media/series",
|
|
"mode": "read"
|
|
},
|
|
{
|
|
"path": "/services/media/anime",
|
|
"mode": "read"
|
|
},
|
|
{
|
|
"path": "/services/media/music",
|
|
"mode": "read"
|
|
},
|
|
{
|
|
"path": "/services/media/audiobooks",
|
|
"mode": "read"
|
|
},
|
|
{
|
|
"path": "/services/media/sport-games",
|
|
"mode": "read"
|
|
},
|
|
{
|
|
"path": "/services/media/live-shows",
|
|
"mode": "read"
|
|
},
|
|
{
|
|
"path": "/services/media/formula-1",
|
|
"mode": "read"
|
|
}
|
|
],
|
|
"resources": [
|
|
{
|
|
"id": "mesh-state",
|
|
"type": "directory",
|
|
"path": "/var/lib/mesh/plex",
|
|
"mode": "0700"
|
|
},
|
|
{
|
|
"id": "state",
|
|
"type": "directory",
|
|
"mode": "0700",
|
|
"place": "."
|
|
},
|
|
{
|
|
"id": "config",
|
|
"type": "directory",
|
|
"mode": "0755",
|
|
"owner": "1000:1000"
|
|
},
|
|
{
|
|
"id": "data",
|
|
"type": "directory",
|
|
"mode": "0755",
|
|
"owner": "1000:1000"
|
|
},
|
|
{
|
|
"id": "transcode",
|
|
"type": "directory",
|
|
"mode": "0755",
|
|
"owner": "1000:1000"
|
|
},
|
|
{
|
|
"id": "server-env",
|
|
"type": "file",
|
|
"path": "${dir:state}/server.env",
|
|
"mode": "0600",
|
|
"content": "ADVERTISE_IP=https://${bound:route:name}/\n"
|
|
},
|
|
{
|
|
"id": "server",
|
|
"type": "container",
|
|
"name": "plex",
|
|
"image": "plexinc/pms-docker@sha256:e0ab27395614a8e1a4fdf84c6bc60ac664915cfdde70c52d030c7728a1c48e14",
|
|
"network": "host",
|
|
"env": {
|
|
"PLEX_UID": "1000",
|
|
"PLEX_GID": "1000",
|
|
"TZ": "Etc/UTC"
|
|
},
|
|
"env-file": [
|
|
"${dir:state}/server.env"
|
|
],
|
|
"volumes": [
|
|
"${dir:config}:/config",
|
|
"${dir:data}:/data",
|
|
"${dir:transcode}:/transcode",
|
|
"/services/media/movies:/movies:ro",
|
|
"/services/media/series:/series:ro",
|
|
"/services/media/anime:/anime:ro",
|
|
"/services/media/music:/music:ro",
|
|
"/services/media/audiobooks:/audiobooks:ro",
|
|
"/services/media/sport-games:/sport-games:ro",
|
|
"/services/media/live-shows:/live-shows:ro",
|
|
"/services/media/formula-1:/formula-1:ro"
|
|
]
|
|
},
|
|
{
|
|
"id": "runtime",
|
|
"type": "container",
|
|
"name": "mesh-plex",
|
|
"network": "host",
|
|
"volumes": [
|
|
"/var/lib/mesh/plex/broker:/run/secrets/broker:ro",
|
|
"${dir:config}:/var/lib/plex/config:ro"
|
|
],
|
|
"env": {
|
|
"MESH_BROKER_FILE": "/run/secrets/broker",
|
|
"MESH_PLEX_URL": "http://127.0.0.1:${port:32400}",
|
|
"MESH_PLEX_DATA_DIR": "/var/lib/plex"
|
|
},
|
|
"artifact": "runtime"
|
|
}
|
|
],
|
|
"requires": [
|
|
"route"
|
|
],
|
|
"contributes": {
|
|
"route": {
|
|
"label": "plex",
|
|
"endpoint": "stream"
|
|
}
|
|
},
|
|
"binds": {
|
|
"route": "${dir:state}/route.json"
|
|
},
|
|
"build": {
|
|
"on": [
|
|
{
|
|
"arg": "BUILD_BASE",
|
|
"module": "mesh-tools",
|
|
"artifact": "build"
|
|
},
|
|
{
|
|
"arg": "RUNTIME_BASE",
|
|
"module": "mesh-tools",
|
|
"artifact": "runtime"
|
|
}
|
|
],
|
|
"artifacts": [
|
|
{
|
|
"name": "runtime",
|
|
"kind": "image",
|
|
"from": "Dockerfile"
|
|
}
|
|
]
|
|
}
|
|
}
|