diff --git a/modules/amqp-email-forwarder/module.json b/modules/amqp-email-forwarder/module.json index 175fadb..94f84e6 100644 --- a/modules/amqp-email-forwarder/module.json +++ b/modules/amqp-email-forwarder/module.json @@ -31,7 +31,7 @@ "type": "file", "path": "/var/lib/amqp-email-forwarder/app.env", "mode": "0600", - "content": "AMQP_HOST=${bound:amqp:at}\nAMQP_PORT=${bound:amqp:port}\nAMQP_USER=${bound:amqp:as}\nAMQP_PASSWORD=${secret:amqp}\nAMQP_VHOST=EMAILDELIVERY_T\nAMQP_EXCHANGE=News.TransactionalEmailing.Command\nAMQP_QUEUE=email-forwarder\nAMQP_URL=amqp://${bound:amqp:as}:${secret:amqp}@${bound:amqp:at}:${bound:amqp:port}/EMAILDELIVERY_T\nSMTP_HOST=mail.novox.be\nSMTP_PORT=587\nSMTP_USER=${secret:smtp-user}\nSMTP_PASSWORD=${secret:smtp-password}\n" + "content": "AMQP_HOST=${bound:amqp:at}\nAMQP_PORT=${bound:amqp:port}\nAMQP_USER=${bound:amqp:as}\nAMQP_VHOST=EMAILDELIVERY_T\nAMQP_EXCHANGE=News.TransactionalEmailing.Command\nAMQP_QUEUE=email-forwarder\nAMQP_URL=amqp://${bound:amqp:as}:${secret:amqp}@${bound:amqp:at}:${bound:amqp:port}/EMAILDELIVERY_T\nSMTP_HOST=mail.novox.be\nSMTP_PORT=587\nSMTP_USER=${secret:smtp-user}\nSMTP_PASSWORD=${secret:smtp-password}\n" }, { "id": "net", @@ -50,7 +50,7 @@ "restart-on": [ "app-env" ], - "secrets-in-environment": "the runtime reads its SMTP and AMQP settings from the environment; a file twin in the SDK is the per-module work of issue 041" + "secrets-in-environment": "the application's own code reads AMQP_URL, SMTP_USER and SMTP_PASSWORD from the environment (amqp-email-forwarder app.js); converting is that repository's change" } ] } diff --git a/modules/amqp-ping/module.json b/modules/amqp-ping/module.json index c78b31d..68e947c 100644 --- a/modules/amqp-ping/module.json +++ b/modules/amqp-ping/module.json @@ -36,7 +36,7 @@ "type": "file", "path": "/var/lib/amqp-ping/amqp.env", "mode": "0600", - "content": "MESH_AMQP_HOST=${bound:amqp:at}\nMESH_AMQP_PORT=${bound:amqp:port}\nMESH_AMQP_USER=${bound:amqp:as}\nMESH_AMQP_VHOST=${bound:amqp:as}\nMESH_AMQP_PASSWORD=${secret:amqp}\n" + "content": "MESH_AMQP_HOST=${bound:amqp:at}\nMESH_AMQP_PORT=${bound:amqp:port}\nMESH_AMQP_USER=${bound:amqp:as}\nMESH_AMQP_VHOST=${bound:amqp:as}\n" }, { "id": "net", @@ -49,10 +49,12 @@ "name": "amqp-ping", "network": "amqp-ping", "volumes": [ - "/var/lib/mesh/amqp-ping/broker:/run/secrets/broker:ro" + "/var/lib/mesh/amqp-ping/broker:/run/secrets/broker:ro", + "/var/lib/amqp-ping/amqp.secret:/run/secrets/amqp:ro" ], "env": { - "MESH_BROKER_FILE": "/run/secrets/broker" + "MESH_BROKER_FILE": "/run/secrets/broker", + "MESH_AMQP_PASSWORD_FILE": "/run/secrets/amqp" }, "env-file": [ "/var/lib/amqp-ping/amqp.env" @@ -60,8 +62,7 @@ "restart-on": [ "amqp-env" ], - "artifact": "runtime", - "secrets-in-environment": "the runtime reads MESH_AMQP_* from the environment; a file twin in the SDK is the per-module work of issue 041" + "artifact": "runtime" } ], "build": { diff --git a/modules/baserow/module.json b/modules/baserow/module.json index e44b6c2..6fc1e0b 100644 --- a/modules/baserow/module.json +++ b/modules/baserow/module.json @@ -86,7 +86,7 @@ "volumes": [ "/services/baserow/data:/baserow/data" ], - "secrets-in-environment": "the image reads its configuration from the environment only; converting to a file is the per-module work of issue 041" + "secrets-in-environment": "baserow reads DATABASE_PASSWORD, REDIS_PASSWORD and SECRET_KEY with os.getenv and has no _FILE twin (settings/base.py); not convertible" }, { "id": "runtime-config", diff --git a/modules/de-spiegel/module.json b/modules/de-spiegel/module.json index 600a819..b46b650 100644 --- a/modules/de-spiegel/module.json +++ b/modules/de-spiegel/module.json @@ -60,7 +60,7 @@ "ports": [ "35621:35621" ], - "secrets-in-environment": "the image reads its configuration from the environment only; converting to a file is the per-module work of issue 041" + "secrets-in-environment": "the application's own code reads SMTP_AUTH_USER/PASS from the environment (de-spiegel server/index.js); converting is that repository's change" } ] } diff --git a/modules/gitea/module.json b/modules/gitea/module.json index a7ba184..cd11944 100644 --- a/modules/gitea/module.json +++ b/modules/gitea/module.json @@ -114,7 +114,7 @@ "volumes": [ "/services/gitea/gitea:/data" ], - "secrets-in-environment": "the image reads its configuration from the environment only; converting to a file is the per-module work of issue 041" + "secrets-in-environment": "gitea honours GITEA__database__PASSWD__FILE and GITEA__security__INTERNAL_TOKEN__FILE; convertible, awaiting a bed that proves it" }, { "id": "admin-bootstrap", @@ -139,7 +139,7 @@ "-c", "su-exec git gitea admin user create --admin --username \"$MESH_GITEA_ADMIN_USER\" --email mesh-admin@localhost --password \"$(cat /run/secrets/admin)\" --must-change-password=false || true" ], - "secrets-in-environment": "the image reads its configuration from the environment only; converting to a file is the per-module work of issue 041" + "secrets-in-environment": "gitea honours GITEA__database__PASSWD__FILE and GITEA__security__INTERNAL_TOKEN__FILE; convertible, awaiting a bed that proves it" }, { "id": "runtime-config", diff --git a/modules/grafana/module.json b/modules/grafana/module.json index b46c8a6..a4317f6 100644 --- a/modules/grafana/module.json +++ b/modules/grafana/module.json @@ -32,13 +32,6 @@ "path": "/var/lib/grafana-module", "mode": "0700" }, - { - "id": "server-env", - "type": "file", - "path": "/var/lib/grafana-module/server.env", - "mode": "0600", - "content": "GF_SECURITY_ADMIN_PASSWORD=${secret:admin}\n" - }, { "id": "data", "type": "directory", @@ -51,16 +44,16 @@ "type": "container", "name": "grafana", "image": "grafana/grafana@sha256:f772d434e8fab0049deb2b1b30abd43342bcfca1537614aa8d36080232cf4283", - "env-file": [ - "/var/lib/grafana-module/server.env" - ], "ports": [ "3000" ], "volumes": [ - "/services/grafana/data:/var/lib/grafana" + "/services/grafana/data:/var/lib/grafana", + "/var/lib/grafana-module/admin.secret:/run/secrets/admin:ro" ], - "secrets-in-environment": "the image reads its configuration from the environment only; converting to a file is the per-module work of issue 041" + "env": { + "GF_SECURITY_ADMIN_PASSWORD__FILE": "/run/secrets/admin" + } }, { "id": "runtime-config", @@ -122,5 +115,6 @@ "from": "Dockerfile" } ] - } + }, + "secrets-owner": "472:472" } diff --git a/modules/icecast/module.json b/modules/icecast/module.json index 54c2d01..82f1ba3 100644 --- a/modules/icecast/module.json +++ b/modules/icecast/module.json @@ -53,7 +53,7 @@ "ports": [ "8000" ], - "secrets-in-environment": "the image reads its configuration from the environment only; converting to a file is the per-module work of issue 041" + "secrets-in-environment": "the image seds ICECAST_*_PASSWORD into icecast.xml and has no _FILE; convertible by mounting a generated icecast.xml, not yet done" }, { "id": "runtime-config", diff --git a/modules/influxdb/module.json b/modules/influxdb/module.json index 8017f21..6102067 100644 --- a/modules/influxdb/module.json +++ b/modules/influxdb/module.json @@ -66,7 +66,7 @@ "/services/influxdb/data:/var/lib/influxdb2", "/services/influxdb/config:/etc/influxdb2" ], - "secrets-in-environment": "the image reads its configuration from the environment only; converting to a file is the per-module work of issue 041" + "secrets-in-environment": "the image honours DOCKER_INFLUXDB_INIT_PASSWORD_FILE and _ADMIN_TOKEN_FILE; convertible, awaiting a bed that proves it" }, { "id": "runtime-config", diff --git a/modules/invoicing/module.json b/modules/invoicing/module.json index fb6d870..9acd9cf 100644 --- a/modules/invoicing/module.json +++ b/modules/invoicing/module.json @@ -100,7 +100,7 @@ "ports": [ "9000" ], - "secrets-in-environment": "the API reads its settings from the environment; converting is the per-module work of issue 041" + "secrets-in-environment": "the application's own code reads MONGO_URL and MINIO_SECRET from the environment (invoicing-app server/src/config.js); converting is that repository's change" } ] } diff --git a/modules/keycloak/module.json b/modules/keycloak/module.json index 9f1dd2e..919be3c 100644 --- a/modules/keycloak/module.json +++ b/modules/keycloak/module.json @@ -97,7 +97,7 @@ "ports": [ "8080" ], - "secrets-in-environment": "the image reads its configuration from the environment only; converting to a file is the per-module work of issue 041" + "secrets-in-environment": "KC_DB_PASSWORD is convertible through a generated keycloak.conf (db-password=); KEYCLOAK_ADMIN_PASSWORD is env-only before Keycloak 26; not yet converted" }, { "id": "runtime-config", diff --git a/modules/letta/module.json b/modules/letta/module.json index a5c31d1..c72c784 100644 --- a/modules/letta/module.json +++ b/modules/letta/module.json @@ -67,7 +67,7 @@ "ports": [ "8283" ], - "secrets-in-environment": "the runtime reads its settings from the environment; converting is the per-module work of issue 041" + "secrets-in-environment": "the letta image is env-driven and its file-source support could not be verified; the mesh runtime can take its password from config.json (client.ts) \u2014 not yet converted" }, { "id": "runtime-config", @@ -105,7 +105,7 @@ "runtime-config" ], "artifact": "runtime", - "secrets-in-environment": "the runtime reads its settings from the environment; converting is the per-module work of issue 041" + "secrets-in-environment": "the letta image is env-driven and its file-source support could not be verified; the mesh runtime can take its password from config.json (client.ts) \u2014 not yet converted" } ], "build": { diff --git a/modules/mailu/module.json b/modules/mailu/module.json index 112beb5..ee67fbb 100644 --- a/modules/mailu/module.json +++ b/modules/mailu/module.json @@ -218,7 +218,7 @@ "/var/lib/mailu/mailu.env", "/var/lib/mailu/secret.env" ], - "secrets-in-environment": "the image reads its configuration from the environment only; converting to a file is the per-module work of issue 041" + "secrets-in-environment": "mailu-admin honours SECRET_KEY_FILE, DB_PW_FILE and API_TOKEN_FILE (configuration.py) but INITIAL_ADMIN_PW is env-only (start.py); the remaining containers' need for SECRET_KEY is unverified" }, { "id": "redis", @@ -246,7 +246,7 @@ "/services/mailu/data/data:/data", "/services/mailu/data/dkim:/dkim" ], - "secrets-in-environment": "the image reads its configuration from the environment only; converting to a file is the per-module work of issue 041" + "secrets-in-environment": "mailu-admin honours SECRET_KEY_FILE, DB_PW_FILE and API_TOKEN_FILE (configuration.py) but INITIAL_ADMIN_PW is env-only (start.py); the remaining containers' need for SECRET_KEY is unverified" }, { "id": "imap", @@ -255,14 +255,12 @@ "image": "ghcr.io/mailu/dovecot@sha256:46d18ba51032be8ebd6841aa49c1ef8762c729038c5fd86a081b5b884d478af9", "network": "mailu", "env-file": [ - "/var/lib/mailu/mailu.env", - "/var/lib/mailu/secret.env" + "/var/lib/mailu/mailu.env" ], "volumes": [ "/services/mailu/data/mail:/mail", "/services/mailu/data/overrides/dovecot:/overrides:ro" - ], - "secrets-in-environment": "the image reads its configuration from the environment only; converting to a file is the per-module work of issue 041" + ] }, { "id": "smtp", @@ -271,14 +269,12 @@ "image": "ghcr.io/mailu/postfix@sha256:bbf882880f68849511710b35237a933f3fe80c4b28bf48ff20205dbd1f1433d7", "network": "mailu", "env-file": [ - "/var/lib/mailu/mailu.env", - "/var/lib/mailu/secret.env" + "/var/lib/mailu/mailu.env" ], "volumes": [ "/services/mailu/data/mailqueue:/queue", "/services/mailu/data/overrides/postfix:/overrides:ro" - ], - "secrets-in-environment": "the image reads its configuration from the environment only; converting to a file is the per-module work of issue 041" + ] }, { "id": "antispam", @@ -287,14 +283,12 @@ "image": "ghcr.io/mailu/rspamd@sha256:e87ab93dd252cc69499caa5317dd10d445fd4291a7ecf6bca09793c7d475a0c8", "network": "mailu", "env-file": [ - "/var/lib/mailu/mailu.env", - "/var/lib/mailu/secret.env" + "/var/lib/mailu/mailu.env" ], "volumes": [ "/services/mailu/data/filter:/var/lib/rspamd", "/services/mailu/data/overrides/rspamd:/etc/rspamd/override.d:ro" - ], - "secrets-in-environment": "the image reads its configuration from the environment only; converting to a file is the per-module work of issue 041" + ] }, { "id": "antivirus", @@ -309,7 +303,7 @@ "volumes": [ "/services/mailu/data/filter:/data" ], - "secrets-in-environment": "the image reads its configuration from the environment only; converting to a file is the per-module work of issue 041" + "secrets-in-environment": "mailu-admin honours SECRET_KEY_FILE, DB_PW_FILE and API_TOKEN_FILE (configuration.py) but INITIAL_ADMIN_PW is env-only (start.py); the remaining containers' need for SECRET_KEY is unverified" }, { "id": "webmail", @@ -325,7 +319,7 @@ "/services/mailu/data/webmail:/data", "/services/mailu/data/overrides/roundcube:/overrides:ro" ], - "secrets-in-environment": "the image reads its configuration from the environment only; converting to a file is the per-module work of issue 041" + "secrets-in-environment": "mailu-admin honours SECRET_KEY_FILE, DB_PW_FILE and API_TOKEN_FILE (configuration.py) but INITIAL_ADMIN_PW is env-only (start.py); the remaining containers' need for SECRET_KEY is unverified" }, { "id": "webdav", @@ -340,7 +334,7 @@ "volumes": [ "/services/mailu/data/dav:/data" ], - "secrets-in-environment": "the image reads its configuration from the environment only; converting to a file is the per-module work of issue 041" + "secrets-in-environment": "mailu-admin honours SECRET_KEY_FILE, DB_PW_FILE and API_TOKEN_FILE (configuration.py) but INITIAL_ADMIN_PW is env-only (start.py); the remaining containers' need for SECRET_KEY is unverified" }, { "id": "fetchmail", @@ -355,7 +349,7 @@ "volumes": [ "/services/mailu/data/data/fetchmail:/data" ], - "secrets-in-environment": "the image reads its configuration from the environment only; converting to a file is the per-module work of issue 041" + "secrets-in-environment": "mailu-admin honours SECRET_KEY_FILE, DB_PW_FILE and API_TOKEN_FILE (configuration.py) but INITIAL_ADMIN_PW is env-only (start.py); the remaining containers' need for SECRET_KEY is unverified" }, { "id": "front", @@ -364,8 +358,7 @@ "image": "ghcr.io/mailu/nginx@sha256:09f28ab6d36367fcacc7994f7021f132ac845bdc05f04bf80906102d11aaa057", "network": "mailu", "env-file": [ - "/var/lib/mailu/mailu.env", - "/var/lib/mailu/secret.env" + "/var/lib/mailu/mailu.env" ], "ports": [ "25", @@ -377,8 +370,7 @@ "volumes": [ "/services/mailu/data/certs:/certs", "/services/mailu/data/overrides/nginx:/overrides:ro" - ], - "secrets-in-environment": "the image reads its configuration from the environment only; converting to a file is the per-module work of issue 041" + ] }, { "id": "runtime-config", diff --git a/modules/mesh-catalog/module.json b/modules/mesh-catalog/module.json index 67f8bd2..153d4e2 100644 --- a/modules/mesh-catalog/module.json +++ b/modules/mesh-catalog/module.json @@ -50,11 +50,11 @@ "mode": "0700" }, { - "id": "db-env", + "id": "database-url", "type": "file", - "path": "/var/lib/mesh-catalog/db.env", + "path": "/var/lib/mesh-catalog/database.url", "mode": "0600", - "content": "DATABASE_URL=postgresql://${bound:postgres-database:as}:${secret:postgres-database}@${bound:postgres-database:at}:${bound:postgres-database:port}/${bound:postgres-database:as}\n" + "content": "postgresql://${bound:postgres-database:as}:${secret:postgres-database}@${bound:postgres-database:at}:${bound:postgres-database:port}/${bound:postgres-database:as}\n" }, { "id": "runtime", @@ -63,19 +63,20 @@ "network": "host", "volumes": [ "/var/lib/mesh/mesh-catalog/broker:/run/secrets/broker:ro", - "/var/lib/mesh-catalog:/run/state" + "/var/lib/mesh-catalog:/run/state", + "/var/lib/mesh-catalog/database.url:/run/secrets/database-url:ro" ], "env": { - "MESH_BROKER_FILE": "/run/secrets/broker" + "MESH_BROKER_FILE": "/run/secrets/broker", + "DATABASE_URL_FILE": "/run/secrets/database-url" }, - "env-file": [ - "/var/lib/mesh-catalog/db.env" - ], "artifact": "runtime", "restart-on": [ - "db-env" + "database-url" ], - "secrets-in-environment": "the mesh's own runtime reads MESH_STORE_* from the environment; a file twin in the SDK is the per-module work of issue 041" + "env-file": [ + "/var/lib/mesh-catalog/db.env" + ] } ], "build": { diff --git a/modules/mesh-catalog/store.ts b/modules/mesh-catalog/store.ts index 5b187ef..02db37e 100644 --- a/modules/mesh-catalog/store.ts +++ b/modules/mesh-catalog/store.ts @@ -1,3 +1,4 @@ +import { readFileSync } from "node:fs"; // The module graph (novox/hq ADR 0070, ADR 0072). // // **This graph links module-versions to each other and knows nothing about nodes.** Which machine @@ -138,7 +139,9 @@ export class Graph { private constructor(private readonly pool: PgPool) {} static fromEnv(env: NodeJS.ProcessEnv = process.env): Graph { - const url = env["DATABASE_URL"]; + // As a file first (novox/hq ADR 0086): the connection string carries the password, and the + // mesh writes it where only this process reads it; the plain variable remains for a hand-run. + const url = env["DATABASE_URL"] ?? readMaybe(env["DATABASE_URL_FILE"]); if (!url) { throw new Error( "no DATABASE_URL: the catalogue holds the module graph and cannot hold it in memory, " + @@ -390,3 +393,13 @@ export class Graph { await this.pool.end(); } } + +/** The content of a file the environment names, its line ending gone — or undefined when it names none. */ +function readMaybe(path: string | undefined): string | undefined { + if (!path) return undefined; + try { + return readFileSync(path, "utf8").replace(/\r?\n$/, ""); + } catch { + return undefined; + } +} diff --git a/modules/minio/module.json b/modules/minio/module.json index 484e777..4fcb31d 100644 --- a/modules/minio/module.json +++ b/modules/minio/module.json @@ -63,7 +63,7 @@ "type": "file", "path": "/var/lib/minio/root.env", "mode": "0600", - "content": "MINIO_ROOT_USER=meshroot\nMINIO_ROOT_PASSWORD=${secret:root}\n" + "content": "MINIO_ROOT_USER=meshroot\n" }, { "id": "data", @@ -95,9 +95,12 @@ "9000" ], "volumes": [ - "/services/minio/data/data1-1:/data" + "/services/minio/data/data1-1:/data", + "/var/lib/minio/root.secret:/run/secrets/root:ro" ], - "secrets-in-environment": "the image reads its configuration from the environment only; converting to a file is the per-module work of issue 041" + "env": { + "MINIO_ROOT_PASSWORD_FILE": "/run/secrets/root" + } }, { "id": "runtime", diff --git a/modules/model-usage/module.json b/modules/model-usage/module.json index 0c00dee..5c5ee05 100644 --- a/modules/model-usage/module.json +++ b/modules/model-usage/module.json @@ -39,11 +39,11 @@ "mode": "0700" }, { - "id": "db-env", + "id": "database-url", "type": "file", - "path": "/var/lib/model-usage/db.env", + "path": "/var/lib/model-usage/database.url", "mode": "0600", - "content": "DATABASE_URL=postgresql://${bound:postgres-database:as}:${secret:postgres-database}@${bound:postgres-database:at}:${bound:postgres-database:port}/${bound:postgres-database:as}\n" + "content": "postgresql://${bound:postgres-database:as}:${secret:postgres-database}@${bound:postgres-database:at}:${bound:postgres-database:port}/${bound:postgres-database:as}\n" }, { "id": "runtime", @@ -53,15 +53,16 @@ "network": "host", "volumes": [ "/var/lib/mesh/model-usage/broker:/run/secrets/broker:ro", - "/var/lib/model-usage:/run/state" + "/var/lib/model-usage:/run/state", + "/var/lib/model-usage/database.url:/run/secrets/database-url:ro" ], "env": { - "MESH_BROKER_FILE": "/run/secrets/broker" + "MESH_BROKER_FILE": "/run/secrets/broker", + "DATABASE_URL_FILE": "/run/secrets/database-url" }, "env-file": [ "/var/lib/model-usage/db.env" - ], - "secrets-in-environment": "the mesh's own runtime reads MESH_STORE_* from the environment; a file twin in the SDK is the per-module work of issue 041" + ] } ] } diff --git a/modules/model-usage/store.ts b/modules/model-usage/store.ts index 4f96563..b19a0ce 100644 --- a/modules/model-usage/store.ts +++ b/modules/model-usage/store.ts @@ -1,3 +1,4 @@ +import { readFileSync } from "node:fs"; // The vendor-neutral usage store (novox/hq ADR 0054). ONE table holds BOTH grains — licence and // session — which differ only in `consumer`; a reading is one row `(licence, consumer, period, // metric, value)` plus its `raw` vendor payload. The store keeps the LATEST reading per @@ -47,7 +48,10 @@ export class UsageStore { /** Build a store from the resolved environment — DATABASE_URL is the granted postgres connection, * templated into the module's env-file from the mesh's binding (umami's DATABASE_URL precedent). */ static fromEnv(env: NodeJS.ProcessEnv = process.env): UsageStore { - return new UsageStore(new Pool({ connectionString: requireEnv("DATABASE_URL", env) })); + // As a file first (novox/hq ADR 0086): the connection string carries the password. + const url = env["DATABASE_URL"] ?? readMaybe(env["DATABASE_URL_FILE"]); + if (!url) throw new Error("DATABASE_URL_FILE (or DATABASE_URL) is not set — model-usage cannot reach its database"); + return new UsageStore(new Pool({ connectionString: url })); } /** Create the one table if it is not there. Run once by the migrate entry before the consumer @@ -84,3 +88,13 @@ export class UsageStore { await this.pool.end(); } } + +/** The content of a file the environment names, its line ending gone — or undefined when it names none. */ +function readMaybe(path: string | undefined): string | undefined { + if (!path) return undefined; + try { + return readFileSync(path, "utf8").replace(/\r?\n$/, ""); + } catch { + return undefined; + } +} diff --git a/modules/mongodb/module.json b/modules/mongodb/module.json index fb24a99..a8eb25b 100644 --- a/modules/mongodb/module.json +++ b/modules/mongodb/module.json @@ -60,13 +60,6 @@ "path": "/var/lib/mongodb/grants", "mode": "0700" }, - { - "id": "root-env", - "type": "file", - "path": "/var/lib/mongodb/root.env", - "mode": "0600", - "content": "MONGO_INITDB_ROOT_PASSWORD=${secret:root}\n" - }, { "id": "data", "type": "directory", @@ -85,18 +78,16 @@ "image": "mongo@sha256:e3fa459b4f4b72f3257c67a23c145e250b8b5700f033860392c68539b998bbe3", "network": "mongodb", "env": { - "MONGO_INITDB_ROOT_USERNAME": "root" + "MONGO_INITDB_ROOT_USERNAME": "root", + "MONGO_INITDB_ROOT_PASSWORD_FILE": "/run/secrets/root" }, - "env-file": [ - "/var/lib/mongodb/root.env" - ], "ports": [ "27017" ], "volumes": [ - "/services/mongodb/db-data:/data/db" - ], - "secrets-in-environment": "the image reads its configuration from the environment only; converting to a file is the per-module work of issue 041" + "/services/mongodb/db-data:/data/db", + "/var/lib/mongodb/root.secret:/run/secrets/root:ro" + ] }, { "id": "runtime", diff --git a/modules/mssql/module.json b/modules/mssql/module.json index 5709e5f..d397c6b 100644 --- a/modules/mssql/module.json +++ b/modules/mssql/module.json @@ -92,7 +92,7 @@ "volumes": [ "/services/mssql/db-data:/var/opt/mssql" ], - "secrets-in-environment": "the image reads its configuration from the environment only; converting to a file is the per-module work of issue 041" + "secrets-in-environment": "the image documents only MSSQL_SA_PASSWORD, no _FILE and no configuration field; not convertible without a wrapper entrypoint" }, { "id": "runtime", diff --git a/modules/n8n/module.json b/modules/n8n/module.json index 14fc4a1..c4df38b 100644 --- a/modules/n8n/module.json +++ b/modules/n8n/module.json @@ -79,7 +79,7 @@ "volumes": [ "/services/n8n/n8n-data:/home/node/.n8n" ], - "secrets-in-environment": "the image reads its configuration from the environment only; converting to a file is the per-module work of issue 041" + "secrets-in-environment": "n8n's loader honours _FILE for every setting; convertible, awaiting a bed that proves it (N8N_BASIC_AUTH_* was removed in n8n 1.0 and is likely dead)" } ] } diff --git a/modules/nextcloud/module.json b/modules/nextcloud/module.json index 3a0c22a..05a982b 100644 --- a/modules/nextcloud/module.json +++ b/modules/nextcloud/module.json @@ -88,7 +88,7 @@ "volumes": [ "/services/nextcloud/html:/var/www/html" ], - "secrets-in-environment": "the image reads its configuration from the environment only; converting to a file is the per-module work of issue 041" + "secrets-in-environment": "the image honours POSTGRES_PASSWORD_FILE and NEXTCLOUD_ADMIN_PASSWORD_FILE (entrypoint file_env); OBJECTSTORE_S3_SECRET has none and needs a generated config fragment; convertible, awaiting a bed" }, { "id": "runtime-config", diff --git a/modules/only-office/module.json b/modules/only-office/module.json index ffc2739..5afcf62 100644 --- a/modules/only-office/module.json +++ b/modules/only-office/module.json @@ -110,7 +110,7 @@ "/services/only-office/redis:/var/lib/redis", "/services/only-office/fonts:/usr/share/fonts/truetype/custom" ], - "secrets-in-environment": "the image reads its configuration from the environment only; converting to a file is the per-module work of issue 041" + "secrets-in-environment": "run-document-server.sh regenerates JWT_SECRET from the environment on every start and overwrites local.json; not convertible" } ] } diff --git a/modules/photos/module.json b/modules/photos/module.json index 1d280d3..99c7c1c 100644 --- a/modules/photos/module.json +++ b/modules/photos/module.json @@ -75,7 +75,7 @@ "ports": [ "9000" ], - "secrets-in-environment": "the server reads its settings from the environment; converting is the per-module work of issue 041" + "secrets-in-environment": "the application's own code reads MONGO_URL and MINIO_SECRET from the environment (photos server/src/config.js); converting is that repository's change" }, { "id": "admin-client", diff --git a/modules/searxng/module.json b/modules/searxng/module.json index 76d2d41..7f64906 100644 --- a/modules/searxng/module.json +++ b/modules/searxng/module.json @@ -71,7 +71,7 @@ "ports": [ "8080" ], - "secrets-in-environment": "the image reads its configuration from the environment only; converting to a file is the per-module work of issue 041" + "secrets-in-environment": "SEARXNG_SECRET is env-only, but settings.yml carries server.secret_key; convertible by mounting a generated settings.yml, not yet done" }, { "id": "runtime-config", diff --git a/modules/step-ca/module.json b/modules/step-ca/module.json index 9d1b18c..b5fdffd 100644 --- a/modules/step-ca/module.json +++ b/modules/step-ca/module.json @@ -104,7 +104,7 @@ "/var/lib/step-ca:/home/step", "/var/lib/mesh/step-ca:/run/mesh:ro" ], - "secrets-in-environment": "the image reads its configuration from the environment only; converting to a file is the per-module work of issue 041" + "secrets-in-environment": "the entrypoint honours DOCKER_STEPCA_INIT_PASSWORD_FILE; convertible, awaiting a bed that proves it" } ] } diff --git a/modules/umami/module.json b/modules/umami/module.json index d27a6a9..8e1a1f7 100644 --- a/modules/umami/module.json +++ b/modules/umami/module.json @@ -102,7 +102,7 @@ "ports": [ "3000" ], - "secrets-in-environment": "the image reads its configuration from the environment only; converting to a file is the per-module work of issue 041" + "secrets-in-environment": "a Next.js/Prisma application: DATABASE_URL and APP_SECRET are read from the environment only; not convertible" }, { "id": "runtime",