Remove extra docker-compose and .env.exmple files.
All checks were successful
ci/woodpecker/push/infra Pipeline was successful

This commit is contained in:
2026-02-16 22:08:02 -06:00
parent ca430d6fdf
commit 7c7ad59002
17 changed files with 77 additions and 2117 deletions

View File

@@ -1,66 +0,0 @@
# ==============================================
# Mosaic Stack Production Environment
# ==============================================
# Copy to .env and configure for production deployment
# ======================
# PostgreSQL Database
# ======================
# CRITICAL: Use a strong, unique password
POSTGRES_USER=mosaic
POSTGRES_PASSWORD=REPLACE_WITH_SECURE_PASSWORD
POSTGRES_DB=mosaic
POSTGRES_SHARED_BUFFERS=256MB
POSTGRES_EFFECTIVE_CACHE_SIZE=1GB
POSTGRES_MAX_CONNECTIONS=100
# ======================
# Valkey Cache
# ======================
VALKEY_MAXMEMORY=256mb
# ======================
# API Configuration
# ======================
API_PORT=3001
API_HOST=0.0.0.0
# ======================
# Web Configuration
# ======================
WEB_PORT=3000
NEXT_PUBLIC_API_URL=https://api.mosaicstack.dev
# ======================
# Authentication (Authentik OIDC)
# ======================
OIDC_ISSUER=https://auth.diversecanvas.com/application/o/mosaic-stack/
OIDC_CLIENT_ID=your-client-id
OIDC_CLIENT_SECRET=your-client-secret
OIDC_REDIRECT_URI=https://api.mosaicstack.dev/auth/callback/authentik
# ======================
# JWT Configuration
# ======================
# CRITICAL: Generate a random secret (openssl rand -base64 32)
JWT_SECRET=REPLACE_WITH_RANDOM_SECRET
JWT_EXPIRATION=24h
# ======================
# Traefik Integration
# ======================
# Set to true if using external Traefik
TRAEFIK_ENABLE=true
TRAEFIK_ENTRYPOINT=websecure
TRAEFIK_TLS_ENABLED=true
TRAEFIK_DOCKER_NETWORK=traefik-public
TRAEFIK_CERTRESOLVER=letsencrypt
# Domain configuration
MOSAIC_API_DOMAIN=api.mosaicstack.dev
MOSAIC_WEB_DOMAIN=app.mosaicstack.dev
# ======================
# Optional: Ollama
# ======================
# OLLAMA_ENDPOINT=http://ollama.diversecanvas.com:11434

View File

@@ -1,161 +0,0 @@
# ==============================================
# Mosaic Stack - Docker Swarm Configuration
# ==============================================
# Copy this file to .env for Docker Swarm deployment
# ======================
# Application Ports (Internal)
# ======================
API_PORT=3001
API_HOST=0.0.0.0
WEB_PORT=3000
# ======================
# Domain Configuration (Traefik)
# ======================
# These domains must be configured in your DNS or /etc/hosts
MOSAIC_API_DOMAIN=api.mosaicstack.dev
MOSAIC_WEB_DOMAIN=mosaic.mosaicstack.dev
MOSAIC_AUTH_DOMAIN=auth.mosaicstack.dev
# ======================
# Web Configuration
# ======================
# Use the Traefik domain for the API URL
NEXT_PUBLIC_APP_URL=http://mosaic.mosaicstack.dev
NEXT_PUBLIC_API_URL=http://api.mosaicstack.dev
# ======================
# PostgreSQL Database
# ======================
DATABASE_URL=postgresql://mosaic:REPLACE_WITH_SECURE_PASSWORD@postgres:5432/mosaic
POSTGRES_USER=mosaic
POSTGRES_PASSWORD=REPLACE_WITH_SECURE_PASSWORD
POSTGRES_DB=mosaic
POSTGRES_PORT=5432
# PostgreSQL Performance Tuning
POSTGRES_SHARED_BUFFERS=256MB
POSTGRES_EFFECTIVE_CACHE_SIZE=1GB
POSTGRES_MAX_CONNECTIONS=100
# ======================
# Valkey Cache
# ======================
VALKEY_URL=redis://valkey:6379
VALKEY_HOST=valkey
VALKEY_PORT=6379
VALKEY_MAXMEMORY=256mb
# Knowledge Module Cache Configuration
KNOWLEDGE_CACHE_ENABLED=true
KNOWLEDGE_CACHE_TTL=300
# ======================
# Authentication (Authentik OIDC)
# ======================
# NOTE: Authentik services are COMMENTED OUT in docker-compose.swarm.yml by default
# Uncomment those services if you want to run Authentik internally
# Otherwise, use external Authentik by configuring OIDC_* variables below
# External Authentik Configuration (default)
OIDC_ENABLED=true
OIDC_ISSUER=https://auth.example.com/application/o/mosaic-stack/
OIDC_CLIENT_ID=your-client-id-here
OIDC_CLIENT_SECRET=your-client-secret-here
OIDC_REDIRECT_URI=https://api.mosaicstack.dev/auth/callback/authentik
# Internal Authentik Configuration (only needed if uncommenting Authentik services)
# Authentik PostgreSQL Database
AUTHENTIK_POSTGRES_USER=authentik
AUTHENTIK_POSTGRES_PASSWORD=REPLACE_WITH_SECURE_PASSWORD
AUTHENTIK_POSTGRES_DB=authentik
# Authentik Server Configuration
AUTHENTIK_SECRET_KEY=REPLACE_WITH_RANDOM_SECRET_MINIMUM_50_CHARS
AUTHENTIK_ERROR_REPORTING=false
AUTHENTIK_BOOTSTRAP_PASSWORD=REPLACE_WITH_SECURE_PASSWORD
AUTHENTIK_BOOTSTRAP_EMAIL=admin@mosaicstack.dev
AUTHENTIK_COOKIE_DOMAIN=.mosaicstack.dev
# ======================
# JWT Configuration
# ======================
JWT_SECRET=REPLACE_WITH_RANDOM_SECRET_MINIMUM_32_CHARS
JWT_EXPIRATION=24h
# ======================
# Encryption (Credential Security)
# ======================
# Generate with: openssl rand -hex 32
ENCRYPTION_KEY=REPLACE_WITH_64_CHAR_HEX_STRING_GENERATE_WITH_OPENSSL_RAND_HEX_32
# ======================
# OpenBao Secrets Management
# ======================
OPENBAO_ADDR=http://openbao:8200
OPENBAO_PORT=8200
# For development only - remove in production
OPENBAO_DEV_ROOT_TOKEN_ID=root
# ======================
# Ollama (Optional AI Service)
# ======================
OLLAMA_ENDPOINT=http://ollama:11434
OLLAMA_PORT=11434
OLLAMA_EMBEDDING_MODEL=mxbai-embed-large
# Semantic Search Configuration
SEMANTIC_SEARCH_SIMILARITY_THRESHOLD=0.5
# ======================
# OpenAI API (Optional)
# ======================
# OPENAI_API_KEY=sk-...
# ======================
# Application Environment
# ======================
NODE_ENV=production
# ======================
# Gitea Integration (Coordinator)
# ======================
GITEA_URL=https://git.mosaicstack.dev
GITEA_BOT_USERNAME=mosaic
GITEA_BOT_TOKEN=REPLACE_WITH_COORDINATOR_BOT_API_TOKEN
GITEA_BOT_PASSWORD=REPLACE_WITH_COORDINATOR_BOT_PASSWORD
GITEA_REPO_OWNER=mosaic
GITEA_REPO_NAME=stack
GITEA_WEBHOOK_SECRET=REPLACE_WITH_RANDOM_WEBHOOK_SECRET
COORDINATOR_API_KEY=REPLACE_WITH_RANDOM_API_KEY_MINIMUM_32_CHARS
# ======================
# Coordinator Service
# ======================
ANTHROPIC_API_KEY=REPLACE_WITH_ANTHROPIC_API_KEY
COORDINATOR_POLL_INTERVAL=5.0
COORDINATOR_MAX_CONCURRENT_AGENTS=10
COORDINATOR_ENABLED=true
# ======================
# Rate Limiting
# ======================
RATE_LIMIT_TTL=60
RATE_LIMIT_GLOBAL_LIMIT=100
RATE_LIMIT_WEBHOOK_LIMIT=60
RATE_LIMIT_COORDINATOR_LIMIT=100
RATE_LIMIT_HEALTH_LIMIT=300
RATE_LIMIT_STORAGE=redis
# ======================
# Orchestrator Configuration
# ======================
ORCHESTRATOR_API_KEY=REPLACE_WITH_RANDOM_API_KEY_MINIMUM_32_CHARS
CLAUDE_API_KEY=REPLACE_WITH_CLAUDE_API_KEY
# ======================
# Logging & Debugging
# ======================
LOG_LEVEL=info
DEBUG=false

View File

@@ -1,95 +0,0 @@
# ==============================================
# OpenBao Standalone Deployment - Portainer Version
# ==============================================
#
# This file is optimized for Portainer deployment:
# - No env_file directive (define variables in Portainer's environment editor)
# - Port exposed on all interfaces (Portainer limitation)
# - All environment variables explicitly defined
#
# Usage in Portainer:
# 1. Stacks -> Add Stack
# 2. Name: mosaic-openbao
# 3. Paste this file content
# 4. Add environment variables in "Environment variables" section:
# - IMAGE_TAG=dev
# - OPENBAO_PORT=8200
# 5. Deploy
#
# SECURITY NOTE: Port 8200 will be exposed on 0.0.0.0 (all interfaces)
# Use firewall rules to restrict access if needed.
# ==============================================
services:
# ======================
# OpenBao Secrets Vault
# ======================
openbao:
image: git.mosaicstack.dev/mosaic/stack-openbao:${IMAGE_TAG:-dev}
container_name: mosaic-openbao
entrypoint: ["dumb-init", "--"]
command: ["bao", "server", "-config=/openbao/config/config.hcl"]
environment:
OPENBAO_ADDR: http://0.0.0.0:8200
ports:
- "${OPENBAO_PORT:-8200}:8200"
volumes:
- openbao_data:/openbao/data
- openbao_logs:/openbao/logs
- openbao_init:/openbao/init
cap_add:
- IPC_LOCK
healthcheck:
test:
[
"CMD-SHELL",
"wget --spider --quiet 'http://localhost:8200/v1/sys/health?standbyok=true&uninitcode=200&sealedcode=200'",
]
interval: 10s
timeout: 5s
retries: 5
start_period: 30s
restart: unless-stopped
networks:
- mosaic_internal
# ======================
# OpenBao Init Sidecar
# ======================
# Auto-initializes and unseals OpenBao on first run
openbao-init:
image: git.mosaicstack.dev/mosaic/stack-openbao:${IMAGE_TAG:-dev}
container_name: mosaic-openbao-init
command: /openbao/init.sh
environment:
OPENBAO_ADDR: http://openbao:8200
volumes:
- openbao_init:/openbao/init
depends_on:
- openbao
restart: "no"
networks:
- mosaic_internal
# ======================
# Volumes
# ======================
volumes:
openbao_data:
name: mosaic-openbao-data
driver: local
openbao_logs:
name: mosaic-openbao-logs
driver: local
openbao_init:
name: mosaic-openbao-init
driver: local
# ======================
# Networks
# ======================
# Connect to the swarm stack's internal network
networks:
mosaic_internal:
external: true
name: mosaic_internal

View File

@@ -1,180 +0,0 @@
# Production Docker Compose - Uses pre-built images from Gitea Packages
#
# Prerequisites:
# - Images built and pushed to git.mosaicstack.dev/mosaic/*
# - .env file configured with production values
#
# Usage:
# docker compose -f docker-compose.prod.yml up -d
#
# For Portainer:
# - Stack → Add Stack → Repository
# - Compose file: docker-compose.prod.yml
services:
# ======================
# PostgreSQL Database
# ======================
postgres:
image: git.mosaicstack.dev/mosaic/stack-postgres:${IMAGE_TAG:-latest}
container_name: mosaic-postgres
restart: unless-stopped
environment:
POSTGRES_USER: ${POSTGRES_USER:-mosaic}
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
POSTGRES_DB: ${POSTGRES_DB:-mosaic}
POSTGRES_SHARED_BUFFERS: ${POSTGRES_SHARED_BUFFERS:-256MB}
POSTGRES_EFFECTIVE_CACHE_SIZE: ${POSTGRES_EFFECTIVE_CACHE_SIZE:-1GB}
POSTGRES_MAX_CONNECTIONS: ${POSTGRES_MAX_CONNECTIONS:-100}
volumes:
- postgres_data:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER:-mosaic} -d ${POSTGRES_DB:-mosaic}"]
interval: 10s
timeout: 5s
retries: 5
start_period: 30s
networks:
- mosaic-internal
labels:
- "com.mosaic.service=database"
- "com.mosaic.description=PostgreSQL 17 with pgvector"
# ======================
# Valkey Cache
# ======================
valkey:
image: valkey/valkey:8-alpine
container_name: mosaic-valkey
restart: unless-stopped
command:
- valkey-server
- --maxmemory ${VALKEY_MAXMEMORY:-256mb}
- --maxmemory-policy noeviction
- --appendonly yes
volumes:
- valkey_data:/data
healthcheck:
test: ["CMD", "valkey-cli", "ping"]
interval: 10s
timeout: 5s
retries: 5
start_period: 10s
networks:
- mosaic-internal
labels:
- "com.mosaic.service=cache"
- "com.mosaic.description=Valkey Redis-compatible cache"
# ======================
# Mosaic API
# ======================
api:
image: git.mosaicstack.dev/mosaic/stack-api:${IMAGE_TAG:-latest}
container_name: mosaic-api
restart: unless-stopped
environment:
NODE_ENV: production
PORT: ${API_PORT:-3001}
API_HOST: ${API_HOST:-0.0.0.0}
DATABASE_URL: postgresql://${POSTGRES_USER:-mosaic}:${POSTGRES_PASSWORD}@postgres:5432/${POSTGRES_DB:-mosaic}
VALKEY_URL: redis://valkey:6379
OIDC_ISSUER: ${OIDC_ISSUER}
OIDC_CLIENT_ID: ${OIDC_CLIENT_ID}
OIDC_CLIENT_SECRET: ${OIDC_CLIENT_SECRET}
OIDC_REDIRECT_URI: ${OIDC_REDIRECT_URI}
JWT_SECRET: ${JWT_SECRET}
JWT_EXPIRATION: ${JWT_EXPIRATION:-24h}
BETTER_AUTH_SECRET: ${BETTER_AUTH_SECRET}
OLLAMA_ENDPOINT: ${OLLAMA_ENDPOINT:-http://ollama:11434}
ports:
- "${API_PORT:-3001}:${API_PORT:-3001}"
depends_on:
postgres:
condition: service_healthy
valkey:
condition: service_healthy
healthcheck:
test:
[
"CMD-SHELL",
'node -e "require(''http'').get(''http://localhost:${API_PORT:-3001}/health'', (r) => {process.exit(r.statusCode === 200 ? 0 : 1)})"',
]
interval: 30s
timeout: 10s
retries: 3
start_period: 40s
networks:
- mosaic-internal
- mosaic-public
labels:
- "com.mosaic.service=api"
- "com.mosaic.description=Mosaic NestJS API"
- "traefik.enable=${TRAEFIK_ENABLE:-false}"
- "traefik.http.routers.mosaic-api.rule=Host(`${MOSAIC_API_DOMAIN:-api.mosaicstack.dev}`)"
- "traefik.http.routers.mosaic-api.entrypoints=${TRAEFIK_ENTRYPOINT:-websecure}"
- "traefik.http.routers.mosaic-api.tls=${TRAEFIK_TLS_ENABLED:-true}"
- "traefik.http.services.mosaic-api.loadbalancer.server.port=${API_PORT:-3001}"
- "traefik.docker.network=${TRAEFIK_DOCKER_NETWORK:-mosaic-public}"
- "traefik.http.routers.mosaic-api.tls.certresolver=${TRAEFIK_CERTRESOLVER:-}"
# ======================
# Mosaic Web
# ======================
web:
image: git.mosaicstack.dev/mosaic/stack-web:${IMAGE_TAG:-latest}
container_name: mosaic-web
restart: unless-stopped
environment:
NODE_ENV: production
PORT: ${WEB_PORT:-3000}
NEXT_PUBLIC_API_URL: ${NEXT_PUBLIC_API_URL:-https://api.mosaicstack.dev}
ports:
- "${WEB_PORT:-3000}:${WEB_PORT:-3000}"
depends_on:
api:
condition: service_healthy
healthcheck:
test:
[
"CMD-SHELL",
'node -e "require(''http'').get(''http://localhost:${WEB_PORT:-3000}'', (r) => {process.exit(r.statusCode === 200 ? 0 : 1)})"',
]
interval: 30s
timeout: 10s
retries: 3
start_period: 40s
networks:
- mosaic-public
labels:
- "com.mosaic.service=web"
- "com.mosaic.description=Mosaic Next.js Web App"
- "traefik.enable=${TRAEFIK_ENABLE:-false}"
- "traefik.http.routers.mosaic-web.rule=Host(`${MOSAIC_WEB_DOMAIN:-app.mosaicstack.dev}`)"
- "traefik.http.routers.mosaic-web.entrypoints=${TRAEFIK_ENTRYPOINT:-websecure}"
- "traefik.http.routers.mosaic-web.tls=${TRAEFIK_TLS_ENABLED:-true}"
- "traefik.http.services.mosaic-web.loadbalancer.server.port=${WEB_PORT:-3000}"
- "traefik.docker.network=${TRAEFIK_DOCKER_NETWORK:-mosaic-public}"
- "traefik.http.routers.mosaic-web.tls.certresolver=${TRAEFIK_CERTRESOLVER:-}"
# ======================
# Volumes
# ======================
volumes:
postgres_data:
name: mosaic-postgres-data
driver: local
valkey_data:
name: mosaic-valkey-data
driver: local
# ======================
# Networks
# ======================
networks:
mosaic-internal:
name: mosaic-internal
driver: bridge
mosaic-public:
name: mosaic-public
driver: bridge

View File

@@ -1,113 +0,0 @@
# ==============================================
# Speech Services - Docker Compose Dev Overlay
# ==============================================
#
# Adds STT and TTS services for local development.
#
# Usage:
# Basic (STT + default TTS):
# docker compose -f docker-compose.yml -f docker-compose.speech.yml up -d
#
# With premium TTS (requires GPU):
# docker compose -f docker-compose.yml -f docker-compose.speech.yml --profile premium-tts up -d
#
# Or use Makefile targets:
# make speech-up # Basic speech services
# make speech-down # Stop speech services
# make speech-logs # View speech service logs
# ==============================================
services:
# ======================
# Speaches (STT + basic TTS)
# ======================
speaches:
image: ghcr.io/speaches-ai/speaches:latest
container_name: mosaic-speaches
restart: unless-stopped
environment:
WHISPER__MODEL: ${SPEACHES_WHISPER_MODEL:-Systran/faster-whisper-large-v3-turbo}
ports:
- "${SPEACHES_PORT:-8090}:8000"
volumes:
- speaches_models:/root/.cache/huggingface
healthcheck:
test: ["CMD-SHELL", "curl -f http://localhost:8000/health || exit 1"]
interval: 30s
timeout: 10s
retries: 5
start_period: 120s
networks:
- mosaic-internal
labels:
- "com.mosaic.service=speech-stt"
- "com.mosaic.description=Speaches STT (Whisper) and basic TTS"
# ======================
# Kokoro TTS (Default TTS)
# ======================
kokoro-tts:
image: ghcr.io/remsky/kokoro-fastapi:latest-cpu
container_name: mosaic-kokoro-tts
restart: unless-stopped
ports:
- "${KOKORO_TTS_PORT:-8880}:8880"
healthcheck:
test: ["CMD-SHELL", "curl -f http://localhost:8880/health || exit 1"]
interval: 30s
timeout: 10s
retries: 5
start_period: 120s
networks:
- mosaic-internal
labels:
- "com.mosaic.service=speech-tts"
- "com.mosaic.description=Kokoro FastAPI TTS engine"
# ======================
# Chatterbox TTS (Premium TTS - Optional)
# ======================
# Only starts with: --profile premium-tts
# Requires NVIDIA GPU with docker nvidia runtime
chatterbox-tts:
image: devnen/chatterbox-tts-server:latest
container_name: mosaic-chatterbox-tts
restart: unless-stopped
ports:
- "${CHATTERBOX_TTS_PORT:-8881}:8000"
profiles:
- premium-tts
deploy:
resources:
reservations:
devices:
- driver: nvidia
count: 1
capabilities: [gpu]
healthcheck:
test: ["CMD-SHELL", "curl -f http://localhost:8000/health || exit 1"]
interval: 30s
timeout: 10s
retries: 5
start_period: 180s
networks:
- mosaic-internal
labels:
- "com.mosaic.service=speech-tts-premium"
- "com.mosaic.description=Chatterbox premium TTS with voice cloning (GPU)"
# ======================
# Volumes
# ======================
volumes:
speaches_models:
name: mosaic-speaches-models
driver: local
# ======================
# Networks
# ======================
networks:
mosaic-internal:
external: true
name: mosaic-internal

View File

@@ -1,459 +0,0 @@
# ==============================================
# Mosaic Stack - Docker Swarm Deployment
# ==============================================
#
# IMPORTANT: Docker Swarm does NOT support docker-compose profiles
# To disable services (e.g., for external alternatives), manually comment them out
#
# Current Configuration:
# - PostgreSQL: ENABLED (internal)
# - Valkey: ENABLED (internal)
# - Coordinator: ENABLED (internal)
# - OpenBao: DISABLED (must use standalone - see docker-compose.openbao.yml)
# - Authentik: DISABLED (commented out - using external OIDC)
# - Ollama: DISABLED (commented out - using external Ollama)
#
# For detailed deployment instructions, see:
# docs/SWARM-DEPLOYMENT.md
#
# Quick Start:
# 1. cp .env.swarm.example .env
# 2. nano .env # Configure environment
# 3. ./scripts/deploy-swarm.sh mosaic
# 4. Initialize OpenBao manually (see docs/SWARM-DEPLOYMENT.md)
#
# ==============================================
services:
# ======================
# PostgreSQL Database
# ======================
postgres:
image: git.mosaicstack.dev/mosaic/stack-postgres:${IMAGE_TAG:-latest}
env_file: .env
environment:
POSTGRES_USER: ${POSTGRES_USER:-mosaic}
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-mosaic_dev_password}
POSTGRES_DB: ${POSTGRES_DB:-mosaic}
POSTGRES_SHARED_BUFFERS: ${POSTGRES_SHARED_BUFFERS:-256MB}
POSTGRES_EFFECTIVE_CACHE_SIZE: ${POSTGRES_EFFECTIVE_CACHE_SIZE:-1GB}
POSTGRES_MAX_CONNECTIONS: ${POSTGRES_MAX_CONNECTIONS:-100}
volumes:
- postgres_data:/var/lib/postgresql/data
# Note: init-scripts bind mount removed for Portainer compatibility
# Init scripts are baked into the postgres image at build time
healthcheck:
test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER:-mosaic} -d ${POSTGRES_DB:-mosaic}"]
interval: 10s
timeout: 5s
retries: 5
start_period: 30s
networks:
- internal
deploy:
restart_policy:
condition: on-failure
# ======================
# Valkey Cache
# ======================
valkey:
image: valkey/valkey:8-alpine
env_file: .env
command:
- valkey-server
- --maxmemory ${VALKEY_MAXMEMORY:-256mb}
- --maxmemory-policy noeviction
- --appendonly yes
volumes:
- valkey_data:/data
healthcheck:
test: ["CMD", "valkey-cli", "ping"]
interval: 10s
timeout: 5s
retries: 5
start_period: 10s
networks:
- internal
deploy:
restart_policy:
condition: on-failure
# ======================
# OpenBao Secrets Vault
# ======================
openbao:
image: git.mosaicstack.dev/mosaic/stack-openbao:${IMAGE_TAG:-latest}
entrypoint: ["dumb-init", "--"]
command: ["bao", "server", "-config=/openbao/config/config.hcl"]
env_file: .env
environment:
OPENBAO_ADDR: http://0.0.0.0:8200
volumes:
- openbao_data:/openbao/data
- openbao_logs:/openbao/logs
- openbao_init:/openbao/init
cap_add:
- IPC_LOCK
healthcheck:
test:
[
"CMD-SHELL",
"wget --spider --quiet 'http://localhost:8200/v1/sys/health?standbyok=true&uninitcode=200&sealedcode=200'",
]
interval: 10s
timeout: 5s
retries: 5
start_period: 30s
networks:
- internal
deploy:
restart_policy:
condition: on-failure
# ======================
# OpenBao Init Sidecar
# ======================
# Auto-initializes and unseals OpenBao on first run.
# The init script has built-in retry logic (waits for OpenBao API).
openbao-init:
image: git.mosaicstack.dev/mosaic/stack-openbao:${IMAGE_TAG:-latest}
command: /openbao/init.sh
env_file: .env
environment:
VAULT_ADDR: http://openbao:8200
volumes:
- openbao_init:/openbao/init
networks:
- internal
deploy:
restart_policy:
condition: on-failure
max_attempts: 5
delay: 10s
# ======================
# Authentik - COMMENTED OUT (Using External Authentik)
# ======================
# Uncomment these services if you want to run Authentik internally
# For external Authentik, configure OIDC_ISSUER, OIDC_CLIENT_ID, OIDC_CLIENT_SECRET in .env
#
# authentik-postgres:
# image: postgres:17.7-alpine3.22
# env_file: .env
# environment:
# POSTGRES_USER: ${AUTHENTIK_POSTGRES_USER:-authentik}
# POSTGRES_PASSWORD: ${AUTHENTIK_POSTGRES_PASSWORD:-authentik_password}
# POSTGRES_DB: ${AUTHENTIK_POSTGRES_DB:-authentik}
# volumes:
# - authentik_postgres_data:/var/lib/postgresql/data
# healthcheck:
# test: ["CMD-SHELL", "pg_isready -U ${AUTHENTIK_POSTGRES_USER:-authentik}"]
# interval: 10s
# timeout: 5s
# retries: 5
# start_period: 20s
# networks:
# - internal
# deploy:
# restart_policy:
# condition: on-failure
#
# authentik-redis:
# image: valkey/valkey:8-alpine
# env_file: .env
# command: valkey-server --save 60 1 --loglevel warning
# volumes:
# - authentik_redis_data:/data
# healthcheck:
# test: ["CMD", "valkey-cli", "ping"]
# interval: 10s
# timeout: 5s
# retries: 5
# start_period: 10s
# networks:
# - internal
# deploy:
# restart_policy:
# condition: on-failure
#
# authentik-server:
# image: ghcr.io/goauthentik/server:2024.12.1
# env_file: .env
# command: server
# environment:
# AUTHENTIK_SECRET_KEY: ${AUTHENTIK_SECRET_KEY:-change-this-to-a-random-secret}
# AUTHENTIK_ERROR_REPORTING__ENABLED: ${AUTHENTIK_ERROR_REPORTING:-false}
# AUTHENTIK_POSTGRESQL__HOST: authentik-postgres
# AUTHENTIK_POSTGRESQL__PORT: 5432
# AUTHENTIK_POSTGRESQL__NAME: ${AUTHENTIK_POSTGRES_DB:-authentik}
# AUTHENTIK_POSTGRESQL__USER: ${AUTHENTIK_POSTGRES_USER:-authentik}
# AUTHENTIK_POSTGRESQL__PASSWORD: ${AUTHENTIK_POSTGRES_PASSWORD:-authentik_password}
# AUTHENTIK_REDIS__HOST: authentik-redis
# AUTHENTIK_REDIS__PORT: 6379
# AUTHENTIK_BOOTSTRAP_PASSWORD: ${AUTHENTIK_BOOTSTRAP_PASSWORD:-admin}
# AUTHENTIK_BOOTSTRAP_EMAIL: ${AUTHENTIK_BOOTSTRAP_EMAIL:-admin@localhost}
# AUTHENTIK_COOKIE_DOMAIN: ${AUTHENTIK_COOKIE_DOMAIN:-.mosaicstack.dev}
# volumes:
# - authentik_media:/media
# - authentik_templates:/templates
# healthcheck:
# test:
# [
# "CMD",
# "wget",
# "--no-verbose",
# "--tries=1",
# "--spider",
# "http://localhost:9000/-/health/live/",
# ]
# interval: 30s
# timeout: 10s
# retries: 3
# start_period: 90s
# networks:
# - internal
# - traefik-public
# deploy:
# restart_policy:
# condition: on-failure
# labels:
# - "traefik.enable=true"
# - "traefik.http.routers.mosaic-auth.rule=Host(`${MOSAIC_AUTH_DOMAIN:-auth.mosaicstack.dev}`)"
# - "traefik.http.routers.mosaic-auth.entrypoints=web"
# - "traefik.http.services.mosaic-auth.loadbalancer.server.port=9000"
#
# authentik-worker:
# image: ghcr.io/goauthentik/server:2024.12.1
# env_file: .env
# command: worker
# environment:
# AUTHENTIK_SECRET_KEY: ${AUTHENTIK_SECRET_KEY:-change-this-to-a-random-secret}
# AUTHENTIK_ERROR_REPORTING__ENABLED: ${AUTHENTIK_ERROR_REPORTING:-false}
# AUTHENTIK_POSTGRESQL__HOST: authentik-postgres
# AUTHENTIK_POSTGRESQL__PORT: 5432
# AUTHENTIK_POSTGRESQL__NAME: ${AUTHENTIK_POSTGRES_DB:-authentik}
# AUTHENTIK_POSTGRESQL__USER: ${AUTHENTIK_POSTGRES_USER:-authentik}
# AUTHENTIK_POSTGRESQL__PASSWORD: ${AUTHENTIK_POSTGRES_PASSWORD:-authentik_password}
# AUTHENTIK_REDIS__HOST: authentik-redis
# AUTHENTIK_REDIS__PORT: 6379
# volumes:
# - authentik_media:/media
# - authentik_certs:/certs
# - authentik_templates:/templates
# networks:
# - internal
# deploy:
# restart_policy:
# condition: on-failure
# ======================
# Ollama (Optional AI Service)
# ======================
# ollama:
# image: ollama/ollama:latest
# env_file: .env
# volumes:
# - ollama_data:/root/.ollama
# healthcheck:
# test: ["CMD", "curl", "-f", "http://localhost:11434/api/tags"]
# interval: 30s
# timeout: 10s
# retries: 3
# start_period: 60s
# networks:
# - internal
# deploy:
# restart_policy:
# condition: on-failure
# ======================
# Mosaic Coordinator
# ======================
coordinator:
image: git.mosaicstack.dev/mosaic/stack-coordinator:${IMAGE_TAG:-latest}
env_file: .env
environment:
GITEA_WEBHOOK_SECRET: ${GITEA_WEBHOOK_SECRET}
GITEA_URL: ${GITEA_URL:-https://git.mosaicstack.dev}
ANTHROPIC_API_KEY: ${ANTHROPIC_API_KEY}
LOG_LEVEL: ${LOG_LEVEL:-info}
HOST: 0.0.0.0
PORT: 8000
COORDINATOR_POLL_INTERVAL: ${COORDINATOR_POLL_INTERVAL:-5.0}
COORDINATOR_MAX_CONCURRENT_AGENTS: ${COORDINATOR_MAX_CONCURRENT_AGENTS:-10}
COORDINATOR_ENABLED: ${COORDINATOR_ENABLED:-true}
# Telemetry (task completion tracking & predictions)
MOSAIC_TELEMETRY_ENABLED: ${MOSAIC_TELEMETRY_ENABLED:-false}
MOSAIC_TELEMETRY_SERVER_URL: ${MOSAIC_TELEMETRY_SERVER_URL:-https://tel-api.mosaicstack.dev}
MOSAIC_TELEMETRY_API_KEY: ${MOSAIC_TELEMETRY_API_KEY:-}
MOSAIC_TELEMETRY_INSTANCE_ID: ${MOSAIC_TELEMETRY_INSTANCE_ID:-}
MOSAIC_TELEMETRY_DRY_RUN: ${MOSAIC_TELEMETRY_DRY_RUN:-false}
healthcheck:
test:
[
"CMD",
"python",
"-c",
"import urllib.request; urllib.request.urlopen('http://localhost:8000/health')",
]
interval: 30s
timeout: 10s
retries: 3
start_period: 5s
networks:
- internal
deploy:
restart_policy:
condition: on-failure
# ======================
# Mosaic API
# ======================
api:
image: git.mosaicstack.dev/mosaic/stack-api:${IMAGE_TAG:-latest}
env_file: .env
environment:
NODE_ENV: production
PORT: ${API_PORT:-3001}
API_HOST: ${API_HOST:-0.0.0.0}
DATABASE_URL: postgresql://${POSTGRES_USER:-mosaic}:${POSTGRES_PASSWORD:-mosaic_dev_password}@postgres:5432/${POSTGRES_DB:-mosaic}
VALKEY_URL: redis://valkey:6379
OIDC_ISSUER: ${OIDC_ISSUER}
OIDC_CLIENT_ID: ${OIDC_CLIENT_ID}
OIDC_CLIENT_SECRET: ${OIDC_CLIENT_SECRET}
OIDC_REDIRECT_URI: ${OIDC_REDIRECT_URI:-http://localhost:3001/auth/callback}
JWT_SECRET: ${JWT_SECRET:-change-this-to-a-random-secret}
JWT_EXPIRATION: ${JWT_EXPIRATION:-24h}
BETTER_AUTH_SECRET: ${BETTER_AUTH_SECRET}
OLLAMA_ENDPOINT: ${OLLAMA_ENDPOINT:-http://ollama:11434}
OPENBAO_ADDR: ${OPENBAO_ADDR:-http://openbao:8200}
ORCHESTRATOR_URL: ${ORCHESTRATOR_URL:-http://orchestrator:3001}
ENCRYPTION_KEY: ${ENCRYPTION_KEY}
# Telemetry (task completion tracking & predictions)
MOSAIC_TELEMETRY_ENABLED: ${MOSAIC_TELEMETRY_ENABLED:-false}
MOSAIC_TELEMETRY_SERVER_URL: ${MOSAIC_TELEMETRY_SERVER_URL:-https://tel-api.mosaicstack.dev}
MOSAIC_TELEMETRY_API_KEY: ${MOSAIC_TELEMETRY_API_KEY:-}
MOSAIC_TELEMETRY_INSTANCE_ID: ${MOSAIC_TELEMETRY_INSTANCE_ID:-}
MOSAIC_TELEMETRY_DRY_RUN: ${MOSAIC_TELEMETRY_DRY_RUN:-false}
healthcheck:
test:
[
"CMD-SHELL",
'node -e "require(''http'').get(''http://localhost:${API_PORT:-3001}/health'', (r) => {process.exit(r.statusCode === 200 ? 0 : 1)})"',
]
interval: 30s
timeout: 10s
retries: 3
start_period: 40s
networks:
- internal
- traefik-public
deploy:
restart_policy:
condition: on-failure
labels:
- "traefik.enable=true"
- "traefik.http.routers.mosaic-api.rule=Host(`${MOSAIC_API_DOMAIN:-api.mosaicstack.dev}`)"
- "traefik.http.routers.mosaic-api.entrypoints=web"
- "traefik.http.services.mosaic-api.loadbalancer.server.port=${API_PORT:-3001}"
# ======================
# Mosaic Orchestrator
# ======================
orchestrator:
image: git.mosaicstack.dev/mosaic/stack-orchestrator:${IMAGE_TAG:-latest}
env_file: .env
user: "1000:1000"
environment:
NODE_ENV: production
ORCHESTRATOR_PORT: 3001
VALKEY_URL: redis://valkey:6379
CLAUDE_API_KEY: ${CLAUDE_API_KEY}
DOCKER_SOCKET: /var/run/docker.sock
GIT_USER_NAME: "Mosaic Orchestrator"
GIT_USER_EMAIL: "orchestrator@mosaicstack.dev"
KILLSWITCH_ENABLED: "true"
SANDBOX_ENABLED: "true"
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
- orchestrator_workspace:/workspace
healthcheck:
test:
["CMD-SHELL", "wget --no-verbose --tries=1 --spider http://localhost:3001/health || exit 1"]
interval: 30s
timeout: 10s
retries: 3
start_period: 40s
networks:
- internal
# Note: security_opt not supported in swarm mode
# Security hardening done via cap_drop/cap_add
cap_drop:
- ALL
cap_add:
- NET_BIND_SERVICE
tmpfs:
- /tmp:noexec,nosuid,size=100m
deploy:
restart_policy:
condition: on-failure
# ======================
# Mosaic Web
# ======================
web:
image: git.mosaicstack.dev/mosaic/stack-web:${IMAGE_TAG:-latest}
env_file: .env
environment:
NODE_ENV: production
PORT: ${WEB_PORT:-3000}
NEXT_PUBLIC_API_URL: ${NEXT_PUBLIC_API_URL:-http://localhost:3001}
healthcheck:
test:
[
"CMD-SHELL",
'node -e "require(''http'').get(''http://localhost:${WEB_PORT:-3000}'', (r) => {process.exit(r.statusCode === 200 ? 0 : 1)})"',
]
interval: 30s
timeout: 10s
retries: 3
start_period: 40s
networks:
- traefik-public
deploy:
restart_policy:
condition: on-failure
labels:
- "traefik.enable=true"
- "traefik.http.routers.mosaic-web.rule=Host(`${MOSAIC_WEB_DOMAIN:-mosaic.mosaicstack.dev}`)"
- "traefik.http.routers.mosaic-web.entrypoints=web"
- "traefik.http.services.mosaic-web.loadbalancer.server.port=${WEB_PORT:-3000}"
# ======================
# Volumes
# ======================
volumes:
postgres_data:
valkey_data:
openbao_data:
openbao_logs:
openbao_init:
# Authentik volumes - commented out (using external Authentik)
# authentik_postgres_data:
# authentik_redis_data:
# authentik_media:
# authentik_certs:
# authentik_templates:
# Ollama volume - commented out (using external Ollama)
# ollama_data:
orchestrator_workspace:
# ======================
# Networks
# ======================
networks:
internal:
driver: overlay
traefik-public:
external: true

View File

@@ -1,22 +0,0 @@
# Development overrides for docker-compose.yml
# Usage: docker compose -f docker-compose.yml -f docker-compose.dev.yml up
services:
postgres:
environment:
POSTGRES_USER: mosaic
POSTGRES_PASSWORD: mosaic_dev_password
POSTGRES_DB: mosaic
ports:
- "5432:5432"
# Enable query logging for development
command:
- "postgres"
- "-c"
- "log_statement=all"
- "-c"
- "log_duration=on"
valkey:
ports:
- "6379:6379"

View File

@@ -1,126 +0,0 @@
# ==============================================
# Mosaic Stack - External Services Deployment Example
# ==============================================
# This example shows a production deployment using external managed services.
# All infrastructure (database, cache, secrets, auth, AI) is managed externally.
#
# Usage:
# 1. Copy this file to docker-compose.override.yml
# 2. Set COMPOSE_PROFILES= (empty) in .env
# 3. Configure external service URLs in .env (see below)
# 4. Run: docker compose up -d
#
# Or run directly:
# docker compose -f docker-compose.yml -f docker-compose.example.external.yml up -d
#
# Services Included:
# - API (NestJS) - configured to use external services
# - Web (Next.js)
# - Orchestrator (Agent management)
#
# External Services (configured via .env):
# - PostgreSQL (e.g., AWS RDS, Google Cloud SQL, Azure Database)
# - Redis/Valkey (e.g., AWS ElastiCache, Google Memorystore, Azure Cache)
# - OpenBao/Vault (e.g., HashiCorp Vault Cloud, self-hosted)
# - OIDC Provider (e.g., Auth0, Okta, Google, Azure AD)
# - LLM Service (e.g., hosted Ollama, OpenAI, Anthropic)
#
# Required Environment Variables (.env):
# COMPOSE_PROFILES= # Empty - no bundled services
# IMAGE_TAG=latest
#
# # External Database
# DATABASE_URL=postgresql://user:password@rds.example.com:5432/mosaic
#
# # External Cache
# VALKEY_URL=redis://elasticache.example.com:6379
#
# # External Secrets (OpenBao/Vault)
# OPENBAO_ADDR=https://vault.example.com:8200
# OPENBAO_ROLE_ID=your-role-id
# OPENBAO_SECRET_ID=your-secret-id
#
# # External OIDC Authentication
# OIDC_ENABLED=true
# OIDC_ISSUER=https://auth.example.com/
# OIDC_CLIENT_ID=your-client-id
# OIDC_CLIENT_SECRET=your-client-secret
#
# # External LLM Service
# OLLAMA_ENDPOINT=https://ollama.example.com:11434
# # Or use OpenAI:
# # AI_PROVIDER=openai
# # OPENAI_API_KEY=sk-...
#
# ==============================================
services:
# Disable all bundled infrastructure services
postgres:
profiles:
- disabled
valkey:
profiles:
- disabled
openbao:
profiles:
- disabled
openbao-init:
profiles:
- disabled
authentik-postgres:
profiles:
- disabled
authentik-redis:
profiles:
- disabled
authentik-server:
profiles:
- disabled
authentik-worker:
profiles:
- disabled
ollama:
profiles:
- disabled
# Configure API to use external services
api:
environment:
# External database (e.g., AWS RDS)
DATABASE_URL: ${DATABASE_URL}
# External cache (e.g., AWS ElastiCache)
VALKEY_URL: ${VALKEY_URL}
# External secrets (e.g., HashiCorp Vault Cloud)
OPENBAO_ADDR: ${OPENBAO_ADDR}
OPENBAO_ROLE_ID: ${OPENBAO_ROLE_ID}
OPENBAO_SECRET_ID: ${OPENBAO_SECRET_ID}
# External LLM (e.g., hosted Ollama or OpenAI)
OLLAMA_ENDPOINT: ${OLLAMA_ENDPOINT}
# External OIDC (e.g., Auth0, Okta, Google)
OIDC_ENABLED: ${OIDC_ENABLED}
OIDC_ISSUER: ${OIDC_ISSUER}
OIDC_CLIENT_ID: ${OIDC_CLIENT_ID}
OIDC_CLIENT_SECRET: ${OIDC_CLIENT_SECRET}
# Security
CSRF_SECRET: ${CSRF_SECRET}
ENCRYPTION_KEY: ${ENCRYPTION_KEY}
# Web app remains unchanged
# web: (uses defaults from docker-compose.yml)
# Orchestrator remains unchanged
# orchestrator: (uses defaults from docker-compose.yml)

View File

@@ -1,114 +0,0 @@
# ==============================================
# Mosaic Stack - Hybrid Deployment Example
# ==============================================
# This example shows a hybrid deployment mixing bundled and external services.
# Common for staging environments: bundled database/cache, external auth/secrets.
#
# Usage:
# 1. Copy this file to docker-compose.override.yml
# 2. Set COMPOSE_PROFILES=database,cache,ollama in .env
# 3. Configure external service URLs in .env (see below)
# 4. Run: docker compose up -d
#
# Or run directly:
# docker compose -f docker-compose.yml -f docker-compose.example.hybrid.yml up -d
#
# Services Included (Bundled):
# - PostgreSQL 17 with pgvector
# - Valkey (Redis-compatible cache)
# - Ollama (local LLM)
# - API (NestJS)
# - Web (Next.js)
# - Orchestrator (Agent management)
#
# Services Included (External):
# - OpenBao/Vault (managed secrets)
# - Authentik/OIDC (managed authentication)
#
# Environment Variables (.env):
# COMPOSE_PROFILES=database,cache,ollama # Enable only these bundled services
# IMAGE_TAG=dev
#
# # Bundled Database (default from docker-compose.yml)
# DATABASE_URL=postgresql://mosaic:${POSTGRES_PASSWORD}@postgres:5432/mosaic
#
# # Bundled Cache (default from docker-compose.yml)
# VALKEY_URL=redis://valkey:6379
#
# # Bundled Ollama (default from docker-compose.yml)
# OLLAMA_ENDPOINT=http://ollama:11434
#
# # External Secrets (OpenBao/Vault)
# OPENBAO_ADDR=https://vault.example.com:8200
# OPENBAO_ROLE_ID=your-role-id
# OPENBAO_SECRET_ID=your-secret-id
#
# # External OIDC Authentication
# OIDC_ENABLED=true
# OIDC_ISSUER=https://auth.example.com/
# OIDC_CLIENT_ID=your-client-id
# OIDC_CLIENT_SECRET=your-client-secret
#
# ==============================================
services:
# Use bundled PostgreSQL and Valkey (enabled via database,cache profiles)
# No overrides needed - profiles handle this
# Disable bundled Authentik - use external OIDC
authentik-postgres:
profiles:
- disabled
authentik-redis:
profiles:
- disabled
authentik-server:
profiles:
- disabled
authentik-worker:
profiles:
- disabled
# Disable bundled OpenBao - use external vault
openbao:
profiles:
- disabled
openbao-init:
profiles:
- disabled
# Use bundled Ollama (enabled via ollama profile)
# No override needed
# Configure API for hybrid deployment
api:
environment:
# Bundled database (default)
DATABASE_URL: postgresql://${POSTGRES_USER:-mosaic}:${POSTGRES_PASSWORD}@postgres:5432/${POSTGRES_DB:-mosaic}
# Bundled cache (default)
VALKEY_URL: redis://valkey:6379
# External secrets
OPENBAO_ADDR: ${OPENBAO_ADDR}
OPENBAO_ROLE_ID: ${OPENBAO_ROLE_ID}
OPENBAO_SECRET_ID: ${OPENBAO_SECRET_ID}
# Bundled Ollama (default)
OLLAMA_ENDPOINT: http://ollama:11434
# External OIDC
OIDC_ENABLED: ${OIDC_ENABLED}
OIDC_ISSUER: ${OIDC_ISSUER}
OIDC_CLIENT_ID: ${OIDC_CLIENT_ID}
OIDC_CLIENT_SECRET: ${OIDC_CLIENT_SECRET}
# Security
CSRF_SECRET: ${CSRF_SECRET}
ENCRYPTION_KEY: ${ENCRYPTION_KEY}
# Web and Orchestrator use defaults from docker-compose.yml

View File

@@ -1,43 +0,0 @@
# ==============================================
# Mosaic Stack - Turnkey Deployment Example
# ==============================================
# This example shows a complete all-in-one deployment with all services bundled.
# Ideal for local development, testing, and demo environments.
#
# Usage:
# 1. Copy this file to docker-compose.override.yml (optional)
# 2. Set COMPOSE_PROFILES=full in .env
# 3. Run: docker compose up -d
#
# Or run directly:
# docker compose -f docker-compose.yml -f docker-compose.example.turnkey.yml up -d
#
# Services Included:
# - PostgreSQL 17 with pgvector
# - Valkey (Redis-compatible cache)
# - OpenBao (secrets management)
# - Authentik (OIDC authentication)
# - Ollama (local LLM)
# - Traefik (reverse proxy) - optional, requires traefik-bundled profile
# - API (NestJS)
# - Web (Next.js)
# - Orchestrator (Agent management)
#
# Environment Variables (.env):
# COMPOSE_PROFILES=full
# IMAGE_TAG=dev # or latest
#
# All services run in Docker containers with no external dependencies.
# ==============================================
services:
# No service overrides needed - the main docker-compose.yml handles everything
# This file serves as documentation for turnkey deployment
# Set COMPOSE_PROFILES=full in your .env file to enable all services
# Placeholder to make the file valid YAML
# (Docker Compose requires at least one service definition)
_placeholder:
image: alpine:latest
profiles:
- never-used

View File

@@ -1,123 +0,0 @@
# ==============================================
# Matrix Dev Environment (Synapse + Element Web)
# ==============================================
#
# Development-only overlay for testing the Matrix bridge locally.
# NOT for production — use docker-compose.sample.matrix.yml for production.
#
# Usage:
# docker compose -f docker/docker-compose.yml -f docker/docker-compose.matrix.yml up -d
#
# Or with Makefile:
# make matrix-up
#
# This overlay:
# - Adds Synapse homeserver (localhost:8008) using shared PostgreSQL
# - Adds Element Web client (localhost:8501)
# - Creates a separate 'synapse' database in the shared PostgreSQL instance
# - Enables open registration for easy dev testing
#
# After first startup, create the bot account:
# docker/matrix/scripts/setup-bot.sh
#
# ==============================================
services:
# ======================
# Synapse Database Init
# ======================
# Creates the 'synapse' database and user in the shared PostgreSQL instance.
# Runs once and exits — idempotent, safe to run repeatedly.
synapse-db-init:
image: postgres:17-alpine
container_name: mosaic-synapse-db-init
restart: "no"
environment:
PGHOST: postgres
PGPORT: 5432
PGUSER: ${POSTGRES_USER:-mosaic}
PGPASSWORD: ${POSTGRES_PASSWORD:-mosaic_dev_password}
SYNAPSE_DB: ${SYNAPSE_POSTGRES_DB:-synapse}
SYNAPSE_USER: ${SYNAPSE_POSTGRES_USER:-synapse}
SYNAPSE_PASSWORD: ${SYNAPSE_POSTGRES_PASSWORD:-synapse_dev_password}
entrypoint: ["sh", "-c"]
command:
- |
until pg_isready -h postgres -p 5432 -U $${PGUSER}; do
echo "Waiting for PostgreSQL..."
sleep 2
done
echo "PostgreSQL is ready. Creating Synapse database and user..."
psql -h postgres -U $${PGUSER} -tc "SELECT 1 FROM pg_roles WHERE rolname='$${SYNAPSE_USER}'" | grep -q 1 || \
psql -h postgres -U $${PGUSER} -c "CREATE USER $${SYNAPSE_USER} WITH PASSWORD '$${SYNAPSE_PASSWORD}';"
psql -h postgres -U $${PGUSER} -tc "SELECT 1 FROM pg_database WHERE datname='$${SYNAPSE_DB}'" | grep -q 1 || \
psql -h postgres -U $${PGUSER} -c "CREATE DATABASE $${SYNAPSE_DB} OWNER $${SYNAPSE_USER} ENCODING 'UTF8' LC_COLLATE='C' LC_CTYPE='C' TEMPLATE template0;"
echo "Synapse database ready: $${SYNAPSE_DB}"
depends_on:
postgres:
condition: service_healthy
networks:
- mosaic-internal
# ======================
# Synapse (Matrix Homeserver)
# ======================
synapse:
image: matrixdotorg/synapse:latest
container_name: mosaic-synapse
restart: unless-stopped
environment:
SYNAPSE_CONFIG_DIR: /data
SYNAPSE_CONFIG_PATH: /data/homeserver.yaml
ports:
- "${SYNAPSE_CLIENT_PORT:-8008}:8008"
- "${SYNAPSE_FEDERATION_PORT:-8448}:8448"
volumes:
- /opt/mosaic/synapse/homeserver.yaml:/data/homeserver.yaml:ro
- /opt/mosaic/synapse/media_store:/data/media_store
- /opt/mosaic/synapse/keys:/data/keys
depends_on:
postgres:
condition: service_healthy
synapse-db-init:
condition: service_completed_successfully
healthcheck:
test: ["CMD-SHELL", "curl -fSs http://localhost:8008/health || exit 1"]
interval: 15s
timeout: 5s
retries: 5
start_period: 30s
networks:
- mosaic-internal
labels:
com.mosaic.service: "matrix-synapse"
com.mosaic.description: "Matrix homeserver (dev)"
# ======================
# Element Web (Matrix Client)
# ======================
element-web:
image: vectorim/element-web:latest
container_name: mosaic-element-web
restart: unless-stopped
ports:
- "${ELEMENT_PORT:-8501}:80"
volumes:
- /opt/mosaic/synapse/element-config.json:/app/config.json:ro
depends_on:
synapse:
condition: service_healthy
healthcheck:
test: ["CMD-SHELL", "wget --no-verbose --tries=1 --spider http://localhost:80 || exit 1"]
interval: 30s
timeout: 5s
retries: 3
start_period: 10s
networks:
- mosaic-internal
labels:
com.mosaic.service: "matrix-element"
com.mosaic.description: "Element Web client (dev)"

View File

@@ -1,182 +0,0 @@
# Production Docker Compose - Uses pre-built images from Gitea Packages
#
# Prerequisites:
# - Images built and pushed to git.mosaicstack.dev/mosaic/*
# - .env file configured with production values
#
# Usage:
# docker compose -f docker-compose.prod.yml up -d
#
# For Portainer:
# - Stack → Add Stack → Repository
# - Compose file: docker-compose.prod.yml
services:
# ======================
# PostgreSQL Database
# ======================
postgres:
image: git.mosaicstack.dev/mosaic/postgres:latest
container_name: mosaic-postgres
restart: unless-stopped
environment:
POSTGRES_USER: ${POSTGRES_USER:-mosaic}
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
POSTGRES_DB: ${POSTGRES_DB:-mosaic}
POSTGRES_SHARED_BUFFERS: ${POSTGRES_SHARED_BUFFERS:-256MB}
POSTGRES_EFFECTIVE_CACHE_SIZE: ${POSTGRES_EFFECTIVE_CACHE_SIZE:-1GB}
POSTGRES_MAX_CONNECTIONS: ${POSTGRES_MAX_CONNECTIONS:-100}
volumes:
- postgres_data:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER:-mosaic} -d ${POSTGRES_DB:-mosaic}"]
interval: 10s
timeout: 5s
retries: 5
start_period: 30s
networks:
- mosaic-internal
labels:
- "com.mosaic.service=database"
- "com.mosaic.description=PostgreSQL 17 with pgvector"
# ======================
# Valkey Cache
# ======================
valkey:
image: valkey/valkey:8-alpine
container_name: mosaic-valkey
restart: unless-stopped
command:
- valkey-server
- --maxmemory ${VALKEY_MAXMEMORY:-256mb}
- --maxmemory-policy noeviction
- --appendonly yes
volumes:
- valkey_data:/data
healthcheck:
test: ["CMD", "valkey-cli", "ping"]
interval: 10s
timeout: 5s
retries: 5
start_period: 10s
networks:
- mosaic-internal
labels:
- "com.mosaic.service=cache"
- "com.mosaic.description=Valkey Redis-compatible cache"
# ======================
# Mosaic API
# ======================
api:
image: git.mosaicstack.dev/mosaic/api:latest
container_name: mosaic-api
restart: unless-stopped
environment:
NODE_ENV: production
PORT: ${API_PORT:-3001}
API_HOST: ${API_HOST:-0.0.0.0}
DATABASE_URL: postgresql://${POSTGRES_USER:-mosaic}:${POSTGRES_PASSWORD}@postgres:5432/${POSTGRES_DB:-mosaic}
VALKEY_URL: redis://valkey:6379
OIDC_ISSUER: ${OIDC_ISSUER}
OIDC_CLIENT_ID: ${OIDC_CLIENT_ID}
OIDC_CLIENT_SECRET: ${OIDC_CLIENT_SECRET}
OIDC_REDIRECT_URI: ${OIDC_REDIRECT_URI}
JWT_SECRET: ${JWT_SECRET}
JWT_EXPIRATION: ${JWT_EXPIRATION:-24h}
BETTER_AUTH_SECRET: ${BETTER_AUTH_SECRET}
CSRF_SECRET: ${CSRF_SECRET}
ENCRYPTION_KEY: ${ENCRYPTION_KEY}
OLLAMA_ENDPOINT: ${OLLAMA_ENDPOINT:-http://ollama:11434}
ports:
- "${API_PORT:-3001}:${API_PORT:-3001}"
depends_on:
postgres:
condition: service_healthy
valkey:
condition: service_healthy
healthcheck:
test:
[
"CMD-SHELL",
'node -e "require(''http'').get(''http://localhost:${API_PORT:-3001}/health'', (r) => {process.exit(r.statusCode === 200 ? 0 : 1)})"',
]
interval: 30s
timeout: 10s
retries: 3
start_period: 40s
networks:
- mosaic-internal
- mosaic-public
labels:
- "com.mosaic.service=api"
- "com.mosaic.description=Mosaic NestJS API"
- "traefik.enable=${TRAEFIK_ENABLE:-false}"
- "traefik.http.routers.mosaic-api.rule=Host(`${MOSAIC_API_DOMAIN:-api.mosaicstack.dev}`)"
- "traefik.http.routers.mosaic-api.entrypoints=${TRAEFIK_ENTRYPOINT:-websecure}"
- "traefik.http.routers.mosaic-api.tls=${TRAEFIK_TLS_ENABLED:-true}"
- "traefik.http.services.mosaic-api.loadbalancer.server.port=${API_PORT:-3001}"
- "traefik.docker.network=${TRAEFIK_DOCKER_NETWORK:-mosaic-public}"
- "traefik.http.routers.mosaic-api.tls.certresolver=${TRAEFIK_CERTRESOLVER:-}"
# ======================
# Mosaic Web
# ======================
web:
image: git.mosaicstack.dev/mosaic/web:latest
container_name: mosaic-web
restart: unless-stopped
environment:
NODE_ENV: production
PORT: ${WEB_PORT:-3000}
NEXT_PUBLIC_API_URL: ${NEXT_PUBLIC_API_URL:-https://api.mosaicstack.dev}
ports:
- "${WEB_PORT:-3000}:${WEB_PORT:-3000}"
depends_on:
api:
condition: service_healthy
healthcheck:
test:
[
"CMD-SHELL",
'node -e "require(''http'').get(''http://localhost:${WEB_PORT:-3000}'', (r) => {process.exit(r.statusCode === 200 ? 0 : 1)})"',
]
interval: 30s
timeout: 10s
retries: 3
start_period: 40s
networks:
- mosaic-public
labels:
- "com.mosaic.service=web"
- "com.mosaic.description=Mosaic Next.js Web App"
- "traefik.enable=${TRAEFIK_ENABLE:-false}"
- "traefik.http.routers.mosaic-web.rule=Host(`${MOSAIC_WEB_DOMAIN:-app.mosaicstack.dev}`)"
- "traefik.http.routers.mosaic-web.entrypoints=${TRAEFIK_ENTRYPOINT:-websecure}"
- "traefik.http.routers.mosaic-web.tls=${TRAEFIK_TLS_ENABLED:-true}"
- "traefik.http.services.mosaic-web.loadbalancer.server.port=${WEB_PORT:-3000}"
- "traefik.docker.network=${TRAEFIK_DOCKER_NETWORK:-mosaic-public}"
- "traefik.http.routers.mosaic-web.tls.certresolver=${TRAEFIK_CERTRESOLVER:-}"
# ======================
# Volumes
# ======================
volumes:
postgres_data:
name: mosaic-postgres-data
driver: local
valkey_data:
name: mosaic-valkey-data
driver: local
# ======================
# Networks
# ======================
networks:
mosaic-internal:
name: mosaic-internal
driver: bridge
mosaic-public:
name: mosaic-public
driver: bridge

View File

@@ -1,206 +0,0 @@
# ==============================================
# Matrix (Synapse + Element) - Sample Swarm Deployment
# ==============================================
#
# Standalone Matrix homeserver deployment for use with Mosaic Stack.
# This is SEPARATE infrastructure — not part of the Mosaic Stack itself.
# Mosaic connects to it via MATRIX_HOMESERVER_URL environment variable.
#
# Also serves: personal communications, GoToSocial bridges, other projects.
#
# Usage (Docker Swarm via Portainer):
# 1. Create a new stack in Portainer
# 2. Paste this file or point to the repo
# 3. Set environment variables in Portainer's env var section
# 4. Deploy the stack
#
# Usage (Docker Swarm CLI):
# 1. cp docker-compose.sample.matrix.env .env
# 2. nano .env # Configure
# 3. docker stack deploy -c docker-compose.sample.matrix.yml matrix
#
# Post-Deploy Setup:
# 1. Generate Synapse config (first run only):
# docker exec <synapse_container> python -m synapse.app.homeserver \
# --server-name ${MATRIX_DOMAIN} --report-stats no \
# --generate-config --config-path /data/homeserver.yaml
#
# 2. Create admin account:
# docker exec -it <synapse_container> register_new_matrix_user \
# -u admin -a -c /data/homeserver.yaml http://localhost:8008
#
# 3. Create Mosaic bot account:
# docker exec -it <synapse_container> register_new_matrix_user \
# -u mosaic-bot -c /data/homeserver.yaml http://localhost:8008
#
# 4. Generate bot access token:
# curl -X POST http://localhost:8008/_matrix/client/v3/login \
# -d '{"type":"m.login.password","user":"mosaic-bot","password":"<password>"}'
#
# 5. Set MATRIX_ACCESS_TOKEN in Mosaic Stack .env
#
# Required Environment Variables:
# MATRIX_DOMAIN=matrix.example.com # Synapse server name (permanent!)
# ELEMENT_DOMAIN=chat.example.com # Element Web domain
# POSTGRES_PASSWORD=<strong-password> # Synapse database password
#
# Optional Environment Variables:
# SYNAPSE_IMAGE_TAG=latest # Synapse version
# ELEMENT_IMAGE_TAG=latest # Element Web version
# POSTGRES_IMAGE_TAG=16-alpine # PostgreSQL version
# TRAEFIK_ENTRYPOINT=websecure # Traefik entrypoint name
# TRAEFIK_CERTRESOLVER=letsencrypt # Traefik cert resolver
# TRAEFIK_DOCKER_NETWORK=traefik-public # Traefik network name
# SYNAPSE_ENABLE_REGISTRATION=false # Public registration
# SYNAPSE_REPORT_STATS=no # Anonymous stats reporting
# SYNAPSE_MAX_UPLOAD_SIZE=50M # Max file upload size
#
# Connecting to Mosaic Stack:
# Add to your Mosaic Stack .env:
# MATRIX_HOMESERVER_URL=http://synapse:8008 (if same Docker network)
# MATRIX_HOMESERVER_URL=https://matrix.example.com (if external)
# MATRIX_ACCESS_TOKEN=<bot access token from step 4>
# MATRIX_BOT_USER_ID=@mosaic-bot:matrix.example.com
#
# ==============================================
services:
# ======================
# Synapse (Matrix Homeserver)
# ======================
synapse:
image: matrixdotorg/synapse:${SYNAPSE_IMAGE_TAG:-latest}
environment:
SYNAPSE_SERVER_NAME: ${MATRIX_DOMAIN}
SYNAPSE_REPORT_STATS: ${SYNAPSE_REPORT_STATS:-no}
SYNAPSE_CONFIG_DIR: /data
SYNAPSE_DATA_DIR: /data
SYNAPSE_LOG_LEVEL: ${SYNAPSE_LOG_LEVEL:-WARNING}
# Database connection (external PostgreSQL or bundled)
POSTGRES_HOST: synapse-postgres
POSTGRES_PORT: 5432
POSTGRES_DB: ${SYNAPSE_POSTGRES_DB:-synapse}
POSTGRES_USER: ${SYNAPSE_POSTGRES_USER:-synapse}
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
volumes:
- synapse-data:/data
- synapse-media:/data/media_store
depends_on:
synapse-postgres:
condition: service_healthy
healthcheck:
test: ["CMD-SHELL", "curl -fSs http://localhost:8008/health || exit 1"]
interval: 30s
timeout: 10s
retries: 3
start_period: 30s
networks:
- internal
- traefik-public
deploy:
restart_policy:
condition: on-failure
delay: 10s
labels:
- "traefik.enable=true"
- "traefik.http.routers.matrix.rule=Host(`${MATRIX_DOMAIN}`)"
- "traefik.http.routers.matrix.entrypoints=${TRAEFIK_ENTRYPOINT:-websecure}"
- "traefik.http.routers.matrix.tls=${TRAEFIK_TLS_ENABLED:-true}"
- "traefik.http.routers.matrix.tls.certresolver=${TRAEFIK_CERTRESOLVER:-}"
- "traefik.http.services.matrix.loadbalancer.server.port=8008"
- "traefik.docker.network=${TRAEFIK_DOCKER_NETWORK:-traefik-public}"
# Well-known delegation (optional — for .well-known/matrix/server)
# - "traefik.http.routers.matrix-wellknown.rule=Host(`${MATRIX_DOMAIN}`) && PathPrefix(`/.well-known/matrix`)"
# ======================
# Element Web (Matrix Client)
# ======================
element-web:
image: vectorim/element-web:${ELEMENT_IMAGE_TAG:-latest}
volumes:
- element-config:/app/config
healthcheck:
test: ["CMD-SHELL", "wget --no-verbose --tries=1 --spider http://localhost:80 || exit 1"]
interval: 30s
timeout: 5s
retries: 3
networks:
- internal
- traefik-public
deploy:
restart_policy:
condition: on-failure
labels:
- "traefik.enable=true"
- "traefik.http.routers.element.rule=Host(`${ELEMENT_DOMAIN}`)"
- "traefik.http.routers.element.entrypoints=${TRAEFIK_ENTRYPOINT:-websecure}"
- "traefik.http.routers.element.tls=${TRAEFIK_TLS_ENABLED:-true}"
- "traefik.http.routers.element.tls.certresolver=${TRAEFIK_CERTRESOLVER:-}"
- "traefik.http.services.element.loadbalancer.server.port=80"
- "traefik.docker.network=${TRAEFIK_DOCKER_NETWORK:-traefik-public}"
# ======================
# PostgreSQL (Synapse Database)
# ======================
# Separate from Mosaic's PostgreSQL — Synapse manages its own schema.
# If you prefer a shared PostgreSQL instance, remove this service and
# point POSTGRES_HOST to your existing PostgreSQL with a separate database.
synapse-postgres:
image: postgres:${POSTGRES_IMAGE_TAG:-16-alpine}
environment:
POSTGRES_DB: ${SYNAPSE_POSTGRES_DB:-synapse}
POSTGRES_USER: ${SYNAPSE_POSTGRES_USER:-synapse}
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
POSTGRES_INITDB_ARGS: "--encoding=UTF-8 --lc-collate=C --lc-ctype=C"
volumes:
- synapse-postgres-data:/var/lib/postgresql/data
healthcheck:
test:
[
"CMD-SHELL",
"pg_isready -U ${SYNAPSE_POSTGRES_USER:-synapse} -d ${SYNAPSE_POSTGRES_DB:-synapse}",
]
interval: 10s
timeout: 5s
retries: 5
networks:
- internal
deploy:
restart_policy:
condition: on-failure
# ======================
# coturn (TURN/STUN for VoIP) - Optional
# ======================
# Uncomment if you need voice/video calls through NAT.
# Requires additional DNS and port configuration.
#
# coturn:
# image: coturn/coturn:latest
# environment:
# TURN_REALM: ${MATRIX_DOMAIN}
# TURN_SECRET: ${COTURN_SECRET}
# ports:
# - "3478:3478/tcp"
# - "3478:3478/udp"
# - "5349:5349/tcp"
# - "5349:5349/udp"
# - "49152-49200:49152-49200/udp"
# networks:
# - internal
# deploy:
# restart_policy:
# condition: on-failure
volumes:
synapse-data:
synapse-media:
synapse-postgres-data:
element-config:
networks:
internal:
driver: overlay
traefik-public:
external: true
name: ${TRAEFIK_DOCKER_NETWORK:-traefik-public}

View File

@@ -1,164 +0,0 @@
# ==============================================
# Speech Services - Sample Swarm Deployment
# ==============================================
#
# Standalone speech services deployment for use with Mosaic Stack.
# This is SEPARATE infrastructure — not part of the Mosaic Stack itself.
# Mosaic connects to it via SPEACHES_URL and TTS_URL environment variables.
#
# Provides:
# - Speaches: Speech-to-Text (Whisper) + basic TTS fallback
# - Kokoro TTS: Default high-quality text-to-speech
# - Chatterbox TTS: Premium TTS with voice cloning (optional, requires GPU)
#
# Usage (Docker Swarm via Portainer):
# 1. Create a new stack in Portainer
# 2. Paste this file or point to the repo
# 3. Set environment variables in Portainer's env var section
# 4. Deploy the stack
#
# Usage (Docker Swarm CLI):
# 1. Create .env file with variables below
# 2. docker stack deploy -c docker-compose.sample.speech.yml speech
#
# Required Environment Variables:
# STT_DOMAIN=stt.example.com # Domain for Speaches (STT + basic TTS)
# TTS_DOMAIN=tts.example.com # Domain for Kokoro TTS (default TTS)
#
# Optional Environment Variables:
# WHISPER_MODEL=Systran/faster-whisper-large-v3-turbo # Whisper model for STT
# CHATTERBOX_TTS_DOMAIN=tts-premium.example.com # Domain for Chatterbox (premium TTS)
# TRAEFIK_ENTRYPOINT=websecure # Traefik entrypoint name
# TRAEFIK_CERTRESOLVER=letsencrypt # Traefik cert resolver
# TRAEFIK_DOCKER_NETWORK=traefik-public # Traefik network name
# TRAEFIK_TLS_ENABLED=true # Enable TLS on Traefik routers
#
# Connecting to Mosaic Stack:
# Add to your Mosaic Stack .env:
# SPEACHES_URL=http://speaches:8000 (if same Docker network)
# SPEACHES_URL=https://stt.example.com (if external)
# TTS_URL=http://kokoro-tts:8880 (if same Docker network)
# TTS_URL=https://tts.example.com (if external)
#
# GPU Requirements (Chatterbox only):
# - NVIDIA GPU with CUDA support
# - nvidia-container-toolkit installed on Docker host
# - Docker runtime configured for GPU access
# - Note: Docker Swarm requires "generic resources" for GPU scheduling.
# See: https://docs.docker.com/engine/daemon/nvidia-gpu/#configure-gpus-for-docker-swarm
#
# ==============================================
services:
# ======================
# Speaches (STT + basic TTS)
# ======================
# Primary speech-to-text service using Whisper.
# Also provides basic TTS as a fallback.
speaches:
image: ghcr.io/speaches-ai/speaches:latest
environment:
WHISPER__MODEL: ${WHISPER_MODEL:-Systran/faster-whisper-large-v3-turbo}
volumes:
- speaches-models:/root/.cache/huggingface
healthcheck:
test: ["CMD-SHELL", "curl -f http://localhost:8000/health || exit 1"]
interval: 30s
timeout: 10s
retries: 5
start_period: 120s
networks:
- internal
- traefik-public
deploy:
restart_policy:
condition: on-failure
delay: 10s
labels:
- "traefik.enable=true"
- "traefik.http.routers.speech-stt.rule=Host(`${STT_DOMAIN}`)"
- "traefik.http.routers.speech-stt.entrypoints=${TRAEFIK_ENTRYPOINT:-websecure}"
- "traefik.http.routers.speech-stt.tls=${TRAEFIK_TLS_ENABLED:-true}"
- "traefik.http.routers.speech-stt.tls.certresolver=${TRAEFIK_CERTRESOLVER:-}"
- "traefik.http.services.speech-stt.loadbalancer.server.port=8000"
- "traefik.docker.network=${TRAEFIK_DOCKER_NETWORK:-traefik-public}"
# ======================
# Kokoro TTS (Default TTS)
# ======================
# High-quality text-to-speech engine. Always deployed alongside Speaches.
kokoro-tts:
image: ghcr.io/remsky/kokoro-fastapi:latest-cpu
healthcheck:
test: ["CMD-SHELL", "curl -f http://localhost:8880/health || exit 1"]
interval: 30s
timeout: 10s
retries: 5
start_period: 120s
networks:
- internal
- traefik-public
deploy:
restart_policy:
condition: on-failure
delay: 10s
labels:
- "traefik.enable=true"
- "traefik.http.routers.speech-tts.rule=Host(`${TTS_DOMAIN}`)"
- "traefik.http.routers.speech-tts.entrypoints=${TRAEFIK_ENTRYPOINT:-websecure}"
- "traefik.http.routers.speech-tts.tls=${TRAEFIK_TLS_ENABLED:-true}"
- "traefik.http.routers.speech-tts.tls.certresolver=${TRAEFIK_CERTRESOLVER:-}"
- "traefik.http.services.speech-tts.loadbalancer.server.port=8880"
- "traefik.docker.network=${TRAEFIK_DOCKER_NETWORK:-traefik-public}"
# ======================
# Chatterbox TTS (Premium TTS - Optional)
# ======================
# Premium TTS with voice cloning capabilities. Requires NVIDIA GPU.
#
# To enable: Uncomment this service and set CHATTERBOX_TTS_DOMAIN.
#
# For Docker Swarm GPU scheduling, configure generic resources on the node:
# /etc/docker/daemon.json:
# { "runtimes": { "nvidia": { ... } },
# "node-generic-resources": ["NVIDIA-GPU=0"] }
#
# chatterbox-tts:
# image: devnen/chatterbox-tts-server:latest
# healthcheck:
# test: ["CMD-SHELL", "curl -f http://localhost:8000/health || exit 1"]
# interval: 30s
# timeout: 10s
# retries: 5
# start_period: 180s
# networks:
# - internal
# - traefik-public
# deploy:
# restart_policy:
# condition: on-failure
# delay: 10s
# resources:
# reservations:
# generic_resources:
# - discrete_resource_spec:
# kind: "NVIDIA-GPU"
# value: 1
# labels:
# - "traefik.enable=true"
# - "traefik.http.routers.speech-tts-premium.rule=Host(`${CHATTERBOX_TTS_DOMAIN}`)"
# - "traefik.http.routers.speech-tts-premium.entrypoints=${TRAEFIK_ENTRYPOINT:-websecure}"
# - "traefik.http.routers.speech-tts-premium.tls=${TRAEFIK_TLS_ENABLED:-true}"
# - "traefik.http.routers.speech-tts-premium.tls.certresolver=${TRAEFIK_CERTRESOLVER:-}"
# - "traefik.http.services.speech-tts-premium.loadbalancer.server.port=8000"
# - "traefik.docker.network=${TRAEFIK_DOCKER_NETWORK:-traefik-public}"
volumes:
speaches-models:
networks:
internal:
driver: overlay
traefik-public:
external: true
name: ${TRAEFIK_DOCKER_NETWORK:-traefik-public}

View File

@@ -1,30 +1,34 @@
{
"default_server_config": {
"m.homeserver": {
"base_url": "http://localhost:8008",
"server_name": "localhost"
"base_url": "https://matrix.mosaicstack.dev",
"server_name": "matrix.mosaicstack.dev"
},
"m.identity_server": {
"base_url": "https://vector.im"
}
},
"brand": "Mosaic Stack Dev",
"brand": "Mosaic Chat",
"integrations_ui_url": "https://scalar.vector.im/",
"integrations_rest_url": "https://scalar.vector.im/api",
"integrations_widgets_urls": [
"https://scalar.vector.im/_matrix/integrations/v1",
"https://scalar.vector.im/api",
"https://scalar-staging.vector.im/_matrix/integrations/v1",
"https://scalar-staging.vector.im/api",
"https://scalar-staging.riot.im/scalar/api"
],
"disable_custom_urls": false,
"disable_guests": true,
"disable_login_language_selector": false,
"disable_3pid_login": false,
"default_country_code": "US",
"show_labs_settings": false,
"default_theme": "dark",
"room_directory": {
"servers": ["localhost"]
"servers": ["matrix.mosaicstack.dev"]
},
"features": {
"feature_video_rooms": false,
"feature_group_calls": false
},
"show_labs_settings": true,
"piwik": false,
"posthog": {
"enabled": false
},
"privacy_policy_url": null,
"terms_and_conditions_links": [],
"setting_defaults": {
"breadcrumbs": true,
"custom_themes": []
},
"disable_guests": true,
"disable_3pid_login": true
"breadcrumbs": true
}
}

View File

@@ -1,27 +1,31 @@
# ==============================================
# Synapse Homeserver Configuration — Development Only
# Synapse Homeserver Configuration — Production
# ==============================================
#
# This config is for LOCAL DEVELOPMENT with the Mosaic Stack docker-compose overlay.
# Do NOT use this in production. See docker-compose.sample.matrix.yml for production.
# Deploy to /opt/mosaic/synapse/homeserver.yaml on the Docker host.
#
# Server name is set to 'localhost' — this is permanent and cannot be changed
# after the database has been initialized.
# IMPORTANT: server_name is PERMANENT. It becomes part of every user ID
# (@user:server_name) and room alias. It cannot be changed after the
# database has been initialized without losing all data.
#
# Before first deploy, replace ALL placeholders marked REPLACE_*.
#
# ==============================================
server_name: "localhost"
# REPLACE with your Matrix domain (e.g. matrix.mosaicstack.dev)
# This is permanent — cannot be changed after first startup.
server_name: "REPLACE_MATRIX_DOMAIN"
pid_file: /data/homeserver.pid
public_baseurl: "http://localhost:8008/"
public_baseurl: "https://REPLACE_MATRIX_DOMAIN/"
# ======================
# Network Listeners
# ======================
listeners:
# Client API (used by Element Web, Mosaic bridge, etc.)
- port: 8008
tls: false
type: http
# Traefik terminates TLS and forwards via X-Forwarded-For
x_forwarded: true
bind_addresses: ["0.0.0.0"]
resources:
@@ -35,9 +39,11 @@ database:
name: psycopg2
txn_limit: 10000
args:
user: "synapse"
password: "synapse_dev_password"
database: "synapse"
# Must match SYNAPSE_POSTGRES_USER / SYNAPSE_POSTGRES_PASSWORD
# from your Portainer environment variables
user: "REPLACE_SYNAPSE_DB_USER"
password: "REPLACE_SYNAPSE_DB_PASSWORD"
database: "REPLACE_SYNAPSE_DB_NAME"
host: "postgres"
port: 5432
cp_min: 5
@@ -66,20 +72,25 @@ url_preview_ip_range_blacklist:
- "fec0::/10"
# ======================
# Registration (Dev Only)
# Registration
# ======================
enable_registration: true
enable_registration_without_verification: true
# Public registration disabled. Create accounts via the admin API or CLI:
# docker exec -it <container> register_new_matrix_user \
# -u username -c /data/homeserver.yaml http://localhost:8008
enable_registration: false
# ======================
# Signing Keys
# ======================
# Auto-generated on first startup and persisted in the signing_key volume
signing_key_path: "/data/keys/localhost.signing.key"
# Auto-generated on first startup and persisted in /opt/mosaic/synapse/keys/
signing_key_path: "/data/keys/signing.key"
# Suppress warning about trusted key servers in dev
suppress_key_server_warning: true
trusted_key_servers: []
# ======================
# Trusted Key Servers
# ======================
# matrix.org is the default. Set to [] to disable federation key trust.
trusted_key_servers:
- server_name: "matrix.org"
# ======================
# Room Configuration
@@ -88,44 +99,46 @@ enable_room_list_search: true
allow_public_rooms_over_federation: false
# ======================
# Rate Limiting (Relaxed for Dev)
# Rate Limiting
# ======================
rc_message:
per_second: 100
burst_count: 200
rc_registration:
per_second: 10
burst_count: 50
rc_registration:
per_second: 1
burst_count: 5
rc_login:
address:
per_second: 10
burst_count: 50
per_second: 3
burst_count: 10
account:
per_second: 10
burst_count: 50
per_second: 3
burst_count: 10
# ======================
# Logging
# ======================
log_config: "/data/localhost.log.config"
# Inline log config — write to stdout for docker logs
# Synapse falls back to a basic console logger if the log_config file is missing,
# so we leave log_config pointing to a non-existent file intentionally.
# Override: mount a custom log config file at /data/localhost.log.config
# Synapse falls back to a basic console logger (stdout) when this file
# does not exist, which is ideal for Docker log collection.
log_config: "/data/log.config"
# ======================
# Miscellaneous
# Secrets
# ======================
# Generate with: python3 -c 'import secrets; print(secrets.token_hex(32))'
report_stats: false
macaroon_secret_key: "dev-macaroon-secret-change-in-production"
form_secret: "dev-form-secret-change-in-production"
macaroon_secret_key: "REPLACE_MACAROON_SECRET"
form_secret: "REPLACE_FORM_SECRET"
# Enable presence for dev
# ======================
# Presence & Retention
# ======================
use_presence: true
# Retention policy (optional, keep messages for 180 days in dev)
retention:
enabled: false
enabled: true
default_policy:
min_lifetime: 1d
max_lifetime: 365d

View File

@@ -11,9 +11,6 @@ listener "tcp" {
tls_disable = 1
}
# Disable memory locking for Docker compatibility
disable_mlock = true
# API address for cluster communication
api_addr = "http://0.0.0.0:8200"