feat(stack): create unified agents stack with Tatlock and Webber
Consolidate Tatlock API into new agents stack and add Webber LLM agent orchestration service. Webber provides autonomous agent execution with tool use, authenticating via Tatlock API. Changes: - Add stacks/agents.yml with Tatlock (port 8000) and Webber (port 8086) - Remove stacks/tatlock.yml (merged into agents stack) - Document Webber service in CONTAINERS.md (Redis DB 9) - Add full Tatlock API documentation to CONTAINERS.md Config updates (pre-existing): - core-api: Enable OIDC, add host stats access, simplify model config - gitea: Migrate from dedicated DB to postgres-shared - media: Remove GPU reservation from Jellyfin Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,147 @@
|
||||
version: '3.8'
|
||||
|
||||
# Agents Stack - LLM Agent Services
|
||||
# Purpose: AI agent orchestration APIs (Tatlock + Webber)
|
||||
# Ports: 8000 (Tatlock), 8086 (Webber)
|
||||
# Network: docker-dataplane
|
||||
# Images: git.schweitz.internal/jpmschweitzer/tatlock, git.schweitz.internal/jpmschweitzer/webber
|
||||
|
||||
services:
|
||||
# ============================================
|
||||
# Tatlock - The Homelab Butler
|
||||
# OpenAI-compatible API with LLM agent orchestration
|
||||
# Port: 8000
|
||||
# ============================================
|
||||
tatlock:
|
||||
image: git.schweitz.internal/jpmschweitzer/tatlock:latest
|
||||
container_name: tatlock
|
||||
restart: unless-stopped
|
||||
|
||||
ports:
|
||||
- "8000:8000"
|
||||
|
||||
environment:
|
||||
- ENVIRONMENT=production
|
||||
- API_HOST=0.0.0.0
|
||||
- API_PORT=8000
|
||||
# Ollama (shared service)
|
||||
- OLLAMA_HOST=http://ollama:11434
|
||||
- OLLAMA_DEFAULT_MODEL=mistral-nemo:latest
|
||||
- OLLAMA_TIMEOUT=120
|
||||
# SearXNG (optional, shared service)
|
||||
- SEARXNG_HOST=http://searxng:8080
|
||||
- SEARXNG_TIMEOUT=30
|
||||
# Qdrant (vector database)
|
||||
- QDRANT_HOST=qdrant
|
||||
- QDRANT_PORT=6333
|
||||
# Redis (shared service)
|
||||
- REDIS_HOST=redis-shared
|
||||
- REDIS_PORT=6379
|
||||
- REDIS_MEMORY_DB=1
|
||||
- REDIS_BENCHMARK_DB=6
|
||||
- REDIS_TIMEOUT=5
|
||||
# Features
|
||||
- ENABLE_BENCHMARKS=true
|
||||
- CORS_ORIGINS=["*"]
|
||||
- PYTHONPATH=/app
|
||||
# Library Desk API
|
||||
- LIBRARY_DESK_HOST=http://library-desk:8089
|
||||
- LIBRARY_DESK_API_KEY=${LIBRARY_API_KEY}
|
||||
|
||||
volumes:
|
||||
- /home/jpmschweitzer/docker-data/tatlock/logs:/app/logs
|
||||
|
||||
networks:
|
||||
- docker-dataplane
|
||||
|
||||
deploy:
|
||||
resources:
|
||||
limits:
|
||||
cpus: '1.0'
|
||||
memory: 1G
|
||||
reservations:
|
||||
memory: 256M
|
||||
|
||||
labels:
|
||||
- "com.centurylinklabs.watchtower.enable=true"
|
||||
|
||||
healthcheck:
|
||||
test: ["CMD", "curl", "-f", "http://localhost:8000/health"]
|
||||
interval: 30s
|
||||
timeout: 10s
|
||||
retries: 3
|
||||
start_period: 30s
|
||||
|
||||
# ============================================
|
||||
# Webber - LLM Agent Orchestration API
|
||||
# Autonomous agent execution with tool use
|
||||
# Port: 8086
|
||||
# ============================================
|
||||
webber:
|
||||
image: git.schweitz.internal/jpmschweitzer/webber:latest
|
||||
container_name: webber
|
||||
restart: unless-stopped
|
||||
|
||||
ports:
|
||||
- "8086:8086"
|
||||
|
||||
environment:
|
||||
# App settings
|
||||
- DEBUG=false
|
||||
- LOG_LEVEL=INFO
|
||||
- PYTHONPATH=/app
|
||||
# Server config
|
||||
- HOST=0.0.0.0
|
||||
- PORT=8086
|
||||
# CORS
|
||||
- CORS_ORIGINS=["*"]
|
||||
- CORS_METHODS=["*"]
|
||||
- CORS_HEADERS=["*"]
|
||||
# Ollama (shared service) - LLM Models hot in VRAM
|
||||
- OLLAMA_URL=http://ollama:11434
|
||||
- OLLAMA_AGENT_MODEL=mistral-nemo:latest
|
||||
- OLLAMA_EMBED_MODEL=nomic-embed-text:latest
|
||||
# Auth - Tatlock API for user validation
|
||||
- TATLOCK_API_URL=http://tatlock:8000
|
||||
- TATLOCK_API_KEY=${WEBBER_TATLOCK_API_KEY}
|
||||
# Tool execution settings
|
||||
- TOOL_TIMEOUT_SECONDS=30
|
||||
- SANDBOX_ENABLED=true
|
||||
- ALLOWED_PATHS=/app/sandbox,/tmp
|
||||
# Session management
|
||||
- SESSION_TTL_HOURS=24
|
||||
- MAX_CONTEXT_TOKENS=8192
|
||||
# Redis (shared service)
|
||||
- REDIS_HOST=redis-shared
|
||||
- REDIS_PORT=6379
|
||||
- REDIS_DB=9
|
||||
|
||||
volumes:
|
||||
- /home/jpmschweitzer/docker-data/webber/logs:/app/logs
|
||||
- /home/jpmschweitzer/docker-data/webber/sandbox:/app/sandbox
|
||||
|
||||
networks:
|
||||
- docker-dataplane
|
||||
|
||||
deploy:
|
||||
resources:
|
||||
limits:
|
||||
cpus: '1.0'
|
||||
memory: 1G
|
||||
reservations:
|
||||
memory: 256M
|
||||
|
||||
labels:
|
||||
- "com.centurylinklabs.watchtower.enable=true"
|
||||
|
||||
healthcheck:
|
||||
test: ["CMD", "curl", "-f", "http://localhost:8086/health"]
|
||||
interval: 30s
|
||||
timeout: 10s
|
||||
retries: 3
|
||||
start_period: 30s
|
||||
|
||||
networks:
|
||||
docker-dataplane:
|
||||
external: true
|
||||
name: docker-dataplane
|
||||
+7
-21
@@ -20,6 +20,7 @@ services:
|
||||
# Application
|
||||
- APP_NAME=Core API
|
||||
- DEBUG=false
|
||||
- OIDC_ENABLED=true
|
||||
|
||||
# Server
|
||||
- HOST=0.0.0.0
|
||||
@@ -28,22 +29,6 @@ services:
|
||||
# Logging
|
||||
- LOG_LEVEL=INFO
|
||||
|
||||
# Model Configuration
|
||||
- DEFAULT_MODEL=gemma:7b
|
||||
- LIGHTWEIGHT_MODELS=gemma:2b,gemma:7b
|
||||
- HEAVY_MODELS=mistral:7b,gemma2:9b,mixtral:8x7b
|
||||
- CODE_MODELS=codestral:latest,codegemma:latest
|
||||
|
||||
# Model Aliases (OpenAI → Local)
|
||||
- ALIAS_GPT35=gemma:7b
|
||||
- ALIAS_GPT4=mistral:7b
|
||||
- ALIAS_GPT4_TURBO=mixtral:8x7b
|
||||
- ALIAS_GPT4_CODE=codestral:latest
|
||||
|
||||
# Agent Configuration
|
||||
# Set to "false" to make agent errors explicit (500 errors) instead of silent fallback.
|
||||
- AGENT_FALLBACK_ENABLED=false
|
||||
|
||||
# Portainer API
|
||||
- PORTAINER_URL=http://192.168.86.149:8001
|
||||
- PORTAINER_API_KEY=${PORTAINER_API_KEY}
|
||||
@@ -69,12 +54,16 @@ services:
|
||||
- HOMEASSISTANT_TOKEN=${HOMEASSISTANT_TOKEN}
|
||||
|
||||
# AI SYSTEM VARIABLES
|
||||
- OLLAMA_BASE_URL=http://192.168.86.149:11434
|
||||
- OLLAMA_TIMEOUT=300
|
||||
- SEARXNG_URL=http://192.168.86.149:8080
|
||||
- QDRANT_HOST=192.168.86.149
|
||||
- QDRANT_PORT=6333
|
||||
|
||||
# Python path
|
||||
- PYTHONPATH=/app
|
||||
|
||||
- PSUTIL_PROCFS_PATH=/host/proc
|
||||
- HOSTFS_ROOT=/hostfs
|
||||
|
||||
volumes:
|
||||
# Data volumes only - no source code
|
||||
- /home/jpmschweitzer/docker-data/core-api/logs:/app/logs
|
||||
@@ -83,9 +72,6 @@ services:
|
||||
- /proc:/host/proc:ro
|
||||
- /sys:/host/sys:ro
|
||||
- /:/hostfs:ro
|
||||
environment:
|
||||
- PSUTIL_PROCFS_PATH=/host/proc
|
||||
- HOSTFS_ROOT=/hostfs
|
||||
|
||||
deploy:
|
||||
resources:
|
||||
|
||||
+9
-45
@@ -1,33 +1,13 @@
|
||||
version: '3.8'
|
||||
|
||||
# Gitea - Self-Hosted Git Service with Database
|
||||
# Gitea - Self-Hosted Git Service
|
||||
# Application Layer
|
||||
# Ports: 3002 (HTTP), 2222 (SSH)
|
||||
# GPU: No
|
||||
# Storage: SSD (repositories, database)
|
||||
# Storage: SSD (repositories)
|
||||
# Database: postgres-shared (gitea database, gitea_user)
|
||||
|
||||
services:
|
||||
gitea-db:
|
||||
image: postgres:14-alpine
|
||||
container_name: gitea-db
|
||||
restart: unless-stopped
|
||||
volumes:
|
||||
# Database on SSD for performance
|
||||
- /home/jpmschweitzer/docker-data/gitea/db:/var/lib/postgresql/data
|
||||
environment:
|
||||
- POSTGRES_USER=gitea
|
||||
- POSTGRES_PASSWORD=gPdM7QV4gvotE9f9lGS4yj
|
||||
- POSTGRES_DB=gitea
|
||||
- TZ=Europe/Amsterdam
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "pg_isready -U gitea -d gitea"]
|
||||
interval: 30s
|
||||
timeout: 10s
|
||||
retries: 3
|
||||
start_period: 30s
|
||||
networks:
|
||||
- docker-dataplane
|
||||
|
||||
gitea:
|
||||
image: gitea/gitea:latest
|
||||
container_name: gitea
|
||||
@@ -44,10 +24,10 @@ services:
|
||||
- USER_UID=1000
|
||||
- USER_GID=1000
|
||||
- GITEA__database__DB_TYPE=postgres
|
||||
- GITEA__database__HOST=gitea-db:5432
|
||||
- GITEA__database__HOST=postgres-shared:5432
|
||||
- GITEA__database__NAME=gitea
|
||||
- GITEA__database__USER=gitea
|
||||
- GITEA__database__PASSWD=gPdM7QV4gvotE9f9lGS4yj
|
||||
- GITEA__database__USER=gitea_user
|
||||
- GITEA__database__PASSWD=cCav64d76NX1zdEEAbVOM9uvao14aY8HojjNdxsSpMM=
|
||||
- TZ=Europe/Amsterdam
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "curl -fSs http://git.schweitz.internal/api/healthz || exit 1"]
|
||||
@@ -55,8 +35,6 @@ services:
|
||||
timeout: 10s
|
||||
retries: 3
|
||||
start_period: 60s
|
||||
depends_on:
|
||||
- gitea-db
|
||||
networks:
|
||||
- docker-dataplane
|
||||
|
||||
@@ -89,24 +67,10 @@ networks:
|
||||
external: true
|
||||
name: docker-dataplane
|
||||
|
||||
# ⚠️ SECURITY WARNING:
|
||||
# Change POSTGRES_PASSWORD and GITEA__database__PASSWD before deploying!
|
||||
# Use a strong, unique password.
|
||||
# Database: Uses postgres-shared stack (gitea database, gitea_user)
|
||||
# Ensure postgres-shared is running before deploying this stack.
|
||||
#
|
||||
# After Deployment:
|
||||
# 1. Access http://localhost:3002
|
||||
# 2. First-time setup:
|
||||
# - Server domain: localhost:3002 or your domain
|
||||
# - SSH server domain: localhost
|
||||
# - SSH server port: 2222 (external)
|
||||
# - HTTP listen port: 3000 (internal)
|
||||
# - Application URL: http://localhost:3002 or https://git.schweitz.net (if using NPM)
|
||||
# - Database: PostgreSQL (pre-configured via environment variables)
|
||||
# - Create admin account (strong password!)
|
||||
# 3. Configure additional settings:
|
||||
# - Email settings (optional)
|
||||
# - Enable/disable user registration
|
||||
# - Configure webhooks and integrations
|
||||
# Access: http://localhost:3002 or https://git.schweitz.net (via NPM)
|
||||
#
|
||||
# SSH Git Clone Usage:
|
||||
# git clone ssh://git@localhost:2222/username/repo.git
|
||||
|
||||
@@ -38,13 +38,6 @@ services:
|
||||
timeout: 10s
|
||||
retries: 3
|
||||
start_period: 60s
|
||||
deploy:
|
||||
resources:
|
||||
reservations:
|
||||
devices:
|
||||
- driver: nvidia
|
||||
count: 1
|
||||
capabilities: [gpu, video, compute, utility]
|
||||
networks:
|
||||
- docker-dataplane
|
||||
|
||||
|
||||
@@ -1,73 +0,0 @@
|
||||
version: '3.8'
|
||||
|
||||
# Tatlock - The Homelab Butler
|
||||
# Purpose: OpenAI-compatible API server with LLM agent orchestration
|
||||
# Port: 8000 (API)
|
||||
# Network: docker-dataplane
|
||||
# Image: git.schweitz.internal/jpmschweitzer/tatlock (internal registry)
|
||||
|
||||
services:
|
||||
tatlock:
|
||||
image: git.schweitz.internal/jpmschweitzer/tatlock:latest
|
||||
container_name: tatlock
|
||||
restart: unless-stopped
|
||||
|
||||
ports:
|
||||
- "8000:8000"
|
||||
|
||||
environment:
|
||||
- ENVIRONMENT=production
|
||||
- API_HOST=0.0.0.0
|
||||
- API_PORT=8000
|
||||
# Ollama (shared service)
|
||||
- OLLAMA_HOST=http://ollama:11434
|
||||
- OLLAMA_DEFAULT_MODEL=mistral-nemo:latest
|
||||
- OLLAMA_TIMEOUT=120
|
||||
# SearXNG (optional, shared service)
|
||||
- SEARXNG_HOST=http://searxng:8080
|
||||
- SEARXNG_TIMEOUT=30
|
||||
# Qdrant (vector database)
|
||||
- QDRANT_HOST=qdrant
|
||||
- QDRANT_PORT=6333
|
||||
# Redis (shared service)
|
||||
- REDIS_HOST=redis-shared
|
||||
- REDIS_PORT=6379
|
||||
- REDIS_MEMORY_DB=1
|
||||
- REDIS_BENCHMARK_DB=6
|
||||
- REDIS_TIMEOUT=5
|
||||
# Features
|
||||
- ENABLE_BENCHMARKS=true
|
||||
- CORS_ORIGINS=["*"]
|
||||
- PYTHONPATH=/app
|
||||
# Library Desk API
|
||||
- LIBRARY_DESK_HOST=http://library-desk:8089
|
||||
- LIBRARY_DESK_API_KEY=${LIBRARY_API_KEY}
|
||||
|
||||
volumes:
|
||||
- /home/jpmschweitzer/docker-data/tatlock/logs:/app/logs
|
||||
|
||||
networks:
|
||||
- docker-dataplane
|
||||
|
||||
deploy:
|
||||
resources:
|
||||
limits:
|
||||
cpus: '1.0'
|
||||
memory: 1G
|
||||
reservations:
|
||||
memory: 256M
|
||||
|
||||
labels:
|
||||
- "com.centurylinklabs.watchtower.enable=true"
|
||||
|
||||
healthcheck:
|
||||
test: ["CMD", "curl", "-f", "http://localhost:8000/health"]
|
||||
interval: 30s
|
||||
timeout: 10s
|
||||
retries: 3
|
||||
start_period: 30s
|
||||
|
||||
networks:
|
||||
docker-dataplane:
|
||||
external: true
|
||||
name: docker-dataplane
|
||||
Reference in New Issue
Block a user