services: # Trusted search infrastructure; also provisioned by the development AppHost. # No host port: the broker reaches it on the Compose network. searxng: image: docker.io/searxng/searxng:2026.10.19-81371861f@sha256:5ed0323b5f5f8701264ef65e239a2bd83cb57098f2b971fa30bf79c06eeae271 restart: unless-stopped expose: - "8080" entrypoint: ["/bin/sh", "/usr/local/bin/csweet-searxng-start.sh"] environment: FORCE_OWNERSHIP: "false" volumes: - ./docker/searxng/settings.yml:/etc/searxng/settings.yml:ro - ./docker/searxng/start.sh:/usr/local/bin/csweet-searxng-start.sh:ro - csweet-searxng-cache:/var/cache/searxng healthcheck: test: ["CMD", "/usr/local/searxng/.venv/bin/python", "-c", "import urllib.request; urllib.request.urlopen('http://127.0.0.1:8080/healthz', timeout=3).read()"] interval: 10s timeout: 5s retries: 5 start_period: 30s csweet-githost: build: context: . dockerfile: docker/githost.Dockerfile expose: - "8080" environment: TrustedServiceAuthentication__KeyId: core TrustedServiceAuthentication__KeyFile: /trust/git.key CSweet__SourceControl__Storage__RepositoryRoot: /data/repositories CSweet__SourceControl__Storage__ExpectedStoreId: ${CSWEET_GIT_STORE_ID:-csweet-local-git} CSweet__SourceControl__Storage__TemporaryRoot: /tmp/csweet-git volumes: - ${CSWEET_GIT_DATA_VOLUME:-csweet-git-data}:/data - csweet-git-trust:/trust healthcheck: test: ["CMD-SHELL", "curl -fsS http://localhost:8080/health || exit 1"] interval: 10s timeout: 5s retries: 5 # --------------------------------------------------------- # Public web entry point (Blazor WASM served by nginx) # --------------------------------------------------------- csweet-app: build: context: . dockerfile: docker/app.Dockerfile ports: - "${APP_PORT:-8080}:8080" depends_on: csweet-api: condition: service_healthy healthcheck: test: ["CMD-SHELL", "wget -q -O /dev/null http://127.0.0.1:8080/health || exit 1"] interval: 10s timeout: 5s retries: 5 start_period: 10s # --------------------------------------------------------- # Database migrations and first-run seed data # --------------------------------------------------------- csweet-migrator: build: context: . dockerfile: docker/migrator.Dockerfile depends_on: postgres: condition: service_healthy restart: "no" environment: DOTNET_ENVIRONMENT: ${DOTNET_ENVIRONMENT:-Production} ConnectionStrings__Postgres: ${CSWEET_CONNECTIONSTRINGS__POSTGRES:-Host=postgres;Port=5432;Database=csweet;Username=csweet;Password=change-me-in-production} # --------------------------------------------------------- # API and application services # --------------------------------------------------------- csweet-api: build: context: . dockerfile: docker/api.Dockerfile expose: - "8080" extra_hosts: - "host.docker.internal:host-gateway" depends_on: postgres: condition: service_healthy csweet-migrator: condition: service_completed_successfully csweet-githost: condition: service_healthy csweet-agenthost: condition: service_started environment: ASPNETCORE_ENVIRONMENT: ${ASPNETCORE_ENVIRONMENT:-Production} DOTNET_ENVIRONMENT: ${DOTNET_ENVIRONMENT:-Production} ConnectionStrings__Postgres: ${CSWEET_CONNECTIONSTRINGS__POSTGRES:-Host=postgres;Port=5432;Database=csweet;Username=csweet;Password=change-me-in-production} CSWEET_SETUP__ALLOW_FIRST_RUN: ${CSWEET_SETUP__ALLOW_FIRST_RUN:-true} CSweet__Smtp__Host: ${CSWEET_SMTP__HOST:-} CSweet__Smtp__Port: ${CSWEET_SMTP__PORT:-587} CSweet__Smtp__EnableSsl: ${CSWEET_SMTP__ENABLESSL:-true} CSweet__Smtp__UserName: ${CSWEET_SMTP__USERNAME:-} CSweet__Smtp__Password: ${CSWEET_SMTP__PASSWORD:-} CSweet__Smtp__FromAddress: ${CSWEET_SMTP__FROMADDRESS:-} CSweet__Smtp__FromName: ${CSWEET_SMTP__FROMNAME:-C-Sweet} CSweet__Smtp__PublicAppUrl: ${CSWEET_SMTP__PUBLICAPPURL:-http://localhost:8080} CSWEET_LLM__DEFAULT_PROVIDER_TYPE: ${CSWEET_LLM__DEFAULT_PROVIDER_TYPE:-LMStudio} CSWEET_LLM__DEFAULT_BASE_URL: ${CSWEET_LLM__DEFAULT_BASE_URL:-http://host.docker.internal:1234/v1} CSWEET_LLM__DEFAULT_API_KEY: ${CSWEET_LLM__DEFAULT_API_KEY:-lm-studio} CSWEET_AGENT_PACKAGE_CACHE: /var/lib/csweet/agents/packages CSweet__SourceControl__GitHostBaseUrl: http://csweet-githost:8080 CSweet__SourceControl__TrustedServiceKeyId: core CSweet__SourceControl__TrustedServiceKeyFile: /trust/git.key CSweet__Secrets__FilePath: /state/provider-secrets.json CSweet__GenAi__MediaRoot: /media CSweet__AgentCatalog__LocalDirectoryPath: /var/lib/csweet/plugins/agents volumes: - csweet-agent-packages:/var/lib/csweet/agents/packages:ro - csweet-provider-secrets:/state - csweet-git-trust:/trust:ro - csweet-media:/media - ${CSWEET_LOCAL_AGENTS_PATH:-./Plugins/Agents}:/var/lib/csweet/plugins/agents:ro healthcheck: test: ["CMD-SHELL", "curl -fsS http://localhost:8080/api/health || exit 1"] interval: 10s timeout: 5s retries: 5 start_period: 30s # --------------------------------------------------------- # Local worker runtime # --------------------------------------------------------- csweet-worker: build: context: . dockerfile: docker/worker.Dockerfile depends_on: postgres: condition: service_healthy csweet-migrator: condition: service_completed_successfully csweet-githost: condition: service_healthy csweet-api: condition: service_healthy csweet-agenthost: condition: service_started environment: DOTNET_ENVIRONMENT: ${DOTNET_ENVIRONMENT:-Production} ConnectionStrings__Postgres: ${CSWEET_CONNECTIONSTRINGS__POSTGRES:-Host=postgres;Port=5432;Database=csweet;Username=csweet;Password=change-me-in-production} CSWEET_AGENT_SOURCE_ROOT: /var/lib/csweet/agents/sources CSWEET_AGENT_PACKAGE_CACHE: /var/lib/csweet/agents/packages CSWEET_AGENT_SOURCE_VOLUME: csweet-agent-sources CSWEET_AGENT_PACKAGE_VOLUME: csweet-agent-packages CSweet__AgentRuntime__McpEndpoint: http://csweet-agenthost:8081/mcp CSweet__AgentRuntime__McpGatewayContainer: ${CSWEET_AGENTHOST_CONTAINER_NAME:-csweet-agenthost} CSweet__AgentRuntime__DockerNetworkName: csweet-runtime CSweet__AgentRuntime__CleanupContainersOnStartup: ${CSWEET_AGENT_RUNTIME_CLEANUP_ON_STARTUP:-true} CSweet__AgentRuntime__SessionWatchdogEnabled: ${CSWEET_AGENT_RUNTIME_SESSION_WATCHDOG_ENABLED:-true} CSweet__AgentRuntime__SessionWatchdogStartupGraceSeconds: ${CSWEET_AGENT_RUNTIME_SESSION_WATCHDOG_STARTUP_GRACE_SECONDS:-30} CSweet__AgentRuntime__SessionWatchdogIntervalSeconds: ${CSWEET_AGENT_RUNTIME_SESSION_WATCHDOG_INTERVAL_SECONDS:-10} CSweet__AgentRuntime__SessionDisconnectShutdownSeconds: ${CSWEET_AGENT_RUNTIME_SESSION_DISCONNECT_SHUTDOWN_SECONDS:-120} CSweet__AgentRuntime__SoftwareDevelopmentPolyglotImage: ${CSWEET_SOFTWARE_DEVELOPER_IMAGE:-csweet/software-development-polyglot-v1:local} CSweet__AgentRuntime__SoftwareDevelopmentEgressProxyUrl: ${CSWEET_SOFTWARE_DEVELOPER_EGRESS_PROXY_URL:-} group_add: - "${DOCKER_GID:-0}" volumes: - /var/run/docker.sock:/var/run/docker.sock - csweet-agent-sources:/var/lib/csweet/agents/sources - csweet-agent-packages:/var/lib/csweet/agents/packages csweet-agenthost: container_name: ${CSWEET_AGENTHOST_CONTAINER_NAME:-csweet-agenthost} build: context: . dockerfile: docker/agenthost.Dockerfile expose: - "8081" depends_on: searxng: condition: service_started postgres: condition: service_healthy csweet-migrator: condition: service_completed_successfully csweet-githost: condition: service_healthy environment: ASPNETCORE_ENVIRONMENT: ${ASPNETCORE_ENVIRONMENT:-Production} DOTNET_ENVIRONMENT: ${DOTNET_ENVIRONMENT:-Production} CSweet__Search__Searxng__BaseUrl: http://searxng:8080 ConnectionStrings__Postgres: ${CSWEET_CONNECTIONSTRINGS__POSTGRES:-Host=postgres;Port=5432;Database=csweet;Username=csweet;Password=change-me-in-production} CSweet__SourceControl__GitHostBaseUrl: http://csweet-githost:8080 CSweet__SourceControl__TrustedServiceKeyId: core CSweet__SourceControl__TrustedServiceKeyFile: /trust/git.key CSweet__Secrets__FilePath: /state/provider-secrets.json CSweet__GenAi__MediaRoot: /media CSweet__AgentCatalog__LocalDirectoryPath: /var/lib/csweet/plugins/agents CSWEET_AGENT_SOURCE_ROOT: /var/lib/csweet/agents/sources volumes: - csweet-provider-secrets:/state - csweet-git-trust:/trust:ro - csweet-media:/media - csweet-agent-sources:/var/lib/csweet/agents/sources - ${CSWEET_LOCAL_AGENTS_PATH:-./Plugins/Agents}:/var/lib/csweet/plugins/agents:ro # --------------------------------------------------------- # Database (PostgreSQL) # --------------------------------------------------------- postgres: image: postgres:17-alpine expose: - "5432" environment: POSTGRES_DB: ${POSTGRES_DB:-csweet} POSTGRES_USER: ${POSTGRES_USER:-csweet} POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-change-me-in-production} volumes: - csweet-postgres:/var/lib/postgresql/data healthcheck: test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER:-csweet} -d ${POSTGRES_DB:-csweet}"] interval: 10s timeout: 5s retries: 5 volumes: csweet-searxng-cache: name: csweet-searxng-cache driver: local csweet-git-data: driver: local csweet-git-trust: driver: local csweet-postgres: driver: local csweet-agent-sources: name: csweet-agent-sources driver: local csweet-agent-packages: name: csweet-agent-packages driver: local csweet-provider-secrets: name: csweet-provider-secrets driver: local csweet-media: name: csweet-media driver: local