Ctrl K
ComunidadGuías…

docker-compose.selfhost.yml

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
# Self-host Sotto from pre-built public images (no source, no build).
# The curl|bash installer (scripts/install.sh) writes .env and runs this.
#
#   docker compose -f docker-compose.selfhost.yml up -d
#
# Images are published by .github/workflows/oss-image.yml. Postgres and Redis
# are pulled from public registries.
name: sotto

services:
  postgres:
    image: pgvector/pgvector:pg17
    environment:
      POSTGRES_USER: sotto
      POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:?Set POSTGRES_PASSWORD in .env}
      POSTGRES_DB: sotto
    volumes:
      - pgdata:/var/lib/postgresql/data
    healthcheck:
      test: ['CMD-SHELL', 'pg_isready -h 127.0.0.1 -U sotto -d sotto']
      interval: 5s
      timeout: 5s
      retries: 12
    networks: [sotto-network]
    restart: unless-stopped

  redis:
    image: redis:7-alpine
    command: ['redis-server', '--appendonly', 'yes']
    volumes:
      - redisdata:/data
    healthcheck:
      test: ['CMD', 'redis-cli', 'ping']
      interval: 5s
      timeout: 5s
      retries: 12
    networks: [sotto-network]
    restart: unless-stopped

  web:
    image: ghcr.io/affromero/sotto-web:${SOTTO_IMAGE_TAG:-latest}
    env_file: [.env]
    environment:
      NODE_ENV: production
      HOSTNAME: '0.0.0.0'
      BYOK_ENCRYPTION_KEY: ${BYOK_ENCRYPTION_KEY:?Set BYOK_ENCRYPTION_KEY in .env}
      SOTTO_CREDENTIAL_SYNC_DIR: /run/cli-credentials
      CLAUDE_HOME: /home/sotto/.claude
      CODEX_HOME: /home/sotto/.codex
      SIDEDOOR_EXECUTION_DIR: /app/apps/web/.sotto/runtime/executions
    ports:
      - '127.0.0.1:${WEB_PORT:-3000}:3000'
    volumes:
      - storage:/app/apps/web/.sotto/storage
      - executions:/app/apps/web/.sotto/runtime
      - cli-credentials:/run/cli-credentials
      - agent-home:/home/sotto/.claude
      - agent-codex-home:/home/sotto/.codex
    depends_on:
      postgres: { condition: service_healthy }
      redis: { condition: service_healthy }
      credential-sync: { condition: service_healthy }
    healthcheck:
      test:
        [
          'CMD',
          'wget',
          '--no-verbose',
          '--tries=1',
          '--spider',
          'http://127.0.0.1:3000/api/v1/health',
        ]
      interval: 30s
      timeout: 10s
      retries: 5
      start_period: 40s
    networks: [sotto-network]
    restart: unless-stopped

  workers:
    image: ghcr.io/affromero/sotto-workers:${SOTTO_IMAGE_TAG:-latest}
    env_file: [.env]
    environment:
      NODE_ENV: production
      SOTTO_CREDENTIAL_SYNC_DIR: /run/cli-credentials
      CLAUDE_HOME: /home/sotto/.claude
      CODEX_HOME: /home/sotto/.codex
      SIDEDOOR_EXECUTION_DIR: /app/apps/web/.sotto/runtime/executions
    volumes:
      - storage:/app/apps/web/.sotto/storage
      - executions:/app/apps/web/.sotto/runtime
      - cli-credentials:/run/cli-credentials
      - agent-home:/home/sotto/.claude
      - agent-codex-home:/home/sotto/.codex
    depends_on:
      postgres: { condition: service_healthy }
      redis: { condition: service_healthy }
      credential-sync: { condition: service_healthy }
    networks: [sotto-network]
    restart: unless-stopped

  credential-sync:
    image: alpine:3.22
    network_mode: none
    read_only: true
    tmpfs: [/tmp]
    volumes:
      - cli-credentials:/credential-sync
      - ${HOME}/.claude:/host-claude:ro
      - ${HOME}/.codex:/host-codex:ro
      - ./sync-cli-credentials.sh:/usr/local/bin/sync-cli-credentials:ro
    command: ['/bin/sh', '/usr/local/bin/sync-cli-credentials']
    healthcheck:
      test: ['CMD', 'test', '-f', '/credential-sync/ready']
      interval: 2s
      timeout: 1s
      retries: 15
    restart: unless-stopped

volumes:
  # The agent CLI rotates its OAuth refresh token in place and retires the old
  # one, so its credentials file has to outlive the container.
  agent-home:
  agent-codex-home:
  pgdata:
  redisdata:
  storage:
  executions:
  cli-credentials:

networks:
  sotto-network: