docker-compose.yml
Rama main · réplica de lectura del repositorio original.
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