diff --git a/mcp-stack.compose.yml b/mcp-stack.compose.yml index b73f6cc..6726bf2 100644 --- a/mcp-stack.compose.yml +++ b/mcp-stack.compose.yml @@ -230,7 +230,11 @@ services: # /config only. /data is a volume instead, because Caddy keeps the certificate and its ACME # account key there: on tmpfs both would be thrown away at every restart, and asking the CA # for a fresh certificate each time runs into its duplicate-issuance limit within a week. - - /config:rw,noexec,nosuid,size=16m + # + # With the uid and gid of the user it runs as: a tmpfs starts out owned by root, and Caddy + # could not even create /config/caddy. Compose's long tmpfs syntax has no uid/gid field, so + # this is the raw mount-options string, as for the proxy's /var/log/squid below. + - /config:rw,noexec,nosuid,size=16m,uid=${MCP_UID:-10001},gid=${MCP_GID:-10001} volumes: - type: bind source: ${MCP_GATEWAY_CADDYFILE:-./mcp-stack.Caddyfile} @@ -262,10 +266,39 @@ services: - "127.0.0.1:${BROWSER_MCP_PORT:-3103}:3103" - "127.0.0.1:${MINIO_MCP_PORT:-3104}:3104" networks: [gateway, coding-control, dev-server-control, workspace-browser, minio-control] - depends_on: [coding-agent-mcp, dev-server-mcp, browser-mcp, minio-mcp] + depends_on: + caddy-data-init: + condition: service_completed_successfully + coding-agent-mcp: + condition: service_started + dev-server-mcp: + condition: service_started + browser-mcp: + condition: service_started + minio-mcp: + condition: service_started restart: unless-stopped logging: *default-logging + # Gives Caddy's /data volume to the user the gateway runs as, every time the stack starts. A + # named volume belongs to whoever created it - root, or the user of an earlier run - and the + # gateway, running as MCP_UID, then cannot write the certificate or the ACME account key: it + # answers on port 80 but never gets a certificate, and port 443 fails the TLS handshake. Runs as + # root with nothing but CAP_CHOWN, no network, and exits. + caddy-data-init: + image: caddy:2 + user: "0:0" + command: ["chown", "-R", "${MCP_UID:-10001}:${MCP_GID:-10001}", "/data"] + read_only: true + cap_drop: [ALL] + cap_add: [CHOWN] + security_opt: [no-new-privileges:true] + network_mode: none + volumes: + - caddy-data:/data + restart: "no" + logging: *default-logging + networks: gateway: coding-control: