This repo was merged into system-admin-toj/containers/ and the copies
here kept drifting. Stale infrastructure config is not inert: agents.yml
here still carried OLLAMA_DEFAULT_MODEL=mistral-nemo:latest months after
the live stack moved to gemma4:e2b, and that setting is what caused the
2026-08-07 outage — mistral-nemo held 9,262 MiB of an 11,264 MiB card,
Whisper got 7 MiB, and Speaches returned CUDA OOM for hours while
reporting healthy. Anyone deploying from this directory would have
reproduced it exactly.
The files stay in this repo's history; README.md explains how to read one
back and points at the live location.
Two had no counterpart in system-admin-toj and were never deployed:
appwrite.yml, added in the most recent commit, and penpot.yml, whose
service is decommissioned. Both are recoverable from history if wanted;
neither should come back to this directory.
Left alone deliberately: an uncommitted CONTAINERS.md edit, which is
someone's unfinished work and would not have survived a delete.
Co-Authored-By: Claude <noreply@anthropic.com>
Self-contained stack with 25 containers: API server, console, realtime
WebSocket server, 10 workers, 3 schedulers, maintenance task, browser,
OpenRuntimes executor, plus internal MariaDB 10.11 and Redis 7.4.
Exposed on port 8093 via bundled Traefik. Watchtower disabled for
deliberate upgrades.
Also includes media.yml reformatting and Jellyfin GPU deploy block.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Mount secrets directory and GCS_CREDENTIALS_FILE env var to support
the new gcs_backup_executor in scheduler v1.2.0.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Merge three individual GPU service stacks into a unified models.yml.
All services share the RTX 2080 Ti and docker-dataplane network.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add full profiles for Stable Audio and TRELLIS services
- Update quick reference table, GPU services, and storage distribution
- Add new stacks to README port allocation and GPU section
- Update total services to 37 across 23 stacks
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Stable Audio Open: AI audio generation on port 11500 (~6GB VRAM)
- TRELLIS: 3D model generation on port 11510 (~6-8GB VRAM, low-VRAM fork)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Change keep-alive from infinite to 5m and max loaded models from 2 to 1,
freeing VRAM for Stable Audio, TRELLIS, and other GPU services.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Switch HA from bridge to host networking for better device discovery
- Add python-matter-server container for Matter protocol support
- Both services share host network for mDNS/IPv6 multicast
- Update NPM forward hostname to use IP address
- Add Matter Server setup instructions
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Fix frontend port mapping (8080, not 80)
- Fix healthcheck endpoints to use /readyz
- Add secret key to exporter service
- Disable email verification (no SMTP configured)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add self-hosted Penpot (Figma alternative) with:
- Docker stack using shared PostgreSQL and Redis infrastructure
- Authentik SSO integration (OIDC, password login disabled)
- Three services: frontend, backend, exporter
- Port 9001 for web UI, external via penpot.schweitz.net
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
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>
Adds HOST_WHITELIST env var to allow access from container name,
localhost, LAN IP, and hostname.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Replace USE_PGBOUNCER with CONN_MAX_AGE=0 and CONN_HEALTH_CHECKS
- Reduce web workers to 1 with 2 threads (homelab scale)
- Update worker config: CONCURRENCY=1, THREADS=2
- Remove redundant Redis config from worker service
Reduces overall PostgreSQL connection count.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Consolidates Jellyfin into a new media stack with full *arr automation:
- Sonarr (8989) - TV show management
- Radarr (7878) - Movie management
- Prowlarr (9696) - Indexer management
- SABnzbd (8880) - Usenet download client
- Jellyfin (8096) - Media streaming with GPU transcoding
Database: All *arr apps use PostgreSQL (postgres-shared) with media_user.
Databases created: sonarr, radarr, prowlarr
Also adds pg-connections.sh utility script for monitoring PostgreSQL connections.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Authentik 2025.10 no longer uses Redis for caching/sessions (now uses
Postgres). Updated stack to remove Redis config and renamed deprecated
WORKER__CONCURRENCY to WORKER__THREADS. Redis DB 0 now available.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Remove Organizr dashboard and Netdata monitoring:
- Delete stacks/organizr.yml and stacks/netdata.yml
- Delete organizr-widgets/ directory and npm forward-auth config
- Remove organizr database references from postgres-shared docs
Promote Tatlock UI as primary dashboard:
- Move from port 8092 to 9999 (Organizr's port)
- Enable external access at home.schweitz.net
- Update all documentation references
Update service counts: 26 containers across 20 stacks
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Disable debug mode for production
- Add Portainer, NPM, Postgres, Authentik API configurations
- Add SearXNG URL for search integration
- Use container name for Home Assistant URL
- Simplify healthcheck to /health endpoint
- Group environment variables by service
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add Flutter-based dashboard to replace Organizr:
- Port 8092, stateless static web app via nginx
- Resource limits (128M/32M), wget-based healthcheck
- Documented in CONTAINERS.md with full service profile
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add environment variables for:
- Central settings database (postgres-shared/system_settings)
- Scheduler service URL for task coordination
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Deploy AdGuard Home as network-wide DNS ad blocker with:
- Quad9 DoH upstream for encrypted, security-focused DNS
- Web UI on port 3053, DNS on 192.168.86.149:53
- Internal domain: dns.schweitz.internal
Includes setup guide (ADGUARD_SETUP.md) for completing wizard.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add paperless.yml stack (port 8091, documents.schweitz.net)
- Uses shared postgres (DB: paperless) and redis (DB 8)
- ClamAV installed on host for virus scanning (port 3310)
- Add Paperless integration to library-desk stack
- Update CONTAINERS.md with Paperless and ClamAV profiles
- Add Portainer and NPM API documentation to setup-new-host.md
- Update redis-shared.yml and postgres-shared.yml with Paperless refs
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add home-assistant.yml stack (port 8123, privileged mode for USB)
- External access via https://housekeeping.schweitz.net
- Health check using /manifest.json endpoint
- Update CONTAINERS.md with service profile
- Update stacks/README.md with port allocation
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add Redis DB column to All Services table in CONTAINERS.md
- Move Nextcloud from DB 3 to DB 7 to resolve conflict with Scheduler
- Split Tatlock Redis usage: DB 1 (memory), DB 6 (benchmarks)
- Add missing services to table: Wiki.js, Tatlock, Library Desk
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add HTTP API to Watchtower for CI/CD triggered updates
- Update custom container images to use git.schweitz.internal
- Add GITEA_TOKEN env var to scheduler for release cleanup task
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add healthcheck configurations to 13 stacks for Portainer status monitoring
- Remove Uptime Kuma service (replaced by Docker healthchecks)
- Clean up stale Heimdall references
- Update documentation and service counts
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- OpenAI-compatible API server with LLM agent orchestration
- Port 8000, connects to docker-dataplane network
- Integrates with ollama, searxng, redis-shared services
- Watchtower auto-update enabled
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Move library-desk service to git.schweitz.net/jpmschweitzer/library-desk
- Update stacks/library-desk.yml to use container image
- Add library-desk to External Repositories in CONTAINERS.md
- Remove source code (now in external repo)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Core-API service moved to git.schweitz.net/jpmschweitzer/core-api
- Source code removed from this repository
- Stack file updated to use container image from Gitea registry
- Documentation updated with external service reference
- Removed obsolete docs/services/core-api.md (docs now in core-api repo)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Scheduler service moved to git.schweitz.net/jpmschweitzer/scheduler
- Source code removed from this repository
- Stack file updated to use container image from Gitea registry
- Added Gitea Actions runner to gitea stack for CI/CD
- Documentation updated with external service reference
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- OLLAMA_NUM_PARALLEL=1: Process requests sequentially to avoid batch
overflow panics when multiple services call embeddings concurrently
- OLLAMA_KEEP_ALIVE=-1: Keep models loaded in VRAM indefinitely
- OLLAMA_MAX_LOADED_MODELS=2: Allow both mistral-nemo and nomic-embed-text
to stay loaded simultaneously
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Replace WIKIJS_API_KEY with WIKIJS_USERNAME/PASSWORD and add
WIKIJS_DB_PASSWORD for PostgreSQL LISTEN/NOTIFY connection.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Implements comprehensive service client layer for Library Desk API to support
Librarian AI agent with multi-tenant knowledge management across Neo4j, Qdrant,
Wiki.js, SearXNG, and Ollama.
## Service Clients (src/clients/)
- Neo4j async client with connection pooling and user-scoped labels
- Qdrant vector store with collection-per-user multi-tenancy
- Wiki.js GraphQL API client for page/dossier management
- SearXNG client for web search integration
- Ollama client for text embeddings (nomic-embed-text)
## Core Infrastructure (src/core/)
- Multi-tenancy helpers for user namespace management
- Wiki.js: path-based namespaces (/users/{user})
- Neo4j: user-specific labels (User_{User}_Document)
- Qdrant: collection per user (library_desk_{user})
- Dependency injection with FastAPI Depends and @lru_cache singletons
- Lifecycle management (startup/shutdown) for all service connections
## Background Jobs (src/jobs/)
- Redis-based job manager for long-running operations
- Job status tracking with 24-hour TTL
- Support for queued, processing, completed, failed states
## Configuration
- Updated config.py with Redis DB 4 for library-desk jobs
- Updated docker-compose.yml: REDIS_DB from 2 to 4
- Added pytest and pytest-asyncio to requirements.txt
## Testing
- Unit tests: 25/25 passed (multi-tenancy helpers)
- Integration tests: 12/12 passed (all services verified)
- Neo4j connection and CRUD operations
- Qdrant vector operations with 768-dim embeddings
- Wiki.js GraphQL queries
- SearXNG web search
- Job Manager with Redis
- Dependency injection lifecycle
- pytest.ini configuration with asyncio support
## Health Monitoring
- Real-time service health checks via /health endpoint
- Connection status for all 5 external services
- Graceful degradation for partial service availability
## Architecture
- Follows async/await pattern throughout
- Connection pooling for Neo4j (singleton driver)
- HTTP client lifecycle management (httpx)
- Multi-tenancy enforced at client layer
- Default user: jpmschweitzer
Files changed: 26 files
- 5 new service clients (~1500 lines)
- 2 core modules (~500 lines)
- 1 job manager (~350 lines)
- 3 test files with 37 test cases
- Updated main.py with lifecycle hooks
All services tested and operational. Ready for Phase 2 (routers/services).
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add hybrid APScheduler + PostgreSQL-based task scheduling system with minute-based execution and priority queue.
Core features:
- Minute-based scheduling with cron-like patterns (-1 = wildcard)
- Priority queue system (1-100, lower = higher priority)
- Concurrent execution (max 5 tasks simultaneously)
- Full REST API for task management (CRUD operations)
- Task execution tracking with audit trail
- API key authentication (Bearer token)
- Health checks and system statistics
Architecture:
- APScheduler runs every minute
- Queries PostgreSQL for tasks scheduled for current minute
- Executes tasks concurrently by priority
- Records execution history in database
Database schema:
- scheduled_tasks: Task definitions/templates
- task_executions: Individual execution records
Technical stack:
- FastAPI for REST API
- APScheduler for scheduling
- PostgreSQL for persistence
- Pydantic for configuration
Endpoints:
- POST/GET/PUT/DELETE /tasks - Task management
- POST /tasks/{name}/trigger - Manual execution
- GET /executions - Execution history
- GET /health - Health check
- GET /stats - System statistics
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- Fixed: Change `result.data` to `result.output` (correct PydanticAI API)
- Increased analysis_timeout from 3s to 10s (mistral-nemo needs more time)
**Status:** Steward now initializes correctly but there's a remaining issue
with the async generator merging logic in two_stage_agent.py causing
requests to hang. This needs further investigation.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>