# OfflinAI Server + Open WebUI: a private chat assistant for a small office.
#
# Single-machine variant (Free plan): both ports are published on 127.0.0.1 only, so only
# the computer running Docker can open them. See README.md and docs/recipes/open-webui.md.
#
#   1. docker compose up -d offlinai-server
#   2. open http://127.0.0.1:12436/console/ : set the password, download a model, create an API key
#   3. put the key in .env next to this file:  OAS_API_KEY=ofai_sk_...
#   4. docker compose up -d
#   5. open http://127.0.0.1:3000 and create the Open WebUI administrator account

name: oas-owui

services:
  offlinai-server:
    image: offlinai/offlinai-server:0.1.4
    # The image's own command plus --allow-host: Open WebUI reaches the server by its
    # service name, which the server accepts only when it is listed here.
    command: ["serve", "--network", "0.0.0.0:12443", "--allow-host", "offlinai-server"]
    ports:
      # Plain HTTP for this computer only. Keep 127.0.0.1 and the same number on both sides.
      - "127.0.0.1:12436:12436"
      # Serving the office network (Pro licence and up): uncomment to publish HTTPS.
      # - "12443:12443"
    volumes:
      - oas-data:/data
    restart: unless-stopped
    # GPU (NVIDIA, with the NVIDIA Container Toolkit / Docker Desktop's GPU support):
    # environment:
    #   OAE_BACKEND: vulkan
    #   NVIDIA_DRIVER_CAPABILITIES: compute,utility,graphics
    # deploy:
    #   resources:
    #     reservations:
    #       devices:
    #         - driver: nvidia
    #           count: 1
    #           capabilities: [gpu]

  open-webui:
    image: ghcr.io/open-webui/open-webui:v0.12.3
    depends_on:
      offlinai-server:
        condition: service_healthy
    ports:
      - "127.0.0.1:3000:8080"
    volumes:
      - open-webui-data:/app/backend/data
    environment:
      # Chat models come from OfflinAI Server's OpenAI-compatible API.
      ENABLE_OPENAI_API: "true"
      OPENAI_API_BASE_URL: "http://offlinai-server:12436/v1"
      OPENAI_API_KEY: "${OAS_API_KEY:-}"   # set in .env (step 3)
      # Open WebUI's other built-in model connection is not used.
      ENABLE_OLLAMA_API: "false"
      # Document Q&A: embeddings come from OfflinAI Server too (no model download by Open WebUI).
      RAG_EMBEDDING_ENGINE: "openai"
      RAG_OPENAI_API_BASE_URL: "http://offlinai-server:12436/v1"
      RAG_OPENAI_API_KEY: "${OAS_API_KEY:-}"
      RAG_EMBEDDING_MODEL: "${OAS_EMBEDDING_MODEL:-nomic-embed-text:latest}"
      # No update checks, no model downloads from the internet, no telemetry.
      OFFLINE_MODE: "true"
      ENABLE_VERSION_UPDATE_CHECK: "false"
      ANONYMIZED_TELEMETRY: "false"
      DO_NOT_TRACK: "true"
      SCARF_NO_ANALYTICS: "true"
      ENABLE_COMMUNITY_SHARING: "false"
      # Staff accounts: the first account is the administrator; later sign-ups wait for approval.
      DEFAULT_USER_ROLE: "pending"
      # The address people open. Change both when you serve the office network.
      WEBUI_URL: "http://127.0.0.1:3000"
      CORS_ALLOW_ORIGIN: "http://127.0.0.1:3000;http://localhost:3000"
      # Signs sign-in sessions. Set a long random value in .env so sessions survive an upgrade;
      # left empty, Open WebUI makes one itself and everyone signs in again after the container is replaced.
      WEBUI_SECRET_KEY: "${WEBUI_SECRET_KEY:-}"
    restart: unless-stopped

volumes:
  oas-data:
  open-webui-data:
