modules: wire tool-runtime app credentials as own-secrets
The six modules that run a mesh-<mod> tool-runtime sidecar read an app credential from an env var the manifest never provided, so the sidecar crash-looped in the whole-mesh dry-run (e.g. "no Plex token — set MESH_PLEX_TOKEN"). These are operator-set app secrets, so deliver them the same way cloudflare-dns delivers its API token: an own-secret file mounted read-only, with a MESH_<APP>_*_FILE env pointing at the mount, and the runtime code preferring that file (falling back to the existing env so nothing regresses). - plex: own-secret token -> /run/secrets/token, MESH_PLEX_TOKEN_FILE - bazarr: own-secret api-key -> /run/secrets/api-key, MESH_BAZARR_API_KEY_FILE - ombi: own-secret api-key -> /run/secrets/api-key, MESH_OMBI_API_KEY_FILE - home-assistant: own-secret token -> /run/secrets/token, MESH_HOMEASSISTANT_TOKEN_FILE - nzbget: own-secret password -> /run/secrets/password, MESH_NZBGET_PASSWORD_FILE (URL stays plain env) - qbittorrent: own-secret password -> /run/secrets/password, MESH_QBITTORRENT_PASSWORD_FILE (URL stays plain env) The operator now completes each with `secret accept <node> <module> <name> --from <file>`. tsc passes for all six.
This commit is contained in:
+14
-1
@@ -5,6 +5,17 @@
|
||||
import { existsSync, readFileSync } from "node:fs";
|
||||
import { join } from "node:path";
|
||||
|
||||
/** Read a secret the mesh mounted at a file path (an own-secret); absent or unreadable yields
|
||||
* undefined, so callers can fall back rather than crash. */
|
||||
function readSecret(path: string | undefined): string | undefined {
|
||||
if (!path) return undefined;
|
||||
try {
|
||||
return readFileSync(path, "utf8").trim();
|
||||
} catch {
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
export interface PlexLibrary {
|
||||
key: string;
|
||||
title: string;
|
||||
@@ -47,7 +58,9 @@ export class PlexClient {
|
||||
static fromEnv(env: NodeJS.ProcessEnv = process.env): PlexClient {
|
||||
const url = env.MESH_PLEX_URL ?? `http://127.0.0.1:${env.PLEX_PORT ?? "32400"}`;
|
||||
const dataDir = env.MESH_PLEX_DATA_DIR ?? "/var/lib/plex";
|
||||
const token = env.MESH_PLEX_TOKEN ?? PlexClient.detectToken(dataDir);
|
||||
// The operator-provided token is an own-secret the mesh mounts at MESH_PLEX_TOKEN_FILE (delivered
|
||||
// by `secret accept`); prefer it, fall back to a bare env var, then to discovery from the data dir.
|
||||
const token = readSecret(env.MESH_PLEX_TOKEN_FILE) ?? env.MESH_PLEX_TOKEN ?? PlexClient.detectToken(dataDir);
|
||||
if (!token) throw new Error("no Plex token — set MESH_PLEX_TOKEN or make the data dir readable");
|
||||
return new PlexClient(url, token);
|
||||
}
|
||||
|
||||
@@ -13,7 +13,8 @@
|
||||
"module.*.download.completed"
|
||||
],
|
||||
"own-secrets": {
|
||||
"broker": "/var/lib/mesh/plex/broker"
|
||||
"broker": "/var/lib/mesh/plex/broker",
|
||||
"token": "/var/lib/mesh/plex/token"
|
||||
},
|
||||
"listens": [
|
||||
{
|
||||
@@ -95,11 +96,13 @@
|
||||
"network": "host",
|
||||
"volumes": [
|
||||
"/var/lib/mesh/plex/broker:/run/secrets/broker:ro",
|
||||
"/var/lib/mesh/plex/token:/run/secrets/token:ro",
|
||||
"/services/plex/config:/var/lib/plex/config:ro"
|
||||
],
|
||||
"env": {
|
||||
"MESH_BROKER_FILE": "/run/secrets/broker",
|
||||
"MESH_PLEX_URL": "http://127.0.0.1:32400",
|
||||
"MESH_PLEX_TOKEN_FILE": "/run/secrets/token",
|
||||
"MESH_PLEX_DATA_DIR": "/var/lib/plex"
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user