As we approach the midpoint of 2025, the AI landscape continues to evolve at a dizzying pace. What worked six months ago might already be outdated, and new tools emerge almost weekly. Today (March 14th, 2025), I'm sharing my current AI stack — the collection of tools, services, and workflows that I've found most effective for my daily use.
This is very much a snapshot in time. The beauty (and challenge) of working with AI in 2025 is that everything is subject to ongoing change and evolution as the underlying technologies improve and new approaches emerge. Consider this less of a recommendation and more of a field report from someone deep in the AI trenches.
I've also published this stack as a GitHub repository for those who want to track changes over time or perhaps fork it as a starting point for documenting their own AI toolkit.
Quick Navigation
- Core AI Components
- Agentic & Orchestration Tools
- Docker Implementation
- APIs Beyond LLMs
- Final Thoughts
- Resource Directory
Core AI Components
Navigate this section: LLM APIs | LLM Frontend | Speech To Text | Vector Storage | Regular Storage
These are the foundational elements that support most of my AI-related activities.
LLM APIs
While self-hosting LLMs is increasingly viable, I still prefer using cloud APIs for most of my needs. This approach lets me avoid hardware stress and simplifies deployment while giving me access to state-of-the-art models.
My current favorites:
-
OpenRouter has become my go-to for consolidated billing and access to a wide variety of APIs. It lets me select models best suited for specific tasks without managing multiple accounts.
-
Google Flash 2.0 serves as my primary model due to its fast inference, large context window, and reasonable pricing. While not the best for complex reasoning, its versatility makes it suitable as the backing model for all my Assistant configurations.
-
Qwen's models, particularly Qwen coder, are my preference for non-agentic code generation and debugging. I find these models particularly underrated in the current landscape.
-
Cohere excels at instructional text-based tasks where clarity and precision matter.
-
OpenAI still has its place in my toolkit, especially Sonnet 3.7 for agented code generation, though I've found its recent performance somewhat inconsistent.
LLM Frontend
After testing numerous AI tool frontends, Open Web UI stands out as the most impressive for my needs. I've shared some of my configurations on the Open Web UI community platform.
One lesson learned: if you're planning to use these tools long-term, start with PostgreSQL rather than SQLite. While the container defaults to Chroma DB, you can configure it to use Milvus, Qdrant, or other vector database options.
My approach to self-hosting has evolved from experimentation to building for long-term stability, with careful component selection from the outset.
Speech To Text / ASR
Transitioning to speech-to-text has been transformative for my workflow! After unsatisfactory experiences a decade ago, Whisper has revolutionized reliability and made STT good enough for everyday use.
I use Whisper AI as a Chrome extension for speech-to-text and rely on it for many hours each day. For Android, the open source Futo Keyboard project shows promise, though it depends on local hardware capabilities.
While I recognize the use case for local processing, I generally prefer not to run speech-to-text or most AI models locally. On my Linux desktop, I use generative AI tools to create custom notepads that leverage Whisper via API.
Vector Storage
I'm currently developing a personal managed context data store for creating personalized AI experiences. This is a long-term project, and my approach will likely evolve significantly over time.
My current focus is on using multi-agent workflows to proactively generate contextual data. Some of my related projects include:
The project involves creating markdown files based on interviews detailing aspects of my life. I've also experimented with the inverse approach of putting non-contextual data through an LLM pipeline to isolate context data.
For vector storage itself, I avoid OpenAI assistants to prevent vendor lock-in and instead use Qdrant to decouple my personal context data from other parts of the project.
Regular Storage
Contrary to what some might expect, storing AI outputs robustly doesn't require specialized solutions; regular databases work perfectly well. MongoDB and PostgreSQL are my preferred databases, with PostgreSQL being especially beneficial as it can easily be extended with PGVector for vector capabilities when needed.
Agentic, Generative & Orchestration Tools
Navigate this section: Agents & Assistants | Other Generative AI | Workflows & Orchestration | AI IDEs & Computer Use
These tools extend the capabilities of my core components, enabling more complex workflows and creative applications.
Agents & Assistants
I've explored many AI agents and assistants, noting that many interesting projects lack well-developed frontends. You can explore some of my AI assistants in my AI Assistants Library.
I'm a strong advocate for simple system prompt-based agents and have open-sourced over 600 system prompts since discovering AI in early 2024. I currently use these in Open Web UI, sharing my library with that community.
While having 600+ assistants might seem excessive, it's quite manageable when each assistant is highly focused on a small, distinct task. For example, I have assistants for changing the persona of text, formalizing it, informalizing it, and other common writing tasks.
Other Generative AI
Beyond text generation, I use:
- Leonardo AI for text-to-image generation, appreciating its diversity of models and configurable parameters.
- Runway ML for creating animations from frames, though I haven't explored text-to-video as extensively yet.
Workflows & Orchestration
My main interest in AI systems lies in addressing the challenge of making this rapidly growing technology more effective through tool use, workflow management, and orchestration.
I use N8N to provision and orchestrate agents, experimenting with different stack combinations while prioritizing simplicity and fewer components. I also appreciate the pipelines and tools within Open Web UI that enable actions on external services.
Langflow provides a user-friendly interface for visually building complex workflows with language models, making it easier to prototype and experiment with different LLM configurations.
AI IDEs & Computer Use
I currently subscribe to Windsurf, valuing its integrated experience for agent-driven code generation, despite some recent performance issues. I also use Aider, especially for single-script projects where precise context specification is advantageous.
My daily driver is OpenSUSE Linux, which influences my choice of tools. I've found Open Interpreter impressive for running LLMs directly within the terminal and see significant potential in this project, though it requires careful provisioning for debugging and working directly on the computer.
Docker Implementation
My GitHub repository includes a docker-compose.yaml file that encapsulates my AI stack. This setup allows for easy deployment and management of the various components.
Key components include:
- OpenWebUI: My primary frontend for interacting with LLMs
- PostgreSQL: The main database for storing application data
- Qdrant: A vector database essential for semantic search and RAG applications
- Redis: Used for caching and performance optimization
- Langflow: Facilitates workflow management for language models
- Linkwarden: A bookmark and web content manager for research and reference
- N8N: My chosen workflow automation platform
- Unstructured: For extracting content from a variety of file formats
The implementation also includes monitoring (Glances) and backup (Duplicati) to ensure a robust and maintainable system.
APIs Beyond LLMs
I leverage specialized APIs alongside LLMs to enhance specific tasks:
- Tavily: This search API provides relevant, up-to-date information, making it ideal for RAG applications and ensuring LLMs have access to current knowledge.
- Sonar by Perplexity: Delivers powerful search capabilities with built-in summarization and information synthesis, particularly effective for research and gathering comprehensive information on specific topics.
Final Thoughts
This stack represents what works for me right now, but I expect it to continue evolving as new tools emerge and existing ones improve. The AI landscape of 2025 is incredibly dynamic, with new capabilities appearing almost weekly.
If you're building your own AI stack, I encourage you to experiment and find the combination of tools that best suits your specific needs and workflow. What works for me might not be ideal for you, and that's perfectly fine.
I'll continue updating my GitHub repository as my stack evolves, so feel free to check back periodically if you're interested in tracking changes over time.
What does your AI stack look like in 2025? I'd love to hear about the tools and approaches that are working well for you.
Resource Directory
Navigate this section: LLM APIs | Frontend Tools | Speech & Voice | Storage & Databases | Agents & Workflows | Media Tools | Development | Infrastructure | Search APIs | My Projects
LLM APIs & Models
Frontend & Interface Tools
Tool | Description | Link |
---|---|---|
Langflow | Visual interface for building LLM workflows | |
Open Interpreter | Terminal-based LLM interface | |
Open Web UI | Frontend for interacting with LLMs |
Speech & Voice Tools
Tool | Description | Link |
---|---|---|
Futo Keyboard | Open source Android keyboard with speech-to-text | |
Whisper AI | Speech-to-text model |
Storage & Databases
Tool | Description | Link |
---|---|---|
MongoDB | NoSQL database for AI outputs | |
PostgreSQL | Relational database with PGVector extension | |
Qdrant | Vector database for semantic search | |
Redis | In-memory data store for caching |
Agents & Workflows
Tool | Description | Link |
---|---|---|
Linkwarden | Bookmark and web content manager | |
N8N | Workflow automation platform | |
Unstructured | Tool for extracting content from various file formats |
Generative Media Tools
Tool | Description | Link |
---|---|---|
Leonardo AI | Text-to-image generation platform | |
Runway ML | Platform for text-to-video and animation |
Development Tools
Tool | Description | Link |
---|---|---|
Aider | AI coding assistant for precise context specification | |
OpenSUSE Linux | Linux distribution | |
Windsurf | AI-powered IDE |
Infrastructure & Deployment
Tool | Description | Link |
---|---|---|
Duplicati | Backup solution for AI stack | |
Glances | System monitoring tool |
Search & Knowledge APIs
Tool | Description | Link |
---|---|---|
Sonar by Perplexity | Search API with summarization | |
Tavily | Search API for RAG applications |
My Projects
Docker Compose (Model)
services:
# OpenWebUI and its dependencies
openwebui:
image: ghcr.io/open-webui/open-webui:latest
container_name: openwebui
hostname: openwebui
restart: unless-stopped
depends_on:
- postgres
- qdrant
environment:
- DATABASE_URL=postgresql://postgres:${POSTGRES_PASSWORD}@postgres:5432/openwebui
- QDRANT_URI=http://qdrant:${QDRANT_PORT:-6333}
- VECTOR_DB=${VECTOR_DB:-qdrant}
- QDRANT_API_KEY=${QDRANT_API_KEY:-$QDRANT_KEY}
- PORT=${OPENWEBUI_PORT:-8080}
# RAG Configuration
- RAG_EMBEDDING_ENGINE=${RAG_EMBEDDING_ENGINE:-openai}
- CHUNK_SIZE=${CHUNK_SIZE:-400}
- CHUNK_OVERLAP=${CHUNK_OVERLAP:-50}
- RAG_TOP_K=${RAG_TOP_K:-4}
- RAG_RELEVANCE_THRESHOLD=${RAG_RELEVANCE_THRESHOLD:-0.15}
- RAG_TEXT_SPLITTER=${RAG_TEXT_SPLITTER:-character}
- ENABLE_RAG_HYBRID_SEARCH=${ENABLE_RAG_HYBRID_SEARCH:-True}
- CONTENT_EXTRACTION_ENGINE=${CONTENT_EXTRACTION_ENGINE:-unstructured}
- UNSTRUCTURED_API_URL=http://unstructured:8000
- UNSTRUCTURED_API_KEY=${UNSTRUCTURED_API_KEY:-$UNSTRUCTURED_KEY}
- PDF_EXTRACT_IMAGES=${PDF_EXTRACT_IMAGES:-True}
- RAG_FILE_MAX_SIZE=${RAG_FILE_MAX_SIZE:-10}
- RAG_FILE_MAX_COUNT=${RAG_FILE_MAX_COUNT:-5}
# RAG OpenAI Configuration (commented out until values are provided)
# - RAG_OPENAI_API_KEY=${RAG_OPENAI_API_KEY}
# - RAG_OPENAI_API_BASE_URL=${RAG_OPENAI_API_BASE_URL}
# Enable Redis for caching
- REDIS_URL=redis://default:${REDIS_PASSWORD:-$REDIS_PASS}@redis:6379
# API Keys for various LLM providers
- OPENAI_API_KEY=${OPENAI_API_KEY:-$OPENAI_KEY}
- ANTHROPIC_API_KEY=${ANTHROPIC_KEY:-$ANTHROPIC_KEY}
- GOOGLE_API_KEY=${GOOGLE_API_KEY:-$GOOGLE_KEY}
- DEEPSEEK_API_KEY=${DEEPSEEK_API_KEY:-$DEEPSEEK_KEY}
- OPENROUTER_API_KEY=${OPENROUTER_API_KEY:-$OPENROUTER_KEY}
- MISTRAL_API_KEY=${MISTRAL_API_KEY:-$MISTRAL_KEY}
- PERPLEXITY_API_KEY=${PERPLEXITY_API_KEY:-$PERPLEXITY_KEY}
- COHERE_API_KEY=${COHERE_API_KEY:-$COHERE_KEY}
# Google Drive authentication
- GOOGLE_CLIENT_ID=$GOOGLE_CLIENT_ID
- GOOGLE_CLIENT_SECRET=$GOOGLE_CLIENT_SECRET
- GOOGLE_REDIRECT_URI=$GOOGLE_REDIRECT_URI
- GOOGLE_AUTH_ENABLED=true
- ENABLE_GOOGLE_DRIVE_INTEGRATION=true
# Performance optimization settings
- ENABLE_WEBSOCKET_SUPPORT=true
- WEBSOCKET_MANAGER=redis
- WEBSOCKET_REDIS_URL=redis://default:${REDIS_PASSWORD:-$REDIS_PASS}@redis:6379
- DATABASE_POOL_SIZE=20
- DATABASE_POOL_MAX_OVERFLOW=10
- DATABASE_POOL_TIMEOUT=30
- DATABASE_POOL_RECYCLE=1800
# Disable autocomplete
- ENABLE_AUTOCOMPLETE_GENERATION=false
# Admin credentials
- DEFAULT_USER_EMAIL=$DEFAULT_USER_EMAIL
- DEFAULT_USER_PASSWORD=$DEFAULT_USER_PASSWORD
- DEFAULT_USER_FIRST_NAME=$DEFAULT_USER_FIRST_NAME
- DEFAULT_USER_LAST_NAME=$DEFAULT_USER_LAST_NAME
- DEFAULT_USER_ROLE=admin
# CORS configuration
- CORS_ALLOW_ORIGIN=$CORS_ALLOW_ORIGIN
volumes:
- openwebui_data:/app/backend/data
networks:
- dsrholdingsai
healthcheck:
test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://localhost:8080/health"]
interval: 30s
timeout: 10s
retries: 3
start_period: 40s
postgres:
image: postgres:15-alpine
container_name: postgres
hostname: postgres
restart: unless-stopped
command: postgres -c shared_buffers=256MB -c work_mem=16MB -c maintenance_work_mem=128MB -c effective_cache_size=512MB -c max_connections=100
environment:
- POSTGRES_USER=postgres
- POSTGRES_PASSWORD=$POSTGRES_PASSWORD
- POSTGRES_DB=postgres
- POSTGRES_MULTIPLE_DATABASES=${LANGFLOW_DB:-langflow},${LINKWARDEN_DB:-linkwarden},${N8N_DB:-n8n}
volumes:
- postgres_data:/var/lib/postgresql/data
- ./scripts/postgres-init:/docker-entrypoint-initdb.d
networks:
- dsrholdingsai
healthcheck:
test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER:-postgres}"]
interval: 10s
timeout: 5s
retries: 5
start_period: 30s
qdrant:
image: qdrant/qdrant:latest
container_name: qdrant
hostname: qdrant
environment:
- QDRANT__SERVICE__API_KEY=${QDRANT_API_KEY:-$QDRANT_KEY}
- QDRANT__SERVICE__ENABLE_API_KEY_AUTHORIZATION=true
restart: unless-stopped
volumes:
- qdrant_data:/qdrant/storage
networks:
- dsrholdingsai
healthcheck:
test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://localhost:6333/readiness"]
interval: 30s
timeout: 10s
retries: 3
start_period: 30s
qdrant-dashboard-proxy:
image: nginx:alpine
container_name: qdrant-dashboard-proxy
hostname: qdrantdashboard
restart: unless-stopped
depends_on:
- qdrant
volumes:
- ./config/nginx/qdrant-dashboard.conf:/etc/nginx/conf.d/default.conf:ro
ports:
- "8090:80"
networks:
- dsrholdingsai
healthcheck:
test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://localhost:80/health"]
interval: 30s
timeout: 10s
retries: 3
start_period: 10s
redis:
image: redis:alpine
container_name: redis
hostname: redis
restart: unless-stopped
command: redis-server --appendonly yes --requirepass ${REDIS_PASSWORD:-$REDIS_PASS} --maxmemory 384mb --maxmemory-policy allkeys-lru
volumes:
- redis_data:/data
networks:
- dsrholdingsai
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 10s
timeout: 5s
retries: 3
start_period: 10s
langflow:
image: langflowai/langflow:latest
container_name: langflow
hostname: langflow
restart: unless-stopped
depends_on:
- postgres
- redis
environment:
- LANGFLOW_DATABASE_URL=postgresql://postgres:$POSTGRES_PASSWORD@postgres:5432/${LANGFLOW_DB:-langflow}
- LANGFLOW_REDIS_URL=redis://default:${REDIS_PASSWORD:-$REDIS_PASS}@redis:6379
- LANGFLOW_SUPERUSER=$LANGFLOW_SUPERUSER
- LANGFLOW_SUPERUSER_PASSWORD=$LANGFLOW_SUPERUSER_PASSWORD
- LANGFLOW_AUTO_LOGIN=False
- AUTH_ENABLED=true
# CORS configuration
- LANGFLOW_CORS_ORIGINS=$CORS_ALLOW_ORIGIN
# Unstructured integration
- LANGFLOW_UNSTRUCTURED_API_URL=http://unstructured:8000
- LANGFLOW_UNSTRUCTURED_API_KEY=${UNSTRUCTURED_API_KEY:-$UNSTRUCTURED_KEY}
volumes:
- langflow_data:/app/backend/langflow_data
ports:
- "${LANGFLOW_PORT:-7860}:7860"
networks:
- dsrholdingsai
healthcheck:
test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://localhost:7860/health"]
interval: 30s
timeout: 10s
retries: 3
linkwarden:
image: ghcr.io/linkwarden/linkwarden:latest
container_name: linkwarden
hostname: linkwarden
restart: unless-stopped
ports:
- "${LINKWARDEN_PORT:-3000}:3000"
environment:
- DATABASE_URL=postgresql://postgres:$POSTGRES_PASSWORD@postgres:5432/${LINKWARDEN_DB:-linkwarden}
- NEXTAUTH_SECRET=$NEXTAUTH_SECRET
- NEXTAUTH_URL=$NEXTAUTH_URL
- REDIS_URL=redis://default:${REDIS_PASSWORD:-$REDIS_PASS}@redis:6379
# CORS configuration
- NEXT_PUBLIC_CORS_ALLOWED_ORIGINS=$NEXT_PUBLIC_CORS_ALLOWED_ORIGINS
- NEXT_PUBLIC_BASE_URL=$NEXT_PUBLIC_BASE_URL
volumes:
- linkwarden_data:/data
networks:
- dsrholdingsai
depends_on:
- postgres
- redis
healthcheck:
test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://localhost:3000"]
interval: 30s
timeout: 10s
retries: 3
start_period: 40s
pgadmin:
image: dpage/pgadmin4:latest
container_name: pgadmin
hostname: pgadmin
restart: unless-stopped
ports:
- "${PGADMIN_PORT:-5050}:80"
environment:
- PGADMIN_DEFAULT_EMAIL=${PGADMIN_EMAIL:[email protected]}
- PGADMIN_DEFAULT_PASSWORD=$PGADMIN_PASSWORD
volumes:
- pgadmin_data:/var/lib/pgadmin
networks:
- dsrholdingsai
depends_on:
- postgres
healthcheck:
test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://localhost:80"]
interval: 30s
timeout: 10s
retries: 3
start_period: 30s
n8n:
image: n8nio/n8n:latest
container_name: n8n
hostname: n8n
restart: unless-stopped
ports:
- "${N8N_PORT:-5678}:5678"
environment:
- N8N_PORT=5678
- N8N_PROTOCOL=http
- N8N_HOST=${N8N_HOST:-n8n.example.com}
- DB_TYPE=postgresdb
- DB_POSTGRESDB_HOST=postgres
- DB_POSTGRESDB_PORT=5432
- DB_POSTGRESDB_DATABASE=${N8N_DB:-n8n}
- DB_POSTGRESDB_USER=postgres
- DB_POSTGRESDB_PASSWORD=$POSTGRES_PASSWORD
- N8N_EMAIL_MODE=smtp
- N8N_SMTP_HOST=${SMTP_HOST:-smtp.example.com}
- N8N_SMTP_PORT=${SMTP_PORT:-587}
- N8N_SMTP_USER=${SMTP_USER:[email protected]}
- N8N_SMTP_PASS=${SMTP_PASS:-$SMTP_PASS}
- N8N_SMTP_SENDER=${SMTP_SENDER:[email protected]}
- N8N_BASIC_AUTH_ACTIVE=false
- N8N_USER_MANAGEMENT_DISABLED=false
- N8N_DEFAULT_USER_EMAIL=${N8N_USER_EMAIL:[email protected]}
- N8N_DEFAULT_USER_PASSWORD=${N8N_PASSWORD:-$N8N_PASSWORD}
- N8N_DEFAULT_USER_FIRSTNAME=${N8N_USER_FIRSTNAME:-FirstName}
- N8N_DEFAULT_USER_LASTNAME=${N8N_USER_LASTNAME:-LastName}
- QUEUE_BULL_REDIS_HOST=redis
- QUEUE_BULL_REDIS_PORT=6379
- QUEUE_BULL_REDIS_PASSWORD=${REDIS_PASSWORD:-$REDIS_PASS}
- N8N_WEBHOOK_URL=${N8N_WEBHOOK_URL:-https://n8n.example.com}
- N8N_RUNNERS_ENABLED=${N8N_RUNNERS_ENABLED:-true}
# CORS configuration
- N8N_CORS_ALLOW_ORIGIN=$CORS_ALLOW_ORIGIN
volumes:
- n8n_data:/home/node/.n8n
networks:
- dsrholdingsai
depends_on:
- postgres
- redis
healthcheck:
test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://localhost:5678"]
interval: 30s
timeout: 10s
retries: 3
start_period: 30s
glances:
image: nicolargo/glances:latest
container_name: glances
hostname: glances
restart: unless-stopped
ports:
- "${GLANCES_PORT:-61208}:61208"
environment:
- GLANCES_OPT=-w
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
- /:/rootfs:ro
- /proc:/host/proc:ro
- /sys:/host/sys:ro
pid: host
networks:
- dsrholdingsai
healthcheck:
test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://localhost:61208"]
interval: 30s
timeout: 10s
retries: 3
start_period: 30s
backup:
image: linuxserver/duplicati:latest
container_name: backup
hostname: backup
restart: unless-stopped
environment:
- PUID=1000
- PGID=1000
- TZ=Europe/Jerusalem
# Backup configuration for incremental backups every 3rd day
- CLI_ARGS=--backup-name="AI Stack Incremental Backup" --dbpath=/config/AISTACK.sqlite --backup-retention-policy=30D:1W,1W:1M --run-script-before=/config/scripts/db-dump.sh --run-script-after=/config/scripts/backup-notification.sh
# Database-specific backup job
- DB_BACKUP_ARGS=--backup-name="Database Backup" --dbpath=/config/DB_BACKUP.sqlite --backup-retention-policy=7D:1D,30D:1W --include-folder=/source/db_dumps
# B2 Credentials
- B2_ACCOUNT_ID=${B2_APP_KEY_ID:-$B2_ACCOUNT_ID}
- B2_ACCOUNT_KEY=${B2_APP_KEY:-$B2_ACCOUNT_KEY}
- B2_BUCKET_NAME=${B2_BUCKET:-aistack}
# Default schedule: every 3rd day at 3 AM for full backup, daily at 1 AM for DB backup
- CRON_EXPRESSION=0 3 */3 * *
- DB_CRON_EXPRESSION=0 1 * * *
ports:
- "${BACKUP_PORT:-8200}:8200"
volumes:
- backup_config:/config
- /var/run/docker.sock:/var/run/docker.sock:ro
- ./scripts/backup:/config/scripts:ro
- db_dumps:/source/db_dumps
- openwebui_data:/source/openwebui_data:ro
- postgres_data:/source/postgres_data:ro
- qdrant_data:/source/qdrant_data:ro
- langflow_data:/source/langflow_data:ro
- linkwarden_data:/source/linkwarden_data:ro
- pgadmin_data:/source/pgadmin_data:ro
- n8n_data:/source/n8n_data:ro
networks:
- dsrholdingsai
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8200"]
interval: 30s
timeout: 10s
retries: 3
start_period: 30s
qdrant-backup:
image: linuxserver/duplicati:latest
container_name: qdrant-backup
hostname: qdrant-backup
restart: unless-stopped
environment:
- PUID=1000
- PGID=1000
- TZ=Europe/Jerusalem
# Qdrant-specific backup job
- CLI_ARGS=--backup-name="Qdrant Vector DB Backup" --dbpath=/config/QDRANT_BACKUP.sqlite --backup-retention-policy=30D:1W,1W:1M --run-script-before=/config/scripts/qdrant-backup.sh --run-script-after=/config/scripts/qdrant-backup-notification.sh
# B2 Credentials (same account but different bucket)
- B2_ACCOUNT_ID=${B2_APP_KEY_ID:-$B2_ACCOUNT_ID}
- B2_ACCOUNT_KEY=${B2_APP_KEY:-$B2_ACCOUNT_KEY}
- B2_BUCKET_NAME=qdrantbackups
# Schedule: daily at 2 AM for Qdrant backup
- CRON_EXPRESSION=0 2 * * *
ports:
- "${QDRANT_BACKUP_PORT:-8201}:8200"
volumes:
- qdrant_backup_config:/config
- /var/run/docker.sock:/var/run/docker.sock:ro
- ./scripts/backup:/config/scripts:ro
- qdrant_backups:/source/qdrant_backups
- qdrant_data:/source/qdrant_data:ro
networks:
- dsrholdingsai
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8200"]
interval: 30s
timeout: 10s
retries: 3
start_period: 30s
backup-dashboard:
image: nginx:alpine
container_name: backup-dashboard
hostname: backup-dashboard.example.com
restart: unless-stopped
volumes:
- ./config/nginx/backup-dashboard.conf:/etc/nginx/conf.d/default.conf:ro
- ./config/nginx/html:/usr/share/nginx/html:ro
ports:
- "${BACKUP_DASHBOARD_PORT:-8202}:80"
depends_on:
- backup
- qdrant-backup
networks:
- dsrholdingsai
healthcheck:
test: ["CMD", "wget", "-qO-", "http://localhost/health"]
interval: 30s
timeout: 10s
retries: 3
start_period: 30s
unstructured:
image: quay.io/unstructured-io/unstructured-api:latest
container_name: unstructured
hostname: unstructured
restart: unless-stopped
ports:
- "${UNSTRUCTURED_PORT:-8000}:8000"
environment:
- UNSTRUCTURED_API_KEY=${UNSTRUCTURED_API_KEY:-$UNSTRUCTURED_KEY}
- METRICS_ENABLED=true
- LOG_LEVEL=INFO
- MAX_DOCUMENT_SIZE=20971520
- CORS_ORIGINS=$CORS_ALLOW_ORIGIN
volumes:
- unstructured_data:/home/unstructured/.cache
networks:
- dsrholdingsai
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8000/health"]
interval: 30s
timeout: 10s
retries: 3
start_period: 60s
deploy:
resources:
limits:
cpus: '2.0'
memory: 4G
reservations:
cpus: '0.5'
memory: 2G
networks:
dsrholdingsai:
external: true
name: dsrholdingsai_network
volumes:
openwebui_data:
postgres_data:
qdrant_data:
langflow_data:
linkwarden_data:
pgadmin_data:
n8n_data:
redis_data:
backup_config:
qdrant_backup_config:
db_dumps:
driver: local
qdrant_backups:
driver: local
unstructured_data: