Files
docker-compose/ai/compose.yaml
Sebastian Krüger 16dd8064d4 fix: disable LiteLLM healthcheck due to missing curl
Healthcheck was failing because curl is not installed in the LiteLLM
container, causing Traefik to mark it as unhealthy and not route traffic.
Disabled healthcheck as Traefik doesn't require it for routing.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-09 18:13:26 +01:00

152 lines
6.5 KiB
YAML

services:
# PostgreSQL with pgvector for AI/RAG workloads
ai_postgres:
image: ${AI_POSTGRES_IMAGE:-pgvector/pgvector:pg16}
container_name: ${AI_COMPOSE_PROJECT_NAME}_postgres
restart: unless-stopped
environment:
TZ: ${TIMEZONE:-Europe/Berlin}
POSTGRES_USER: ${AI_DB_USER}
POSTGRES_PASSWORD: ${AI_DB_PASSWORD}
POSTGRES_DB: ${AI_DB_NAME}
POSTGRES_HOST_AUTH_METHOD: scram-sha-256
POSTGRES_INITDB_ARGS: --auth-host=scram-sha-256
volumes:
- ai_postgres_data:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U ${AI_DB_USER}"]
interval: 30s
timeout: 10s
retries: 3
start_period: 40s
networks:
- compose_network
# Open WebUI - ChatGPT-like interface for AI models
webui:
image: ${AI_WEBUI_IMAGE:-ghcr.io/open-webui/open-webui:main}
container_name: ${AI_COMPOSE_PROJECT_NAME}_webui
restart: unless-stopped
environment:
TZ: ${TIMEZONE:-Europe/Berlin}
# Database configuration
DATABASE_URL: postgresql://${AI_DB_USER}:${AI_DB_PASSWORD}@ai_postgres:5432/${AI_DB_NAME}
# OpenAI API configuration (pointing to LiteLLM proxy)
OPENAI_API_BASE_URLS: http://litellm:4000
OPENAI_API_KEYS: sk-1234
# WebUI configuration
WEBUI_NAME: ${AI_WEBUI_NAME:-Pivoine AI}
WEBUI_URL: https://${AI_TRAEFIK_HOST}
WEBUI_SECRET_KEY: ${AI_WEBUI_SECRET_KEY}
# Feature flags
ENABLE_SIGNUP: ${AI_ENABLE_SIGNUP:-true}
ENABLE_RAG_WEB_SEARCH: ${AI_ENABLE_RAG_WEB_SEARCH:-true}
ENABLE_RAG_WEB_LOADER_SSL_VERIFICATION: ${AI_ENABLE_RAG_SSL_VERIFY:-true}
# RAG configuration
RAG_EMBEDDING_ENGINE: ${AI_RAG_EMBEDDING_ENGINE:-openai}
RAG_EMBEDDING_MODEL: ${AI_RAG_EMBEDDING_MODEL:-text-embedding-3-small}
VECTOR_DB: ${AI_VECTOR_DB:-pgvector}
# Email configuration (IONOS SMTP)
SMTP_HOST: ${EMAIL_SMTP_HOST}
SMTP_PORT: ${EMAIL_SMTP_PORT}
SMTP_USER: ${EMAIL_SMTP_USER}
SMTP_PASSWORD: ${EMAIL_SMTP_PASSWORD}
SMTP_FROM_EMAIL: ${EMAIL_FROM}
SMTP_USE_TLS: false
SMTP_USE_SSL: true
volumes:
- ai_webui_data:/app/backend/data
depends_on:
- ai_postgres
- litellm
networks:
- compose_network
labels:
- 'traefik.enable=${AI_TRAEFIK_ENABLED}'
# HTTP to HTTPS redirect
- 'traefik.http.middlewares.${AI_COMPOSE_PROJECT_NAME}-redirect-web-secure.redirectscheme.scheme=https'
- 'traefik.http.routers.${AI_COMPOSE_PROJECT_NAME}-web.middlewares=${AI_COMPOSE_PROJECT_NAME}-redirect-web-secure'
- 'traefik.http.routers.${AI_COMPOSE_PROJECT_NAME}-web.rule=Host(`${AI_TRAEFIK_HOST}`)'
- 'traefik.http.routers.${AI_COMPOSE_PROJECT_NAME}-web.entrypoints=web'
# HTTPS router
- 'traefik.http.routers.${AI_COMPOSE_PROJECT_NAME}-web-secure.rule=Host(`${AI_TRAEFIK_HOST}`)'
- 'traefik.http.routers.${AI_COMPOSE_PROJECT_NAME}-web-secure.tls.certresolver=resolver'
- 'traefik.http.routers.${AI_COMPOSE_PROJECT_NAME}-web-secure.entrypoints=web-secure'
- 'traefik.http.middlewares.${AI_COMPOSE_PROJECT_NAME}-web-secure-compress.compress=true'
- 'traefik.http.routers.${AI_COMPOSE_PROJECT_NAME}-web-secure.middlewares=${AI_COMPOSE_PROJECT_NAME}-web-secure-compress,security-headers@file'
# Service
- 'traefik.http.services.${AI_COMPOSE_PROJECT_NAME}-web-secure.loadbalancer.server.port=8080'
- 'traefik.docker.network=${NETWORK_NAME}'
# Watchtower
- 'com.centurylinklabs.watchtower.enable=${WATCHTOWER_LABEL_ENABLE}'
# LiteLLM - Proxy to convert Anthropic API to OpenAI-compatible format
litellm:
image: ghcr.io/berriai/litellm:main-latest
container_name: ${AI_COMPOSE_PROJECT_NAME}_litellm
restart: unless-stopped
environment:
TZ: ${TIMEZONE:-Europe/Berlin}
ANTHROPIC_API_KEY: ${ANTHROPIC_API_KEY}
DATABASE_URL: null
volumes:
- ./litellm-config.yaml:/app/litellm-config.yaml:ro
command: ["--config", "/app/litellm-config.yaml", "--host", "0.0.0.0", "--port", "4000", "--detailed_debug", "--drop_params"]
networks:
- compose_network
healthcheck:
disable: true
labels:
- 'traefik.enable=${AI_TRAEFIK_ENABLED}'
# HTTP to HTTPS redirect
- 'traefik.http.middlewares.${AI_COMPOSE_PROJECT_NAME}-litellm-redirect-web-secure.redirectscheme.scheme=https'
- 'traefik.http.routers.${AI_COMPOSE_PROJECT_NAME}-litellm-web.middlewares=${AI_COMPOSE_PROJECT_NAME}-litellm-redirect-web-secure'
- 'traefik.http.routers.${AI_COMPOSE_PROJECT_NAME}-litellm-web.rule=Host(`${AI_LITELLM_TRAEFIK_HOST}`)'
- 'traefik.http.routers.${AI_COMPOSE_PROJECT_NAME}-litellm-web.entrypoints=web'
# HTTPS router
- 'traefik.http.routers.${AI_COMPOSE_PROJECT_NAME}-litellm-web-secure.rule=Host(`${AI_LITELLM_TRAEFIK_HOST}`)'
- 'traefik.http.routers.${AI_COMPOSE_PROJECT_NAME}-litellm-web-secure.tls.certresolver=resolver'
- 'traefik.http.routers.${AI_COMPOSE_PROJECT_NAME}-litellm-web-secure.entrypoints=web-secure'
- 'traefik.http.middlewares.${AI_COMPOSE_PROJECT_NAME}-litellm-web-secure-compress.compress=true'
- 'traefik.http.middlewares.${AI_COMPOSE_PROJECT_NAME}-litellm-auth.basicauth.users=${AUTH_USERS}'
- 'traefik.http.routers.${AI_COMPOSE_PROJECT_NAME}-litellm-web-secure.middlewares=${AI_COMPOSE_PROJECT_NAME}-litellm-auth,${AI_COMPOSE_PROJECT_NAME}-litellm-web-secure-compress,security-headers@file'
# Service
- 'traefik.http.services.${AI_COMPOSE_PROJECT_NAME}-litellm-web-secure.loadbalancer.server.port=4000'
- 'traefik.docker.network=${NETWORK_NAME}'
# Watchtower
- 'com.centurylinklabs.watchtower.enable=${WATCHTOWER_LABEL_ENABLE}'
# Crawl4AI - Web scraping for LLMs (internal API, no public access)
crawl4ai:
image: ${AI_CRAWL4AI_IMAGE:-unclecode/crawl4ai:latest}
container_name: ${AI_COMPOSE_PROJECT_NAME}_crawl4ai
restart: unless-stopped
environment:
TZ: ${TIMEZONE:-Europe/Berlin}
# API configuration
PORT: ${AI_CRAWL4AI_PORT:-11235}
volumes:
- ai_crawl4ai_data:/app/.crawl4ai
networks:
- compose_network
labels:
# No Traefik exposure - internal only
- 'traefik.enable=false'
# Watchtower
- 'com.centurylinklabs.watchtower.enable=${WATCHTOWER_LABEL_ENABLE}'
volumes:
ai_postgres_data:
name: ${AI_COMPOSE_PROJECT_NAME}_postgres_data
ai_webui_data:
name: ${AI_COMPOSE_PROJECT_NAME}_webui_data
ai_crawl4ai_data:
name: ${AI_COMPOSE_PROJECT_NAME}_crawl4ai_data