mucgpt

MUCGPT Stack - Docker Compose

This directory contains the Docker Compose configuration for running the complete MUCGPT stack locally.

πŸ“š For complete project documentation, see the main README and development guide.

Quick Start

Prerequisites:

Steps:

  1. Copy and configure the config files:

    cp .env.example .env
    cp core.config.yaml.example core.config.yaml
    cp assistant.config.yaml.example assistant.config.yaml
    # Edit core.config.yaml with your LLM model settings
    # Edit assistant.config.yaml if you need non-default DB/LDAP settings
    # Edit .env for proxy/SSL settings (if needed)
    
  2. Start the stack:

    podman compose up -d
    
  3. Access the services:

Architecture Overview

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                          External Access                             β”‚
β”‚                         (localhost ports)                            β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
         β”‚                β”‚              β”‚              β”‚
    :8083 (Gateway)  :5432 (DB)    :5050 (pgAdmin) :8100 (Keycloak)
         β”‚                β”‚              β”‚              β”‚
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                       Internal Network                               β”‚
β”‚                                                                      β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”         β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”      β”‚
β”‚  β”‚   Gateway    │◄─────────    Authentication Layer         β”‚      β”‚
β”‚  β”‚ refarch-     β”‚         β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”‚      β”‚
β”‚  β”‚ gateway      β”‚         β”‚  β”‚ Keycloak β”‚  β”‚ init-       β”‚  β”‚      β”‚
β”‚  β”‚ :8080        β”‚         β”‚  β”‚ :8100    β”‚  β”‚ keycloak    β”‚  β”‚      β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”˜         β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β”‚      β”‚
β”‚         β”‚                 β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜      β”‚
β”‚         β”‚                                                           β”‚
β”‚    β”Œβ”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”‚
β”‚    β”‚    β”‚                     β”‚                  β”‚             β”‚   β”‚
β”‚    β–Ό    β–Ό                     β–Ό                  β–Ό             β–Ό   β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”      β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”β”‚
β”‚  β”‚ Frontend β”‚      β”‚  Application     β”‚   β”‚  Database  β”‚  β”‚ MCP  β”‚β”‚
β”‚  β”‚ :8080    β”‚      β”‚     Services     β”‚   β”‚   Layer    β”‚  β”‚Serverβ”‚β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜      β”‚                  β”‚   β”‚            β”‚  β””β”€β”€β”€β”€β”€β”€β”˜β”‚
β”‚                    β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”‚   β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β” β”‚  :8088  β”‚
β”‚                    β”‚  β”‚ core-      β”‚  β”‚   β”‚ β”‚Postgresβ”‚ β”‚         β”‚
β”‚                    β”‚  β”‚ service    β”‚  β”‚   β”‚ β”‚:5432   β”‚ β”‚         β”‚
β”‚                    β”‚  β”‚ :8000      β”‚  β”‚   β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚         β”‚
β”‚                    β”‚  β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”˜  β”‚   β”‚            β”‚         β”‚
β”‚                    β”‚         β”‚        β”‚   β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β” β”‚         β”‚
β”‚                    β”‚  β”Œβ”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”  β”‚   β”‚ β”‚pgAdmin β”‚ β”‚         β”‚
β”‚                    β”‚  β”‚ xberg -    β”‚  β”‚   β”‚ |:5050   β”‚ β”‚         β”‚
β”‚                    β”‚  β”‚ full :8000 β”‚  β”‚   β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚         β”‚
β”‚                    β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β”‚   β”‚            β”‚         β”‚
β”‚                    β”‚                  β”‚   β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β” β”‚         β”‚
β”‚                    β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”‚   β”‚ β”‚Valkey  β”‚ β”‚         β”‚
β”‚                    β”‚  β”‚ assistant- β”‚  β”‚   β”‚ β”‚:6379   β”‚ β”‚         β”‚
β”‚                    β”‚  β”‚ service    β”‚  β”‚   β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚         β”‚
β”‚                    β”‚  β”‚ :8084      β”‚  β”‚   β”‚            β”‚         β”‚
β”‚                    β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β”‚   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜         β”‚
β”‚                    β”‚                  β”‚                           β”‚
β”‚                    β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”‚                           β”‚
β”‚                    β”‚  β”‚ assistant- β”‚  β”‚                           β”‚
β”‚                    β”‚  β”‚ migrations β”‚  β”‚                           β”‚
β”‚                    β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β”‚                           β”‚
β”‚                    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜                           β”‚
β”‚                                                                    β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Services

Infrastructure Services

Service Port Description
postgres 5432 PostgreSQL 17.4 database
pg-admin 5050 Database administration UI
keycloak 8100 Identity and access management
valkey 6379 In-memory data store (Redis-compatible)
refarch-gateway 8083 API Gateway with OAuth2/OIDC
xberg-full 8086 Document extraction service

Application Services

Service Port (Internal) Port (External) Description
core-service 8000 39146 Core AI/LLM service backend
assistant-service 8084 39147 Assistant management service
assistant-migrations - - Database migration service (run-once)
frontend 8080 8081 Web UI

MCP Servers

Service Port Description
mcpdoc-server 8088 Model Context Protocol server for documentation

The mcpdoc-server image installs mcpdoc through the local mcpdoc-server/pyproject.toml project. Pin or override transitive dependencies there, for example when an upstream mcp release is incompatible with mcpdoc.

Docker Compose Files

Common Commands

Production Mode

# Start all services
podman compose up -d

# Stop all services
podman compose down

# View logs
podman compose logs -f [service-name]

# Rebuild specific service
podman compose up -d --build <service-name>

Development Mode

For local development with services running outside Docker:

# Start stack with development overrides
podman compose -f docker-compose.yml -f docker-compose.dev.yml up -d

See DEVELOPMENT.md for details on local development setup.

Network Flow

  1. External requests β†’ Gateway (:8083)
  2. Gateway routes by path:
    • /api/sso/** β†’ Keycloak
    • /api/backend/** β†’ Core service
    • /api/assistant/** β†’ Assistant service
    • /** β†’ Frontend
  3. Internal communication via internal network
  4. Database access shared by services

Configuration

The stack uses YAML configuration files as the primary configuration source, with environment variables available as overrides. Each service has its own config.yaml mounted into the container.

Configuration Files

File Mounted to Used by Purpose
core.config.yaml /app/config.yaml core-service Models, Langfuse prompts, MCP, Redis, SSO
assistant.config.yaml /app/config.yaml assistant-service, assistant-migrations Database, Redis, LDAP, SSO
.env env vars all services Proxies, SSL, infrastructure overrides

Quick Setup

  1. Copy the example files:

    cp .env.example .env
    cp core.config.yaml.example core.config.yaml
    cp assistant.config.yaml.example assistant.config.yaml
    
  2. Edit core.config.yaml – configure your LLM models and optional features:

    MODELS:
       - type: "OPENAI"
         llm_name: "gpt-4.1"
         endpoint: "https://your-endpoint.example.com/v1"
         api_key: "sk-..."
         model_info:
           auto_enrich_from_model_info_endpoint: true
           internal_task_model_strength: "strong"
    
       - type: "OPENAI"
         llm_name: "gpt-4.1-nano"
         endpoint: "https://your-endpoint.example.com/v1"
         api_key: "sk-..."
         model_info:
           auto_enrich_from_model_info_endpoint: true
           internal_task_model_strength: "weak"
    
     REDIS:
       HOST: "valkey"
       PORT: 6379
    
    LANGFUSE:
      HOST: "https://your-langfuse-host.example.com"
      PUBLIC_KEY: "pk-lf-..."
      SECRET_KEY: "sk-lf-..."
    
    MCP:
      SOURCES:
        "my-mcp-server":
           url: "http://mcpdoc-server:8088/sse"
           transport: "sse"
    

Internal Task Models

The core service supports an optional internal model hint for lightweight generation tasks.

Set this per model under MODELS[].model_info.internal_task_model_strength:

Example:

MODELS:
  - type: "OPENAI"
    llm_name: "gpt-4.1-mini"
    endpoint: "https://your-endpoint.example.com/v1"
    api_key: "sk-..."
    model_info:
      internal_task_model_strength: "strong"

  - type: "OPENAI"
    llm_name: "gpt-4.1-nano"
    endpoint: "https://your-endpoint.example.com/v1"
    api_key: "sk-..."
    model_info:
      internal_task_model_strength: "weak"

Selection behavior:

This setting is internal to the core service and is not exposed to the frontend config API.

Prompt Pool Configuration

The optional PROMPTS section in core.config.yaml maps core-service prompt names to Langfuse folders and labels. Configure a mapping only when the matching prompt exists in Langfuse. The full commented example is in core.config.yaml.example.

  1. Edit assistant.config.yaml – configure database and optional LDAP:

    DB:
      HOST: "postgres"
      PORT: 5432
      NAME: "postgres"
      USER: "admin"
      PASSWORD: "admin"
    
    REDIS:
      HOST: "valkey"
      PORT: 6379
    
    LDAP:
      ENABLED: false
    
  2. Edit .env for proxy/SSL settings (if needed).

  3. Start the stack:

    podman compose up -d
    

Environment Variable Overrides

Any YAML setting can be overridden with environment variables. The services use nested delimiters (__) to map to YAML sections:

Service Env Prefix Example
core-service MUCGPT_CORE_ MUCGPT_CORE_REDIS__HOST=valkey
assistant-service MUCGPT_ASSISTANT_ MUCGPT_ASSISTANT_DB__HOST=postgres
assistant-migrations MUCGPT_ASSISTANT_ (same as assistant-service)

Mapping rules:

Examples – set via .env or container environment::

# Override assistant database password (nested under DB section)
MUCGPT_ASSISTANT_DB__PASSWORD=my-secure-password

# Override core Redis host (nested under REDIS section)
MUCGPT_CORE_REDIS__HOST=my-redis-host

# Override core Langfuse secret key (nested under LANGFUSE section)
MUCGPT_CORE_LANGFUSE__SECRET_KEY=sk-lf-...

Configuration Priority

Settings are loaded in this order (highest priority wins):

  1. Constructor / init – used in tests
  2. Environment variables – including .env file, uses __ for nesting
  3. YAML config file – config.yaml mounted into each container

This means environment variables always override YAML values, which is useful for injecting secrets in CI/CD without storing them in config files.

Technical Details

Health Checks: All services implement health checks with readiness probes ensuring proper startup order.

Volumes: