# Lokaler LLM-Server: llama-swap (llama.cpp/ROCm + whisper/sd-server) hinter Caddy (IP-Filter + API-Key) # Web-Chat: Open WebUI, ebenfalls hinter Caddy (IP-Filter + eigener Login) # Start: docker compose up -d --build Logs: docker compose logs -f llama-swap name: localai services: llama-swap: # ROCm-Image + whisper-server/sd-server aus dem unified-Image, siehe llama-swap/Dockerfile build: context: ./llama-swap args: LLAMA_SWAP_TAG: ${LLAMA_SWAP_TAG:-v265-rocm-b11610} UNIFIED_TAG: ${UNIFIED_TAG:-unified-vulkan-265} image: localai/llama-swap:${LLAMA_SWAP_TAG:-v265-rocm-b11610}-mm restart: unless-stopped # nur lokal erreichbar – von außen ausschließlich über Caddy ports: - "127.0.0.1:${BACKEND_PORT:-8080}:8080" user: "${HOST_UID:-1000}:${HOST_GID:-1000}" group_add: - "${RENDER_GID}" - "${VIDEO_GID}" devices: - /dev/kfd - /dev/dri security_opt: - seccomp=unconfined ipc: host environment: HOME: /tmp LLAMA_CACHE: /models HIP_VISIBLE_DEVICES: "${HIP_VISIBLE_DEVICES:-0}" # Vulkan (sd-server) zählt die iGPU mit – hier ist die RX 6950 XT Gerät 1 GGML_VK_VISIBLE_DEVICES: "${VK_VISIBLE_DEVICES:-1}" HF_TOKEN: "${HF_TOKEN:-}" volumes: - ./models:/models - ./llama-swap/config.yaml:/app/config.yaml:ro healthcheck: test: ["CMD", "curl", "-fsS", "http://127.0.0.1:8080/health"] interval: 30s timeout: 5s retries: 3 caddy: image: caddy:${CADDY_TAG:-2.10.2-alpine} restart: unless-stopped # Host-Netz: Quell-IP bleibt erhalten und ufw greift (Docker-Port-Publishing umgeht ufw) network_mode: host environment: LLM_API_KEY: "${LLM_API_KEY:?LLM_API_KEY in .env setzen}" ALLOWED_NETS: "${ALLOWED_NETS:-127.0.0.0/8 ::1}" LISTEN_PORT: "${LISTEN_PORT:-8800}" BACKEND_PORT: "${BACKEND_PORT:-8080}" WEBUI_PORT: "${WEBUI_PORT:-8801}" WEBUI_BACKEND_PORT: "${WEBUI_BACKEND_PORT:-3000}" volumes: - ./caddy/Caddyfile:/etc/caddy/Caddyfile:ro depends_on: - llama-swap - open-webui # Web-Chat im Browser. Spricht intern direkt mit llama-swap (Docker-Netz, ohne Caddy). # Die Werte unten gelten nur beim ersten Start – danach im Admin-Bereich ändern. open-webui: image: ghcr.io/open-webui/open-webui:${OPEN_WEBUI_TAG:-v0.11.4} restart: unless-stopped # nur lokal erreichbar – von außen ausschließlich über Caddy ports: - "127.0.0.1:${WEBUI_BACKEND_PORT:-3000}:8080" environment: WEBUI_SECRET_KEY: "${WEBUI_SECRET_KEY:?WEBUI_SECRET_KEY in .env setzen}" # erster Account wird Admin, weitere müssen freigeschaltet werden DEFAULT_USER_ROLE: pending ENABLE_VERSION_UPDATE_CHECK: "false" ENABLE_OLLAMA_API: "false" OPENAI_API_BASE_URL: http://llama-swap:8080/v1 OPENAI_API_KEY: none # nur eine Chat-Sitzung gleichzeitig (-np 1): keine Zusatz-Requests beim Tippen ENABLE_AUTOCOMPLETE_GENERATION: "false" ENABLE_FOLLOW_UP_GENERATION: "false" ENABLE_EVALUATION_ARENA_MODELS: "false" # Dokumente/RAG: Embeddings von nomic-embed statt eines lokalen Downloads RAG_EMBEDDING_ENGINE: openai RAG_EMBEDDING_MODEL: nomic-embed RAG_OPENAI_API_BASE_URL: http://llama-swap:8080/v1 RAG_OPENAI_API_KEY: none RAG_EMBEDDING_MODEL_AUTO_UPDATE: "false" # Spracheingabe über whisper AUDIO_STT_ENGINE: openai AUDIO_STT_MODEL: whisper AUDIO_STT_OPENAI_API_BASE_URL: http://llama-swap:8080/v1 AUDIO_STT_OPENAI_API_KEY: none WHISPER_MODEL_AUTO_UPDATE: "false" # Bilder über z-image (verdrängt das Chat-Modell, siehe config.yaml) ENABLE_IMAGE_GENERATION: "true" IMAGE_GENERATION_ENGINE: openai IMAGE_GENERATION_MODEL: z-image IMAGE_SIZE: 1024x1024 IMAGES_OPENAI_API_BASE_URL: http://llama-swap:8080/v1 IMAGES_OPENAI_API_KEY: none volumes: - open-webui:/app/backend/data depends_on: - llama-swap volumes: open-webui: