Ctrl K
ComunidadGuías…

docker-compose.yml

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

Archivo original ↗Preguntar a KiBot
name: omega

services:

  nginx:
    build:
      context: .
      dockerfile: docker/nginx.Dockerfile
    container_name: omega-nginx
    restart: unless-stopped
    mem_limit: "${NGINX_MEMORY_LIMIT:-256m}"
    cpus: "${NGINX_CPU_LIMIT:-1.0}"
    pids_limit: 128
    # Loopback by default. A bare "80:80" is reachable from every
    # machine on the coffee shop wifi, and there is no login wall in
    # front of Jun worth that. BIND_ADDR=0.0.0.0 opens it up, which
    # is also what a public TLS_MODE needs so Let's Encrypt can reach
    # the challenge.
    ports:
      - "${BIND_ADDR:-127.0.0.1}:80:80"
      - "${BIND_ADDR:-127.0.0.1}:443:443"
    environment:
      DOMAIN:    "${DOMAIN:-localhost}"
      TLS_MODE:  "${TLS_MODE:-off}"
      OMEGA_EXTRA_HOSTS: "${OMEGA_EXTRA_HOSTS:-}"
    volumes:
      - letsencrypt:/etc/letsencrypt:ro
      - certbot_webroot:/var/www/certbot:ro
      - selfsigned:/etc/nginx/selfsigned
    depends_on:
      php:
        condition: service_healthy
    healthcheck:
      test: ["CMD", "curl", "-fsS", "http://127.0.0.1/health"]
      interval: 10s
      timeout: 3s
      retries: 5
      start_period: 10s
    security_opt:
      - "no-new-privileges:true"
    cap_drop: [ALL]
    cap_add: [CHOWN, DAC_OVERRIDE, NET_BIND_SERVICE, SETGID, SETUID]
    networks: [omega]

  php:
    build:
      context: .
      dockerfile: docker/php.Dockerfile
    container_name: omega-php
    restart: unless-stopped
    mem_limit: "${PHP_MEMORY_LIMIT:-1g}"
    cpus: "${PHP_CPU_LIMIT:-2.0}"
    pids_limit: 256
    # NO read_only here, unlike ollama and llamacpp. sync-webapp.sh
    # pushes webapp/ in with docker cp and the daemon refuses that
    # against a read-only rootfs ("container rootfs is marked
    # read-only"), which kills the entire dev loop. php still runs as
    # www-data with cap_drop ALL and no-new-privileges.
    tmpfs:
      - /tmp:size=128m,mode=1777
    expose:
      - "9000"
    environment:
      AI_PROVIDER: "${AI_PROVIDER:-ollama}"
      OLLAMA_URL: "${OLLAMA_URL:-http://ollama:11434}"
      OLLAMA_API_KEY: "${OLLAMA_API_KEY:-}"
      OLLAMA_MODELS_TO_PULL: "${OLLAMA_MODELS_TO_PULL:-hf.co/efficiencyx/Jun-LoRA-E2B-GGUF:Q4_K_M}"
      TITLE_MODEL: "${TITLE_MODEL-hf.co/efficiencyx/Titlewen-GGUF:F16}"
      OLLAMA_MTP: "${OLLAMA_MTP:-}"
      OLLAMA_MTP_MODEL: "${OLLAMA_MTP_MODEL:-jun-mtp}"
      OPENROUTER_API_KEY: "${OPENROUTER_API_KEY:-}"
      OPENROUTER_MODEL: "${OPENROUTER_MODEL:-}"
      LLAMACPP_URL: "${LLAMACPP_URL:-http://llamacpp:8080}"
      LLAMACPP_MODEL_HF: "${LLAMACPP_MODEL_HF:-efficiencyx/Jun-LoRA-E2B-GGUF:Q4_K_M}"
      LLAMACPP_MODEL_FILE: "${LLAMACPP_MODEL_FILE:-}"
      LLAMACPP_MODEL_ALIAS: "${LLAMACPP_MODEL_ALIAS:-jun-local}"
      LLAMACPP_MTP: "${LLAMACPP_MTP:-}"
      VLLM_URL: "${VLLM_URL:-}"
      VLLM_API_KEY: "${VLLM_API_KEY:-}"
      VLLM_MODEL: "${VLLM_MODEL:-}"
      OMEGA_NUM_CTX: "${OMEGA_NUM_CTX:-}"
      OMEGA_TURN_TIMEOUT_S: "${OMEGA_TURN_TIMEOUT_S:-}"
      OMEGA_STREAM_IDLE_S: "${OMEGA_STREAM_IDLE_S:-}"
      OMEGA_DEV_KEY: "${OMEGA_DEV_KEY:-}"
      OMEGA_REGISTRATION_KEY: "${OMEGA_REGISTRATION_KEY:-}"
      BIND_ADDR: "${BIND_ADDR:-127.0.0.1}"
      OMEGA_ALLOWED_HOSTS: "${DOMAIN:-localhost},localhost,127.0.0.1,::1,${OMEGA_EXTRA_HOSTS:-}"
      OMEGA_ALLOWED_ORIGINS: "${OMEGA_ALLOWED_ORIGINS:-}"
      TRUST_PROXY: "${TRUST_PROXY:-}"
      # start.sh reads this on the host, php has no GPU device of
      # its own
      OMEGA_GPU_VRAM_MB: "${OMEGA_GPU_VRAM_MB:-}"
      LLAMACPP_TOOLS: "${LLAMACPP_TOOLS:-}"
      FLEE_BANS: "${FLEE_BANS:-on}"
      FREE_ROAM: "${FREE_ROAM:-off}"
      WATCH_FRAME_EVERY: "${WATCH_FRAME_EVERY:-auto}"
      LAN_INFERENCE: "${LAN_INFERENCE:-off}"
      JUN_LAN_TOKEN: "${JUN_LAN_TOKEN:-}"
      GAME_BRIDGE: "${GAME_BRIDGE:-off}"
      CONSOLIDATION_THINK: "${CONSOLIDATION_THINK:-}"
      CONSOLIDATION_STALL_SECONDS: "${CONSOLIDATION_STALL_SECONDS:-}"
      # KOKORO_URL is the old name, kept so existing .env files
      # still work
      TTS_URL: "${TTS_URL:-}"
      KOKORO_URL: "${KOKORO_URL:-http://tts:8001}"
      KARAOKE_URL: "${KARAOKE_URL:-http://karaoke:8001}"
      SIDECAR_SECRET: "${SIDECAR_SECRET:-}"
    volumes:
      - omega_state:/var/lib/omega
      - ./tools:/var/www/omega/tools
    # no depends_on for the model server or TTS, ON PURPOSE. they
    # come and go with their profiles, so they're soft dependencies
    healthcheck:
      test: ["CMD", "cgi-fcgi", "-bind", "-connect", "127.0.0.1:9000"]
      interval: 10s
      timeout: 3s
      retries: 5
      start_period: 15s
    security_opt:
      - "no-new-privileges:true"
    cap_drop: [ALL]
    networks: [omega]

  ollama:
    build:
      context: .
      dockerfile: docker/ollama.Dockerfile
    container_name: omega-ollama
    profiles: [ollama]
    restart: unless-stopped
    mem_limit: "${OLLAMA_MEMORY_LIMIT:-16g}"
    cpus: "${OLLAMA_CPU_LIMIT:-8.0}"
    pids_limit: 512
    read_only: true
    tmpfs:
      - /tmp:size=256m,mode=1777
    environment:
      OLLAMA_MODELS_TO_PULL: "${OLLAMA_MODELS_TO_PULL:-hf.co/efficiencyx/Jun-LoRA-E2B-GGUF:Q4_K_M}"
      TITLE_MODEL: "${TITLE_MODEL-hf.co/efficiencyx/Titlewen-GGUF:F16}"
      OLLAMA_MTP: "${OLLAMA_MTP:-}"
      OLLAMA_MTP_N_MAX: "${OLLAMA_MTP_N_MAX:-4}"
      OLLAMA_MTP_MODEL: "${OLLAMA_MTP_MODEL:-jun-mtp}"
      # cap how many requests and models Ollama holds at once. each
      # one keeps its own KV cache, the memory of the prompt it
      # already read, so they add up fast.
      OLLAMA_NUM_PARALLEL: "${OLLAMA_NUM_PARALLEL:-1}"
      OLLAMA_MAX_LOADED_MODELS: "${OLLAMA_MAX_LOADED_MODELS:-3}"
      OLLAMA_KEEP_ALIVE: "${OLLAMA_KEEP_ALIVE:-5m}"
      # q8_0 stores that cache smaller. it needs flash attention,
      # without it we get f16.
      OLLAMA_FLASH_ATTENTION: "${OLLAMA_FLASH_ATTENTION:-1}"
      OLLAMA_KV_CACHE_TYPE: "${OLLAMA_KV_CACHE_TYPE:-q8_0}"
    volumes:
      - ollama_data:/root/.ollama
    healthcheck:
      test: ["CMD", "curl", "-fsS", "http://127.0.0.1:11434/api/tags"]
      interval: 10s
      timeout: 3s
      retries: 30
      start_period: 30s
    security_opt:
      - "no-new-privileges:true"
    cap_drop: [ALL]
    networks: [omega]

  llamacpp:
    image: ghcr.io/ggml-org/llama.cpp:server@sha256:8c74db29f1a2bef3f0a331b52c4d6214601dfceed4bee0b94cc48b3b23ff257d
    container_name: omega-llamacpp
    profiles: [llamacpp]
    restart: unless-stopped
    mem_limit: "${LLAMACPP_MEMORY_LIMIT:-16g}"
    cpus: "${LLAMACPP_CPU_LIMIT:-8.0}"
    pids_limit: 512
    read_only: true
    tmpfs:
      - /tmp:size=256m,mode=1777
    # router mode, the preset file comes out of these on every start
    entrypoint: ["/bin/sh", "/jun/llamacpp-entrypoint.sh"]
    environment:
      LLAMACPP_MODEL_HF: "${LLAMACPP_MODEL_HF:-efficiencyx/Jun-LoRA-E2B-GGUF:Q4_K_M}"
      LLAMACPP_MODEL_FILE: "${LLAMACPP_MODEL_FILE:-}"
      LLAMACPP_MODEL_ALIAS: "${LLAMACPP_MODEL_ALIAS:-jun-local}"
      LLAMACPP_MTP: "${LLAMACPP_MTP:-}"
      LLAMACPP_MTP_N_MAX: "${LLAMACPP_MTP_N_MAX:-4}"
      LLAMACPP_PARALLEL: "${LLAMACPP_PARALLEL:-1}"
      TITLE_MODEL: "${TITLE_MODEL-hf.co/efficiencyx/Titlewen-GGUF:F16}"
      OMEGA_NUM_CTX: "${OMEGA_NUM_CTX:-}"
      # -hf downloads land in the HF hub layout under HF_HOME now,
      # not ~/.cache/llama.cpp. the root fs is read-only, so without
      # this every download dies on "Read-only file system"
      HF_HOME: /root/.cache/llama.cpp/huggingface
    volumes:
      - llamacpp_cache:/root/.cache/llama.cpp
      - ./docker/llamacpp-entrypoint.sh:/jun/llamacpp-entrypoint.sh:ro
    healthcheck:
      test: ["CMD", "curl", "-fsS", "http://127.0.0.1:8080/health"]
      interval: 10s
      timeout: 3s
      retries: 90
      start_period: 60s
    security_opt:
      - "no-new-privileges:true"
    cap_drop: [ALL]
    networks: [omega]

  tts:
    build:
      context: .
      dockerfile: docker/tts.Dockerfile
      args:
        TORCH_INDEX: "${TTS_TORCH_INDEX:-https://download.pytorch.org/whl/cpu}"
    container_name: omega-tts
    restart: unless-stopped
    profiles: [voice]
    mem_limit: "${TTS_MEMORY_LIMIT:-8g}"
    cpus: "${TTS_CPU_LIMIT:-4.0}"
    pids_limit: 256
    read_only: true
    tmpfs:
      # exec ON PURPOSE. phonemizer copies libespeak-ng.so in here and
      # dlopens it, noexec = no espeak and her French/Italian/... comes out as English
      - /tmp:size=512m,mode=1777,exec
    environment:
      SIDECAR_SECRET: "${SIDECAR_SECRET:-}"
      TTS_DEVICE: "${TTS_DEVICE:-cpu}"
      STT_MODEL: "${STT_MODEL:-base}"
      STT_LANG: "${STT_LANG-}"
      STT_DEVICE: "${STT_DEVICE:-cpu}"
      STT_MAX_DURATION_S: "${STT_MAX_DURATION_S:-120}"
      STT_MAX_CONCURRENT: "${STT_MAX_CONCURRENT:-1}"
      TTS_MAX_CONCURRENT: "${TTS_MAX_CONCURRENT:-2}"
      TTS_MAX_QUEUE: "${TTS_MAX_QUEUE:-8}"
    volumes:
      - tts_cache:/home/omega/.cache
    healthcheck:
      test: ["CMD", "curl", "-fsS", "http://127.0.0.1:8001/health"]
      interval: 10s
      timeout: 5s
      retries: 30
      start_period: 300s
    security_opt:
      - "no-new-privileges:true"
    cap_drop: [ALL]
    cap_add: [CHOWN, DAC_OVERRIDE, SETGID, SETUID]
    networks: [omega]

  # the same server.py as `tts`, built with demucs (splits a song
  # into vocals and backing) and, on the GPU overlays, a CUDA or
  # ROCm torch. it sits behind a profile because the image is
  # several GB and only karaoke wants it. with the profile off
  # api/karaoke.php just can't reach the host, and the webapp
  # greys the karaoke button out.
  karaoke:
    build:
      context: .
      dockerfile: docker/karaoke.Dockerfile
      args:
        TORCH_INDEX: "${KARAOKE_TORCH_INDEX:-https://download.pytorch.org/whl/cpu}"
    container_name: omega-karaoke
    profiles: [karaoke]
    restart: unless-stopped
    mem_limit: "${KARAOKE_MEMORY_LIMIT:-12g}"
    cpus: "${KARAOKE_CPU_LIMIT:-6.0}"
    pids_limit: 384
    read_only: true
    tmpfs:
      - /tmp:size=1g,mode=1777
    environment:
      SIDECAR_SECRET: "${SIDECAR_SECRET:-}"
      SEP_DEVICE: "${SEP_DEVICE:-auto}"
      STT_MODEL: "${STT_MODEL:-base}"
      STT_LANG: "${STT_LANG-}"
      STT_DEVICE: "${STT_DEVICE:-cpu}"
      SEP_MAX_DURATION_S: "${SEP_MAX_DURATION_S:-900}"
      SEP_MAX_CONCURRENT: "${SEP_MAX_CONCURRENT:-1}"
      SEP_MAX_JOBS: "${SEP_MAX_JOBS:-4}"
      STT_MAX_CONCURRENT: "${STT_MAX_CONCURRENT:-1}"
    volumes:
      - karaoke_cache:/home/omega/.cache
    healthcheck:
      test: ["CMD", "curl", "-fsS", "http://127.0.0.1:8001/health"]
      interval: 10s
      timeout: 5s
      retries: 30
      start_period: 300s
    security_opt:
      - "no-new-privileges:true"
    cap_drop: [ALL]
    cap_add: [CHOWN, DAC_OVERRIDE, SETGID, SETUID]
    networks: [omega]

  certbot:
    build:
      context: .
      dockerfile: docker/certbot.Dockerfile
    container_name: omega-certbot
    profiles: [prod]
    restart: unless-stopped
    mem_limit: "${CERTBOT_MEMORY_LIMIT:-512m}"
    cpus: "${CERTBOT_CPU_LIMIT:-1.0}"
    pids_limit: 128
    environment:
      DOMAIN: "${DOMAIN:-localhost}"
      EMAIL:  "${EMAIL:-admin@localhost}"
    volumes:
      - letsencrypt:/etc/letsencrypt
      - certbot_webroot:/var/www/certbot
    # the challenge is answered by nginx on :80, so asking before it's
    # up is a guaranteed failed validation
    depends_on:
      nginx:
        condition: service_healthy
    security_opt:
      - "no-new-privileges:true"
    cap_drop: [ALL]
    networks: [omega]

volumes:
  ollama_data:
  llamacpp_cache:
  tts_cache:
    # Pinned to the old volume name so an install that already exists
    # keeps the weights it downloaded, 300MB and up, instead of
    # fetching them again.
    name: omega_kokoro_cache
  karaoke_cache:
  omega_state:
  letsencrypt:
  certbot_webroot:
  selfsigned:

networks:
  omega:
    name: omega