services: mqttctl: build: context: . dockerfile: dockerfiles/mqttctl.Dockerfile restart: unless-stopped depends_on: broker-agent: condition: service_healthy mqttctl-mcp-keygen: condition: service_completed_successfully environment: PORT: "3000" HOST: "0.0.0.0" ORIGIN: "http://localhost:3000" MQTTCTL_CONFIG_PATH: /app/config/mqttctl.config.json5 MQTTCTL_SECRETS_PATH: /app/config/mqttctl.secrets.json5 MQTTCTL_DB_KIND: sqlite MQTTCTL_SQLITE_PATH: /app/data/mqttctl.sqlite MQTTCTL_UI_OVERRIDE_CSS_PATH: /app/config/custom.css NODE_EXTRA_CA_CERTS: /mosquitto/config/certs/ca/ca.crt MQTTCTL_LOG_CONSOLE_FORMAT: text MQTTCTL_MCP_AUTH_ENABLED: "true" MQTTCTL_MCP_PUBLIC_KEY_PATH: /run/mqttctl-mcp-public/signing-public.pem volumes: - ./config/compose/gui-api/mqttctl.config.json5:/app/config/mqttctl.config.json5:ro - ./config/compose/gui-api/mqttctl.secrets.json5:/app/config/mqttctl.secrets.json5:ro - ./config/compose/gui-api/custom.css:/app/config/custom.css:ro - ./config/compose/gui-api/app-data:/app/data - mqttctl-mcp-public:/run/mqttctl-mcp-public:ro - mqttctl-broker-public:/mosquitto/config/certs:ro ports: - "3000:3000" broker-agent: build: context: . dockerfile: dockerfiles/broker-agent.Dockerfile environment: MQTTCTL_BROKER_AGENT_CONFIG_PATH: /etc/mqttctl/broker-agent.config.json MQTTCTL_TLS_PUBLIC_DIR: /run/mqttctl-broker-public MQTTCTL_LOG_CONSOLE_FORMAT: text volumes: - ./config/compose/mqtt-agent/broker-agent.config.json:/etc/mqttctl/broker-agent.config.json:ro - ./config/compose/mqtt-agent:/mosquitto/config - ./config/compose/mqtt-agent/shared/data:/mosquitto/data - mqttctl-broker-public:/run/mqttctl-broker-public ports: - "1883:1883" - "8883:8883" - "9001:9001" healthcheck: test: ["CMD", "curl", "--fail", "--silent", "--cacert", "/mosquitto/config/certs/ca/ca.crt", "https://localhost:3943/healthz"] interval: 5s timeout: 5s retries: 12 start_period: 10s mqttctl-mcp-keygen: build: context: ./mcp dockerfile: Dockerfile user: "0:0" command: ["node", "scripts/generate-signing-keypair.mjs"] restart: "no" environment: MQTTCTL_MCP_PRIVATE_KEY_FILE: /run/mqttctl-mcp-private/signing-private.pem MQTTCTL_MCP_PUBLIC_KEY_FILE: /run/mqttctl-mcp-public/signing-public.pem MCP_KEY_OWNER_UID: "1000" MCP_KEY_OWNER_GID: "1000" volumes: - mqttctl-mcp-private:/run/mqttctl-mcp-private - mqttctl-mcp-public:/run/mqttctl-mcp-public mqttctl-mcp: build: context: ./mcp dockerfile: Dockerfile restart: unless-stopped depends_on: mqttctl-mcp-keygen: condition: service_completed_successfully mqttctl: condition: service_started environment: MQTTCTL_BASE_URL: http://mqttctl:3000 MQTTCTL_MCP_PRIVATE_KEY_FILE: /run/mqttctl-mcp-private/signing-private.pem MQTTCTL_MCP_KEY_ID: compose MQTTCTL_MCP_AUDIENCE: mqttctl-api MCP_READ_BEARER_TOKENS: MCP_READWRITE_BEARER_TOKENS: HTTPS_ENABLED: "true" HTTP_ENABLED: "false" MCP_FAILURE_RESTART_DELAY_SECONDS: "60" volumes: - mqttctl-mcp-private:/run/mqttctl-mcp-private:ro - mqttctl-mcp-data:/app/data ports: - "3443:3443" healthcheck: test: ["CMD-SHELL", "curl --insecure --fail --silent https://localhost:3443/healthz >/dev/null && curl --insecure --fail --silent https://localhost:3443/readyz >/dev/null"] interval: 30s timeout: 10s retries: 5 start_period: 20s volumes: mqttctl-broker-public: mqttctl-mcp-private: mqttctl-mcp-public: mqttctl-mcp-data: