Files
mesh-media-catalog/modules/sonarr/module.json
T
jochen f4d8faead0 sonarr: the runtime serves its watcher and tools, and its downloads step is a run-once process (hq ADR 0198)
The mesh-sonarr container and the mesh-sonarr-downloads step container go with the Dockerfile, build bases and bus credential. The step runs node on the bundle with its words in the process's env, the bound clients' files, the app's config.xml and its memory read where the mesh writes them; it still runs again when a binding it reads changes.
2026-10-04 00:45:22 +02:00

221 lines
6.2 KiB
JSON

{
"module": "sonarr",
"version": "1",
"provides": [
{
"name": "sonarr-api",
"scope": "mesh",
"credential": {
"own": "api-key"
}
}
],
"serves": {
"sonarr-api": {
"scheme": "http",
"port": 8989,
"url-base": ""
}
},
"capabilities": [
"container-runtime"
],
"emits": [
"episode.grabbed",
"download.completed"
],
"consumes": [],
"own-secrets": {
"api-key": {
"path": "${dir:mesh-state}/api-key",
"taken": "at-start"
}
},
"listens": [
{
"name": "web",
"port": 8989,
"protocol": "tcp",
"from": "mesh",
"why": "managing series: its web UI, and the API other modules reach as sonarr-api"
}
],
"accesses": [
{
"id": "series",
"path": "/services/media/series",
"mode": "read-write"
},
{
"id": "anime",
"path": "/services/media/anime",
"mode": "read-write"
},
{
"id": "downloads",
"path": "/services/media/downloads",
"mode": "read-write"
}
],
"resources": [
{
"id": "mesh-state",
"type": "directory",
"mode": "0700",
"place": "mesh"
},
{
"id": "state",
"type": "directory",
"mode": "0700",
"place": "."
},
{
"id": "config",
"type": "directory",
"mode": "0700",
"owner": "1000:1000"
},
{
"id": "identity",
"type": "file",
"path": "${dir:state}/identity.env",
"mode": "0644",
"content": "# The identity this module's process runs as on THIS machine: the owner of its\n# data here, which the definition may not know (novox/hq ADR 0112, issue 153). Set puid and\n# pgid on the assignment \u2014 the mesh-wide layer carries the image's default, a node's its own.\nPUID=${setting:puid}\nPGID=${setting:pgid}\n"
},
{
"id": "mesh-init",
"type": "directory",
"mode": "0755"
},
{
"id": "api-key-init",
"type": "file",
"path": "${dir:mesh-init}/10-mesh-api-key.sh",
"mode": "0755",
"content": "#!/bin/bash\n# Written by the mesh (ADR 0158): this module's one credential is the vault's, shared with every\n# consumer; the file is applied here, before the service starts, on every start.\nset -euo pipefail\nCONF=/config/config.xml\nKEY=$(cat /run/secrets/api-key)\nif [ -s \"$CONF\" ] && grep -q '<ApiKey>' \"$CONF\"; then\n sed -i -E \"s#<ApiKey>[^<]*</ApiKey>#<ApiKey>$KEY</ApiKey>#\" \"$CONF\"\nelif [ -s \"$CONF\" ]; then\n sed -i -E \"s#</Config># <ApiKey>$KEY</ApiKey>\\n</Config>#\" \"$CONF\"\nelse\n printf '<Config>\\n <ApiKey>%s</ApiKey>\\n</Config>\\n' \"$KEY\" > \"$CONF\"\nfi\necho \"[mesh] API key set from the vault's credential\"\n"
},
{
"id": "server",
"type": "container",
"name": "sonarr",
"image": "lscr.io/linuxserver/sonarr@sha256:a5c1a5fecbef946927ab90ad68df319ac5fe644057e5fc18cd993f01ac07b2b2",
"env": {
"TZ": "Etc/UTC"
},
"ports": [
"8989"
],
"volumes": [
"${dir:config}:/config",
"${access:series}:/series",
"${access:anime}:/anime",
"${access:downloads}:/downloads",
"${dir:mesh-init}:/custom-cont-init.d:ro",
"${dir:mesh-state}/api-key:/run/secrets/api-key:ro"
],
"env-file": [
"${dir:state}/identity.env"
],
"restart-on": [
"identity",
"needs-api-key",
"api-key-init"
]
},
{
"id": "downloads-config",
"type": "file",
"path": "${dir:state}/downloads.json",
"mode": "0600",
"content": "{\n \"node\": \"${machine:name}\",\n \"downloads\": {\n \"nzbget-api\": {\n \"name\": \"nzbget\"\n },\n \"qbittorrent-api\": {\n \"name\": \"qbittorrent\"\n },\n \"jackett-api\": {\n \"adopt-hosts\": [],\n \"indexers\": []\n }\n }\n}\n",
"merge": "json"
},
{
"id": "downloads-memory",
"type": "directory",
"mode": "0700"
},
{
"id": "downloads",
"type": "process",
"name": "sonarr-downloads",
"artifact": "code",
"run": [
"node",
"downloads/index.js"
],
"run-once": true,
"env": {
"MESH_DOWNLOADS_APP": "sonarr",
"MESH_DOWNLOADS_API": "v3",
"MESH_DOWNLOADS_APP_URL": "http://127.0.0.1:${port:8989}",
"MESH_DOWNLOADS_APP_CONFIG": "${dir:config}/config.xml",
"MESH_DOWNLOADS_DIR": "${dir:state}",
"MESH_DOWNLOADS_SETTINGS": "${dir:state}/downloads.json",
"MESH_DOWNLOADS_MEMORY": "${dir:downloads-memory}/memory.json"
},
"restart-on": [
"downloads-config",
"bound-nzbget-api",
"secret-nzbget-api",
"bound-qbittorrent-api",
"secret-qbittorrent-api",
"bound-jackett-api",
"secret-jackett-api"
]
}
],
"requires": [
"jackett-api",
"nzbget-api",
"qbittorrent-api",
"route",
"plex-api"
],
"contributes": {
"route": {
"label": "series",
"endpoint": "web"
}
},
"binds": {
"route": "${dir:state}/route.json",
"nzbget-api": "${dir:state}/nzbget-api.json",
"qbittorrent-api": "${dir:state}/qbittorrent-api.json",
"jackett-api": "${dir:state}/jackett-api.json",
"plex-api": "${dir:state}/plex-api.json"
},
"secrets": {
"nzbget-api": "${dir:state}/nzbget-api.secret",
"qbittorrent-api": "${dir:state}/qbittorrent-api.secret",
"jackett-api": "${dir:state}/jackett-api.secret",
"plex-api": "${dir:state}/plex-api.secret"
},
"build": {
"artifacts": [
{
"name": "code",
"kind": "bundle",
"language": "typescript",
"entrypoints": [
"index.js",
"tools/index.js",
"downloads/index.js"
],
"loads": [
"index.js",
"tools/index.js"
],
"env": {
"MESH_SONARR_URL": "http://127.0.0.1:${port:8989}",
"MESH_SONARR_CONFIG_DIR": "${dir:config}",
"MESH_SONARR_API_KEY_FILE": "${dir:mesh-state}/api-key",
"MESH_PLEX_BIND_FILE": "${dir:state}/plex-api.json",
"MESH_PLEX_TOKEN_FILE": "${dir:state}/plex-api.secret"
}
}
]
}
}