Files
oikos/docker-compose.yml
dtoro b37f85ae08
Some checks failed
ci / build-test (push) Has been cancelled
ci / docker-build (push) Has been cancelled
fix: make Nomos actually provision LXCs from chat (pct_create + web fetch)
Root cause of "asks permission but never acts": the approved pct_create
execution failed to parse because the LLM emitted `"privileged":0` /
`"nesting":1` (numbers) into strict `bool` fields, so the container was
never created. Compounded by a hardcoded template name (debian-13.0-1)
that no longer exists on the host, and no way for the agent to read the web.

- flexBool: accept 0/1, "true", bool for privileged/nesting (the exact prod failure)
- pct_create template pre-flight: list host cache, validate/auto-pick newest debian
- pct_create services[] + post_install: one approval provisions a working service
- new http_get MCP tool (sanitized, size-capped, SSRF-guarded) — agent can read repos/sites
- request_execution description: target=host, full JSON schema + example
- SOUL.md: agent CAN fetch the web; prefer one-step provisioning
- default model deepseek-v4-flash -> v4-pro; maxIterations 15 -> 25
- unit tests for flexBool, template resolve, pkg sanitize, HTML sanitize + SSRF block

Verified live on host:strong with a throwaway VMID 999: template auto-resolved,
container created + booted, services installed, post_install ran, then destroyed.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-10 00:28:56 +02:00

176 lines
5.4 KiB
YAML

# Docker Compose for Oikos development
# Usage: docker compose up -d postgres (just the DB)
# make dev (full dev stack)
services:
postgres:
image: timescale/timescaledb:2.17.2-pg16
environment:
POSTGRES_DB: oikos
POSTGRES_USER: oikos
POSTGRES_PASSWORD: ${OIKOS_DB_PASSWORD:-oikos_dev}
ports:
- "5432:5432"
volumes:
- pg-data:/var/lib/postgresql/data
healthcheck:
test: ["CMD", "pg_isready", "-U", "oikos"]
interval: 5s
timeout: 5s
retries: 5
# One-shot: run migrations then exit
migrate:
build:
context: .
dockerfile: compose/oikos/Dockerfile
depends_on:
postgres:
condition: service_healthy
environment:
OIKOS_DATABASE_URL: postgres://oikos:${OIKOS_DB_PASSWORD:-oikos_dev}@postgres:5432/oikos?sslmode=disable
command: ["migrate"]
restart: "no"
# One-shot: ingest seeds then exit
seed:
build:
context: .
dockerfile: compose/oikos/Dockerfile
depends_on:
migrate:
condition: service_completed_successfully
environment:
OIKOS_DATABASE_URL: postgres://oikos:${OIKOS_DB_PASSWORD:-oikos_dev}@postgres:5432/oikos?sslmode=disable
OIKOS_SEEDS_DIR: /seeds
command: ["seed"]
restart: "no"
# API server (Phase 2)
api:
build:
context: .
dockerfile: compose/oikos/Dockerfile
profiles: ["dev", "full"]
depends_on:
seed:
condition: service_completed_successfully
environment:
OIKOS_DATABASE_URL: postgres://oikos:${OIKOS_DB_PASSWORD:-oikos_dev}@postgres:5432/oikos?sslmode=disable
OIKOS_API_LISTEN: ":8090"
OIKOS_ENV: dev
OIKOS_DEBUG: "true"
OIKOS_NOMOS_AGENT_SLUG: ${OIKOS_NOMOS_AGENT_SLUG:-agent:nomos}
NOMOS_PROXY_URL: http://nomos:8092
volumes:
- ${OIKOS_SSH_KEY_PATH:-~/.ssh/id_ed25519}:/etc/oikos/ssh_key:ro
ports:
- "8090:8090"
command: ["api"]
stop_signal: SIGTERM
stop_grace_period: 30s
# Scheduler (Phase 3) — observe loop
scheduler:
build:
context: .
dockerfile: compose/oikos/Dockerfile
profiles: ["dev", "full"]
depends_on:
seed:
condition: service_completed_successfully
environment:
OIKOS_DATABASE_URL: postgres://oikos:${OIKOS_DB_PASSWORD:-oikos_dev}@postgres:5432/oikos?sslmode=disable
OIKOS_DEBUG: "true"
OIKOS_SCHEDULER_INTERVAL: "30s"
OIKOS_SSH_KEY_PATH: /etc/oikos/ssh_key
OIKOS_SSH_USER: root
volumes:
- ${OIKOS_SSH_KEY_PATH:-~/.ssh/id_ed25519}:/etc/oikos/ssh_key:ro
cap_add:
- NET_RAW
command: ["scheduler"]
stop_signal: SIGTERM
stop_grace_period: 30s
# Notifier (Phase 3) — Matrix alerts
notifier:
build:
context: .
dockerfile: compose/oikos/Dockerfile
profiles: ["dev", "full"]
depends_on:
seed:
condition: service_completed_successfully
environment:
OIKOS_DATABASE_URL: postgres://oikos:${OIKOS_DB_PASSWORD:-oikos_dev}@postgres:5432/oikos?sslmode=disable
OIKOS_DEBUG: "true"
OIKOS_APPROVAL_HMAC_SECRET: ${OIKOS_APPROVAL_HMAC_SECRET:-dev-secret}
OIKOS_MATRIX_HOMESERVER: ${OIKOS_MATRIX_HOMESERVER:-https://matrix.hubris.network}
OIKOS_MATRIX_USER: ${OIKOS_MATRIX_USER:-@hermes:hubris.network}
OIKOS_MATRIX_TOKEN: ${OIKOS_MATRIX_TOKEN}
OIKOS_MATRIX_ROOM: ${OIKOS_MATRIX_ROOM:-!alerts:hubris.network}
command: ["notifier"]
stop_signal: SIGTERM
stop_grace_period: 30s
# Nomos agent gateway (Phase 4) — mesh-published :8092
nomos:
build:
context: .
dockerfile: compose/nomos/Dockerfile
profiles: ["full"]
depends_on:
api:
condition: service_started
environment:
NOMOS_MCP_URL: http://api:8090/mcp
NOMOS_AGENT_SLUG: agent:nomos
OPENROUTER_API_KEY: ${OPENROUTER_API_KEY}
NOMOS_MODEL: ${NOMOS_MODEL:-deepseek/deepseek-v4-pro}
DATABASE_URL: postgres://oikos:${OIKOS_DB_PASSWORD:-oikos_dev}@postgres:5432/oikos?sslmode=disable
ports:
- "8092:8092"
stop_signal: SIGTERM
stop_grace_period: 10s
# Redis (required by Infisical — Phase 5)
redis:
image: redis:7-alpine
profiles: ["infisical", "full"]
volumes:
- redis-data:/data
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 5s
timeout: 3s
retries: 5
# Infisical self-hosted (Phase 5 secrets management)
infisical:
image: infisical/infisical:latest
profiles: ["infisical", "full"]
depends_on:
postgres:
condition: service_healthy
redis:
condition: service_healthy
environment:
ENCRYPTION_KEY: ${INFISICAL_ENCRYPTION_KEY:-dev-encryption-key-change-me}
JWT_SIGNUP_SECRET: ${INFISICAL_JWT_SIGNUP_SECRET:-dev-jwt-change-me}
JWT_REFRESH_SECRET: ${INFISICAL_JWT_REFRESH_SECRET:-dev-refresh-change-me}
JWT_AUTH_SECRET: ${INFISICAL_JWT_AUTH_SECRET:-dev-auth-change-me}
JWT_SERVICE_SECRET: ${INFISICAL_JWT_SERVICE_SECRET:-dev-service-change-me}
JWT_MFA_SECRET: ${INFISICAL_JWT_MFA_SECRET:-dev-mfa-change-me}
JWT_PROVIDER_SECRET: ${INFISICAL_JWT_PROVIDER_SECRET:-dev-provider-change-me}
SITE_URL: ${INFISICAL_SITE_URL:-http://localhost:8080}
SMTP_HOST: ""
DB_CONNECTION_URI: postgres://oikos:${OIKOS_DB_PASSWORD:-oikos_dev}@postgres:5432/infisical?sslmode=disable
REDIS_URL: redis://redis:6379
ports:
- "8080:8080"
volumes:
pg-data:
redis-data: