fix: harden compose Pi auth mounts
This commit is contained in:
@@ -13,3 +13,4 @@ THT_DWH_REST_URL=https://dwh.example.invalid
|
|||||||
THT_VEC_REST_URL=https://vector.example.invalid
|
THT_VEC_REST_URL=https://vector.example.invalid
|
||||||
THT_VEC_WRITE_REST_URL=https://vector-write.example.invalid
|
THT_VEC_WRITE_REST_URL=https://vector-write.example.invalid
|
||||||
THT_OLLAMA_URL=https://embeddings.example.invalid
|
THT_OLLAMA_URL=https://embeddings.example.invalid
|
||||||
|
THT_LLM_URL=https://llm.example.invalid
|
||||||
|
|||||||
@@ -25,10 +25,12 @@ services:
|
|||||||
THT_VEC_REST_URL: ${THT_VEC_REST_URL:-}
|
THT_VEC_REST_URL: ${THT_VEC_REST_URL:-}
|
||||||
THT_VEC_WRITE_REST_URL: ${THT_VEC_WRITE_REST_URL:-}
|
THT_VEC_WRITE_REST_URL: ${THT_VEC_WRITE_REST_URL:-}
|
||||||
THT_OLLAMA_URL: ${THT_OLLAMA_URL:-}
|
THT_OLLAMA_URL: ${THT_OLLAMA_URL:-}
|
||||||
|
THT_LLM_URL: ${THT_LLM_URL:-}
|
||||||
MAX_PI_PROCESSES: ${MAX_PI_PROCESSES:-4}
|
MAX_PI_PROCESSES: ${MAX_PI_PROCESSES:-4}
|
||||||
volumes:
|
volumes:
|
||||||
- settings:/data/settings
|
- settings:/data/settings
|
||||||
- pi-state:/home/thoth/.pi
|
- pi-state:/home/thoth/.pi
|
||||||
|
- ${PI_AUTH_FILE:?set PI_AUTH_FILE}:/home/thoth/.pi/agent/auth.json:ro
|
||||||
- workspace-registry:/data/workspace-registry
|
- workspace-registry:/data/workspace-registry
|
||||||
- sessions:/data/sessions
|
- sessions:/data/sessions
|
||||||
healthcheck:
|
healthcheck:
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ services:
|
|||||||
volumes: !override
|
volumes: !override
|
||||||
- ${THT_DATA_ROOT:?set THT_DATA_ROOT}:/data
|
- ${THT_DATA_ROOT:?set THT_DATA_ROOT}:/data
|
||||||
- ${THT_PI_STATE_ROOT:?set THT_PI_STATE_ROOT}:/home/thoth/.pi
|
- ${THT_PI_STATE_ROOT:?set THT_PI_STATE_ROOT}:/home/thoth/.pi
|
||||||
|
- ${PI_AUTH_FILE:?set PI_AUTH_FILE}:/home/thoth/.pi/agent/auth.json:ro
|
||||||
- ${THT_WORKSPACE_REGISTRY_ROOT:?set THT_WORKSPACE_REGISTRY_ROOT}:/data/workspace-registry
|
- ${THT_WORKSPACE_REGISTRY_ROOT:?set THT_WORKSPACE_REGISTRY_ROOT}:/data/workspace-registry
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
|
|
||||||
|
|||||||
Vendored
+2
@@ -3,6 +3,7 @@
|
|||||||
THOTH_HTTP_PORT=8080
|
THOTH_HTTP_PORT=8080
|
||||||
THOTH_CORE_HTTP_PORT=8787
|
THOTH_CORE_HTTP_PORT=8787
|
||||||
MAX_PI_PROCESSES=4
|
MAX_PI_PROCESSES=4
|
||||||
|
PI_AUTH_FILE=/absolute/path/to/pi-auth.json
|
||||||
|
|
||||||
THT_WORKSPACE_GIT_REMOTE=https://git.example.invalid/platform/thoth-workspaces.git
|
THT_WORKSPACE_GIT_REMOTE=https://git.example.invalid/platform/thoth-workspaces.git
|
||||||
THT_WORKSPACE_GIT_BRANCH=main
|
THT_WORKSPACE_GIT_BRANCH=main
|
||||||
@@ -14,3 +15,4 @@ THT_DWH_REST_URL=https://dwh.example.invalid
|
|||||||
THT_VEC_REST_URL=https://vector.example.invalid
|
THT_VEC_REST_URL=https://vector.example.invalid
|
||||||
THT_VEC_WRITE_REST_URL=https://vector-write.example.invalid
|
THT_VEC_WRITE_REST_URL=https://vector-write.example.invalid
|
||||||
THT_OLLAMA_URL=https://embeddings.example.invalid
|
THT_OLLAMA_URL=https://embeddings.example.invalid
|
||||||
|
THT_LLM_URL=https://llm.example.invalid
|
||||||
|
|||||||
Vendored
+2
@@ -3,6 +3,7 @@
|
|||||||
THOTH_SERVER_BIND=127.0.0.1
|
THOTH_SERVER_BIND=127.0.0.1
|
||||||
THOTH_HTTP_PORT=8080
|
THOTH_HTTP_PORT=8080
|
||||||
MAX_PI_PROCESSES=4
|
MAX_PI_PROCESSES=4
|
||||||
|
PI_AUTH_FILE=/absolute/path/to/pi-auth.json
|
||||||
|
|
||||||
THT_DATA_ROOT=/srv/thothii/data
|
THT_DATA_ROOT=/srv/thothii/data
|
||||||
THT_PI_STATE_ROOT=/srv/thothii/pi-state
|
THT_PI_STATE_ROOT=/srv/thothii/pi-state
|
||||||
@@ -17,3 +18,4 @@ THT_DWH_REST_URL=https://dwh.example.invalid
|
|||||||
THT_VEC_REST_URL=https://vector.example.invalid
|
THT_VEC_REST_URL=https://vector.example.invalid
|
||||||
THT_VEC_WRITE_REST_URL=https://vector-write.example.invalid
|
THT_VEC_WRITE_REST_URL=https://vector-write.example.invalid
|
||||||
THT_OLLAMA_URL=https://embeddings.example.invalid
|
THT_OLLAMA_URL=https://embeddings.example.invalid
|
||||||
|
THT_LLM_URL=https://llm.example.invalid
|
||||||
|
|||||||
@@ -26,6 +26,18 @@ if (/omics_portal|chirone|localllm_default|\/home\/chirone/i.test(JSON.stringify
|
|||||||
throw new Error("forbidden application coupling");
|
throw new Error("forbidden application coupling");
|
||||||
}
|
}
|
||||||
if (!config.networks || !config.networks.thothii) throw new Error("base stack must define the thothii network");
|
if (!config.networks || !config.networks.thothii) throw new Error("base stack must define the thothii network");
|
||||||
|
if (!Object.hasOwn(config.services.core.environment || {}, "THT_LLM_URL")) {
|
||||||
|
throw new Error("core must expose a generic THT_LLM_URL endpoint contract");
|
||||||
|
}
|
||||||
|
if (/docker\.sock|\/var\/run\/docker|docker[-_]?daemon/i.test(JSON.stringify(config.services))) {
|
||||||
|
throw new Error("Compose must not mount the Docker socket or daemon");
|
||||||
|
}
|
||||||
|
const piAuthMounts = (config.services.core.volumes || []).filter(
|
||||||
|
(mount) => mount.target === "/home/thoth/.pi/agent/auth.json",
|
||||||
|
);
|
||||||
|
if (piAuthMounts.length !== 1 || piAuthMounts[0].type !== "bind" || !piAuthMounts[0].read_only) {
|
||||||
|
throw new Error("Pi auth must be one read-only file bind");
|
||||||
|
}
|
||||||
|
|
||||||
const ports = Object.fromEntries(
|
const ports = Object.fromEntries(
|
||||||
Object.entries(config.services).map(([name, service]) => [name, service.ports || []]),
|
Object.entries(config.services).map(([name, service]) => [name, service.ports || []]),
|
||||||
@@ -74,6 +86,18 @@ if (!config.networks || !config.networks.thothii) throw new Error("base stack mu
|
|||||||
for (const volume of ["settings", "pi-state", "workspace-registry", "sessions"]) {
|
for (const volume of ["settings", "pi-state", "workspace-registry", "sessions"]) {
|
||||||
if (!config.volumes || !config.volumes[volume]) throw new Error(`missing required volume: ${volume}`);
|
if (!config.volumes || !config.volumes[volume]) throw new Error(`missing required volume: ${volume}`);
|
||||||
}
|
}
|
||||||
|
if (!Object.hasOwn(config.services.core.environment || {}, "THT_LLM_URL")) {
|
||||||
|
throw new Error("core must expose a generic THT_LLM_URL endpoint contract");
|
||||||
|
}
|
||||||
|
if (/docker\.sock|\/var\/run\/docker|docker[-_]?daemon/i.test(JSON.stringify(config.services))) {
|
||||||
|
throw new Error("Compose must not mount the Docker socket or daemon");
|
||||||
|
}
|
||||||
|
const piAuthMounts = (config.services.core.volumes || []).filter(
|
||||||
|
(mount) => mount.target === "/home/thoth/.pi/agent/auth.json",
|
||||||
|
);
|
||||||
|
if (piAuthMounts.length !== 1 || piAuthMounts[0].type !== "bind" || !piAuthMounts[0].read_only) {
|
||||||
|
throw new Error("Pi auth must be one read-only file bind");
|
||||||
|
}
|
||||||
NODE
|
NODE
|
||||||
|
|
||||||
render_profile local deploy/env/local.env.example deploy/compose.local.yaml
|
render_profile local deploy/env/local.env.example deploy/compose.local.yaml
|
||||||
|
|||||||
Reference in New Issue
Block a user