diff --git a/modules/influxdb/client.ts b/modules/influxdb/client.ts index 120dfa2..245060e 100644 --- a/modules/influxdb/client.ts +++ b/modules/influxdb/client.ts @@ -24,6 +24,13 @@ function meshConfig(file?: string): Record { catch { return {}; } } +/** A secret delivered as a file, trimmed; undefined when there is none, so the caller can fall back. */ +function tokenFromFile(file?: string): string | undefined { + if (!file) return undefined; + try { return readFileSync(file, "utf8").trim() || undefined; } + catch { return undefined; } +} + export class InfluxDBClient { readonly baseUrl: string; @@ -43,8 +50,10 @@ export class InfluxDBClient { static fromEnv(env: NodeJS.ProcessEnv = process.env): InfluxDBClient { const cfg = meshConfig(env.MESH_INFLUXDB_CONFIG_FILE); const url = cfg.url ?? env.MESH_INFLUXDB_URL ?? `http://127.0.0.1:${env.INFLUXDB_PORT ?? "8086"}`; - const token = cfg.token ?? env.MESH_INFLUXDB_TOKEN; - if (!token) throw new Error("no InfluxDB token — set MESH_INFLUXDB_TOKEN"); + // The token reaches the process as a file (novox/hq ADR 0086); the environment variable stays + // only for a workstation running the tools by hand. + const token = cfg.token ?? tokenFromFile(env.MESH_INFLUXDB_TOKEN_FILE) ?? env.MESH_INFLUXDB_TOKEN; + if (!token) throw new Error("no InfluxDB token — set MESH_INFLUXDB_TOKEN_FILE"); const org = cfg.org ?? env.MESH_INFLUXDB_ORG ?? "mesh"; return new InfluxDBClient(url, token, org); } diff --git a/modules/influxdb/module.json b/modules/influxdb/module.json index a1c48ac..d955f9c 100644 --- a/modules/influxdb/module.json +++ b/modules/influxdb/module.json @@ -13,7 +13,7 @@ "port": 8086, "protocol": "tcp", "from": "mesh", - "why": "queries and writes, over http" + "why": "queries, writes and the web UI, over http; a name is a route grant" } ], "resources": [ @@ -26,46 +26,45 @@ { "id": "state", "type": "directory", - "path": "/var/lib/influxdb-module", - "mode": "0700" - }, - { - "id": "server-env", - "type": "file", - "path": "/var/lib/influxdb-module/server.env", - "mode": "0600", - "content": "DOCKER_INFLUXDB_INIT_MODE=setup\nDOCKER_INFLUXDB_INIT_USERNAME=admin\nDOCKER_INFLUXDB_INIT_PASSWORD=${secret:admin}\nDOCKER_INFLUXDB_INIT_ADMIN_TOKEN=${secret:admin-token}\nDOCKER_INFLUXDB_INIT_ORG=mesh\nDOCKER_INFLUXDB_INIT_BUCKET=default\n" + "mode": "0700", + "place": "." }, { "id": "data", "type": "directory", - "path": "/services/influxdb/data", "mode": "0700", "owner": "1000:1000" }, { "id": "config", "type": "directory", - "path": "/services/influxdb/config", "mode": "0700", "owner": "1000:1000" }, + { + "id": "server-env", + "type": "file", + "path": "${dir:state}/server.env", + "mode": "0600", + "content": "DOCKER_INFLUXDB_INIT_MODE=setup\nDOCKER_INFLUXDB_INIT_USERNAME=admin\nDOCKER_INFLUXDB_INIT_PASSWORD_FILE=/run/secrets/admin\nDOCKER_INFLUXDB_INIT_ADMIN_TOKEN_FILE=/run/secrets/admin-token\nDOCKER_INFLUXDB_INIT_ORG=mesh\nDOCKER_INFLUXDB_INIT_BUCKET=default\n" + }, { "id": "server", "type": "container", "name": "influxdb", "image": "influxdb@sha256:f75e48af0598e8aec7986e991a848d19a119101a7d563a2e5db1dfaac9c45daa", "env-file": [ - "/var/lib/influxdb-module/server.env" + "${dir:state}/server.env" ], "ports": [ "8086" ], "volumes": [ - "/services/influxdb/data:/var/lib/influxdb2", - "/services/influxdb/config:/etc/influxdb2" - ], - "secrets-in-environment": "the image honours DOCKER_INFLUXDB_INIT_PASSWORD_FILE and _ADMIN_TOKEN_FILE; convertible, awaiting a bed that proves it" + "${dir:data}:/var/lib/influxdb2", + "${dir:config}:/etc/influxdb2", + "${dir:state}/admin.secret:/run/secrets/admin:ro", + "${dir:state}/admin-token.secret:/run/secrets/admin-token:ro" + ] }, { "id": "runtime-config", @@ -83,13 +82,13 @@ "volumes": [ "/var/lib/mesh/influxdb/broker:/run/secrets/broker:ro", "/var/lib/mesh/influxdb/config.json:/run/config/config.json:ro", - "/services/influxdb/config:/var/lib/influxdb/config:ro" + "${dir:state}/admin-token.secret:/run/secrets/admin-token:ro" ], "env": { "MESH_BROKER_FILE": "/run/secrets/broker", - "MESH_INFLUXDB_URL": "http://127.0.0.1:8086", + "MESH_INFLUXDB_URL": "http://127.0.0.1:${port:8086}", "MESH_INFLUXDB_CONFIG_FILE": "/run/config/config.json", - "MESH_INFLUXDB_CONFIG_DIR": "/var/lib/influxdb/config" + "MESH_INFLUXDB_TOKEN_FILE": "/run/secrets/admin-token" }, "restart-on": [ "runtime-config" @@ -97,6 +96,22 @@ "artifact": "runtime" } ], + "requires": [ + "route", + "secret" + ], + "contributes": { + "route": { + "label": "influxdb", + "endpoint": "api" + } + }, + "secrets": { + "secret": { + "admin": "${dir:state}/admin.secret", + "admin-token": "${dir:state}/admin-token.secret" + } + }, "build": { "on": [ { @@ -117,14 +132,5 @@ "from": "Dockerfile" } ] - }, - "requires": [ - "secret" - ], - "secrets": { - "secret": { - "admin": "/var/lib/influxdb-module/admin.secret", - "admin-token": "/var/lib/influxdb-module/admin-token.secret" - } } }