# Mana Mac Mini Configuration # Domain: mana.how (via Cloudflare Tunnel) # # Port Schema: # 3000-3099: Core Services & Backends # 4000-4099: Matrix Stack # 5000-5099: Web Frontends # 5100-5199: Games # 6000-6099: Automation & Workflows # 8000-8099: Monitoring Dashboards # 9000-9199: Infrastructure & Exporters # # Naming Convention: mana-{category}-{service} # Categories: infra, core, app, matrix, mon, auto services: # ============================================ # Tier 0: Infrastructure Services # ============================================ postgres: image: postgres:16-alpine container_name: mana-infra-postgres restart: always environment: POSTGRES_DB: mana POSTGRES_USER: postgres POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-mana123} volumes: - /Volumes/ManaData/postgres:/var/lib/postgresql/data ports: - "5432:5432" healthcheck: test: ["CMD-SHELL", "pg_isready -U postgres"] interval: 10s timeout: 5s retries: 5 redis: image: redis:7-alpine container_name: mana-infra-redis restart: always command: redis-server --requirepass ${REDIS_PASSWORD:-redis123} volumes: - redis_data:/data ports: - "6379:6379" healthcheck: test: ["CMD", "redis-cli", "--raw", "incr", "ping"] interval: 10s timeout: 5s retries: 5 minio: image: minio/minio:latest container_name: mana-infra-minio restart: always command: server /data --console-address ":9001" environment: MINIO_ROOT_USER: ${MINIO_ACCESS_KEY:-minioadmin} MINIO_ROOT_PASSWORD: ${MINIO_SECRET_KEY:-minioadmin} volumes: - /Volumes/ManaData/minio:/data ports: - "9000:9000" - "9001:9001" healthcheck: test: ["CMD", "mc", "ready", "local"] interval: 30s timeout: 20s retries: 3 # MinIO bucket initialization and lifecycle rules (runs once) minio-init: image: minio/mc:latest container_name: mana-infra-minio-init depends_on: minio: condition: service_healthy entrypoint: > /bin/sh -c " mc alias set myminio http://minio:9000 $${MINIO_ACCESS_KEY:-minioadmin} $${MINIO_SECRET_KEY:-minioadmin}; mc mb --ignore-existing myminio/manacore-storage; mc mb --ignore-existing myminio/picture-storage; mc mb --ignore-existing myminio/chat-storage; mc mb --ignore-existing myminio/manadeck-storage; mc mb --ignore-existing myminio/presi-storage; mc mb --ignore-existing myminio/calendar-storage; mc mb --ignore-existing myminio/contacts-storage; mc mb --ignore-existing myminio/storage-storage; mc mb --ignore-existing myminio/inventory-storage; mc mb --ignore-existing myminio/mukke-storage; mc mb --ignore-existing myminio/planta-storage; mc mb --ignore-existing myminio/projectdoc-storage; mc mb --ignore-existing myminio/mail-storage; mc anonymous set download myminio/manacore-storage; mc anonymous set download myminio/picture-storage; mc anonymous set download myminio/planta-storage; mc anonymous set download myminio/inventory-storage; mc ilm rule add --expire-days 90 myminio/chat-storage --prefix 'tmp/' 2>/dev/null || true; mc ilm rule add --expire-days 30 myminio/calendar-storage --prefix 'tmp/' 2>/dev/null || true; mc ilm rule add --expire-days 7 myminio/picture-storage --prefix 'tmp/' 2>/dev/null || true; echo 'Buckets and lifecycle rules created successfully'; exit 0; " # ============================================ # Tier 1: Core Auth Service (Port 3001) # ============================================ mana-auth: build: context: . dockerfile: services/mana-core-auth/Dockerfile image: mana-core-auth:local container_name: mana-core-auth restart: always depends_on: postgres: condition: service_healthy redis: condition: service_healthy environment: NODE_ENV: production PORT: 3001 DATABASE_URL: postgresql://postgres:${POSTGRES_PASSWORD:-mana123}@postgres:5432/mana_auth REDIS_HOST: redis REDIS_PORT: 6379 REDIS_PASSWORD: ${REDIS_PASSWORD:-redis123} JWT_SECRET: ${JWT_SECRET:-your-jwt-secret-change-me} BETTER_AUTH_SECRET: ${BETTER_AUTH_SECRET:-${JWT_SECRET:-your-jwt-secret-change-me}} JWT_PUBLIC_KEY: ${JWT_PUBLIC_KEY:-} JWT_PRIVATE_KEY: ${JWT_PRIVATE_KEY:-} BASE_URL: https://auth.mana.how # Cross-domain SSO: share session cookies across all *.mana.how subdomains COOKIE_DOMAIN: .mana.how MANA_CORE_SERVICE_KEY: ${MANA_CORE_SERVICE_KEY} SMTP_HOST: smtp-relay.brevo.com SMTP_PORT: 587 SMTP_USER: ${SMTP_USER:-94cde5002@smtp-brevo.com} SMTP_PASSWORD: ${SMTP_PASSWORD} SMTP_FROM: Mana CORS_ORIGINS: https://mana.how,https://calendar.mana.how,https://chat.mana.how,https://clock.mana.how,https://contacts.mana.how,https://context.mana.how,https://docs.mana.how,https://element.mana.how,https://link.mana.how,https://manadeck.mana.how,https://matrix.mana.how,https://mukke.mana.how,https://nutriphi.mana.how,https://photos.mana.how,https://picture.mana.how,https://planta.mana.how,https://playground.mana.how,https://presi.mana.how,https://questions.mana.how,https://skilltree.mana.how,https://storage.mana.how,https://todo.mana.how,https://traces.mana.how,https://zitare.mana.how DUCKDB_PATH: /data/analytics/metrics.duckdb SYNAPSE_OIDC_CLIENT_SECRET: ${SYNAPSE_OIDC_CLIENT_SECRET:-} # Backend URLs for user data aggregation (GDPR self-service) CHAT_BACKEND_URL: http://chat-backend:3030 TODO_BACKEND_URL: http://todo-backend:3031 CALENDAR_BACKEND_URL: http://calendar-backend:3032 CONTACTS_BACKEND_URL: http://contacts-backend:3034 PICTURE_BACKEND_URL: http://picture-backend:3040 PRESI_BACKEND_URL: http://presi-backend:3036 ZITARE_BACKEND_URL: http://zitare-backend:3007 PHOTOS_BACKEND_URL: http://photos-backend:3039 CLOCK_BACKEND_URL: http://clock-backend:3033 STORAGE_BACKEND_URL: http://storage-backend:3035 ADMIN_SERVICE_KEY: ${MANA_CORE_SERVICE_KEY} volumes: - analytics_data:/data/analytics ports: - "3001:3001" healthcheck: test: ["CMD", "node", "-e", "const http = require('http'); http.get('http://127.0.0.1:3001/health', (r) => process.exit(r.statusCode === 200 ? 0 : 1)).on('error', () => process.exit(1))"] interval: 30s timeout: 10s retries: 3 start_period: 40s # ============================================ # Tier 2: Gateway & Search Services (Ports 3010-3029) # ============================================ # NOTE: api-gateway disabled - no GHCR image available, no Dockerfile exists # To re-enable: create Dockerfile in services/api-gateway/ and build locally api-gateway: profiles: ["disabled"] image: ghcr.io/memo-2023/api-gateway:latest container_name: mana-core-gateway restart: always depends_on: mana-auth: condition: service_healthy # Removed: postgres, redis, mana-search - lazy connect with retry environment: NODE_ENV: production PORT: 3010 DATABASE_URL: postgresql://postgres:${POSTGRES_PASSWORD:-mana123}@postgres:5432/mana REDIS_HOST: redis REDIS_PORT: 6379 REDIS_PASSWORD: ${REDIS_PASSWORD:-redis123} MANA_CORE_AUTH_URL: http://mana-auth:3001 SEARCH_SERVICE_URL: http://mana-search:3020 STT_SERVICE_URL: http://host.docker.internal:3021 TTS_SERVICE_URL: http://host.docker.internal:3022 IMAGE_GEN_SERVICE_URL: http://host.docker.internal:3025 CORS_ORIGINS: https://api.mana.how,https://mana.how # Retry config for lazy dependencies DB_RETRY_ATTEMPTS: 5 DB_RETRY_DELAY: 3000 ports: - "3010:3010" healthcheck: test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://127.0.0.1:3010/health"] interval: 30s timeout: 10s retries: 3 start_period: 40s searxng: image: searxng/searxng:latest container_name: mana-core-searxng restart: always volumes: - ./services/mana-search/searxng/settings.yml:/etc/searxng/settings.yml:ro - ./services/mana-search/searxng/limiter.toml:/etc/searxng/limiter.toml:ro environment: SEARXNG_BASE_URL: http://searxng:8080 SEARXNG_SECRET: ${SEARXNG_SECRET:-change-me-searxng-secret} # Internal only - no external port mapping healthcheck: test: ["CMD", "wget", "-q", "--spider", "http://localhost:8080/healthz"] interval: 30s timeout: 10s retries: 3 start_period: 15s mana-search: build: context: . dockerfile: services/mana-search/Dockerfile image: mana-search:local container_name: mana-core-search restart: always depends_on: searxng: condition: service_healthy # Removed: redis - lazy connect environment: NODE_ENV: production PORT: 3020 SEARXNG_URL: http://searxng:8080 SEARXNG_TIMEOUT: 15000 SEARXNG_DEFAULT_LANGUAGE: de-DE REDIS_HOST: redis REDIS_PORT: 6379 REDIS_PASSWORD: ${REDIS_PASSWORD:-redis123} CACHE_SEARCH_TTL: 3600 CACHE_EXTRACT_TTL: 86400 EXTRACT_TIMEOUT: 10000 EXTRACT_MAX_LENGTH: 50000 ports: - "3020:3020" healthcheck: test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://127.0.0.1:3020/api/v1/health"] interval: 30s timeout: 10s retries: 3 start_period: 40s mana-media: build: context: . dockerfile: services/mana-media/apps/api/Dockerfile image: mana-media:local container_name: mana-core-media restart: always depends_on: postgres: condition: service_healthy redis: condition: service_healthy minio: condition: service_healthy environment: NODE_ENV: production PORT: 3015 DATABASE_URL: postgresql://postgres:${POSTGRES_PASSWORD:-mana123}@postgres:5432/mana_media REDIS_HOST: redis REDIS_PORT: 6379 REDIS_PASSWORD: ${REDIS_PASSWORD:-redis123} S3_ENDPOINT: minio S3_PORT: 9000 S3_USE_SSL: "false" S3_ACCESS_KEY: ${MINIO_ACCESS_KEY:-minioadmin} S3_SECRET_KEY: ${MINIO_SECRET_KEY:-minioadmin} S3_BUCKET: mana-media S3_PUBLIC_URL: https://media.mana.how MATRIX_HOMESERVER_URL: https://matrix.mana.how PUBLIC_URL: https://media.mana.how/api/v1 CORS_ORIGINS: https://mana.how,https://nutriphi.mana.how,https://contacts.mana.how,https://chat.mana.how,https://storage.mana.how,https://photos.mana.how ports: - "3015:3015" healthcheck: test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://127.0.0.1:3015/api/v1/health"] interval: 30s timeout: 10s retries: 3 start_period: 40s # ============================================ # Tier 3: App Backends (Ports 3030-3049) # ============================================ chat-backend: build: context: . dockerfile: apps/chat/apps/backend/Dockerfile image: chat-backend:local container_name: mana-app-chat-backend restart: always depends_on: mana-auth: condition: service_healthy # Removed: postgres - lazy connect environment: NODE_ENV: production PORT: 3030 DATABASE_URL: postgresql://postgres:${POSTGRES_PASSWORD:-mana123}@postgres:5432/chat MANA_CORE_AUTH_URL: http://mana-auth:3001 OLLAMA_URL: http://host.docker.internal:11434 OLLAMA_TIMEOUT: 120000 OPENROUTER_API_KEY: ${OPENROUTER_API_KEY:-} SUPABASE_URL: ${SUPABASE_URL:-} SUPABASE_SERVICE_KEY: ${SUPABASE_SERVICE_ROLE_KEY:-} AZURE_OPENAI_ENDPOINT: ${AZURE_OPENAI_ENDPOINT:-} AZURE_OPENAI_API_KEY: ${AZURE_OPENAI_API_KEY:-} AZURE_OPENAI_API_VERSION: 2024-12-01-preview CORS_ORIGINS: https://chat.mana.how,https://mana.how ADMIN_SERVICE_KEY: ${MANA_CORE_SERVICE_KEY} GLITCHTIP_DSN: https://7ffb55d23705497989dbabd486a42014@glitchtip.mana.how/4 ports: - "3030:3030" healthcheck: test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://127.0.0.1:3030/health"] interval: 30s timeout: 10s retries: 3 start_period: 40s todo-backend: build: context: . dockerfile: apps/todo/apps/backend/Dockerfile image: todo-backend:local container_name: mana-app-todo-backend restart: always depends_on: mana-auth: condition: service_healthy environment: NODE_ENV: production PORT: 3031 DATABASE_URL: postgresql://postgres:${POSTGRES_PASSWORD:-mana123}@postgres:5432/todo MANA_CORE_AUTH_URL: http://mana-auth:3001 CORS_ORIGINS: https://todo.mana.how,https://mana.how,https://calendar.mana.how,https://contacts.mana.how ADMIN_SERVICE_KEY: ${MANA_CORE_SERVICE_KEY} GLITCHTIP_DSN: https://c774433d212c473d9088542a84224488@glitchtip.mana.how/3 ports: - "3031:3031" healthcheck: test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://127.0.0.1:3031/health"] interval: 30s timeout: 10s retries: 3 start_period: 40s calendar-backend: build: context: . dockerfile: apps/calendar/apps/backend/Dockerfile image: calendar-backend:local container_name: mana-app-calendar-backend restart: always depends_on: mana-auth: condition: service_healthy environment: NODE_ENV: production PORT: 3032 DATABASE_URL: postgresql://postgres:${POSTGRES_PASSWORD:-mana123}@postgres:5432/calendar DB_HOST: postgres DB_PORT: 5432 DB_USER: postgres MANA_CORE_AUTH_URL: http://mana-auth:3001 CORS_ORIGINS: https://calendar.mana.how,https://mana.how ADMIN_SERVICE_KEY: ${MANA_CORE_SERVICE_KEY} ENCRYPTION_KEY: ${CALENDAR_ENCRYPTION_KEY:-} GLITCHTIP_DSN: https://7dcf6e8648a04b85b2cb275921c059d5@glitchtip.mana.how/1 ports: - "3032:3032" healthcheck: test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://127.0.0.1:3032/health"] interval: 30s timeout: 10s retries: 3 start_period: 40s clock-backend: build: context: . dockerfile: apps/clock/apps/backend/Dockerfile image: clock-backend:local container_name: mana-app-clock-backend restart: always depends_on: mana-auth: condition: service_healthy environment: NODE_ENV: production PORT: 3033 DATABASE_URL: postgresql://postgres:${POSTGRES_PASSWORD:-mana123}@postgres:5432/clock DB_HOST: postgres DB_PORT: 5432 DB_USER: postgres MANA_CORE_AUTH_URL: http://mana-auth:3001 CORS_ORIGINS: https://clock.mana.how,https://mana.how ADMIN_SERVICE_KEY: ${MANA_CORE_SERVICE_KEY} GLITCHTIP_DSN: https://4d5ea890019d4a988e9834bc3e374e0a@glitchtip.mana.how/7 ports: - "3033:3033" healthcheck: test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://127.0.0.1:3033/health"] interval: 30s timeout: 10s retries: 3 start_period: 40s contacts-backend: build: context: . dockerfile: apps/contacts/apps/backend/Dockerfile image: contacts-backend:local container_name: mana-app-contacts-backend restart: always depends_on: mana-auth: condition: service_healthy # Removed: minio - lazy connect environment: NODE_ENV: production PORT: 3034 DATABASE_URL: postgresql://postgres:${POSTGRES_PASSWORD:-mana123}@postgres:5432/contacts DB_HOST: postgres DB_PORT: 5432 DB_USER: postgres MANA_CORE_AUTH_URL: http://mana-auth:3001 CORS_ORIGINS: https://contacts.mana.how,https://mana.how,https://calendar.mana.how S3_ENDPOINT: http://minio:9000 S3_REGION: us-east-1 S3_ACCESS_KEY: ${MINIO_ACCESS_KEY:-minioadmin} S3_SECRET_KEY: ${MINIO_SECRET_KEY:-minioadmin} S3_BUCKET: contacts-photos ADMIN_SERVICE_KEY: ${MANA_CORE_SERVICE_KEY} GLITCHTIP_DSN: https://a0d81e4b78694b57951a1a5de6d64ae7@glitchtip.mana.how/2 ports: - "3034:3034" healthcheck: test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://127.0.0.1:3034/health"] interval: 30s timeout: 10s retries: 3 start_period: 40s storage-backend: build: context: . dockerfile: apps/storage/apps/backend/Dockerfile image: storage-backend:local container_name: mana-app-storage-backend restart: always depends_on: mana-auth: condition: service_healthy environment: NODE_ENV: production PORT: 3035 DATABASE_URL: postgresql://postgres:${POSTGRES_PASSWORD:-mana123}@postgres:5432/storage MANA_CORE_AUTH_URL: http://mana-auth:3001 CORS_ORIGINS: https://storage.mana.how,https://mana.how S3_ENDPOINT: http://minio:9000 S3_REGION: us-east-1 S3_ACCESS_KEY: ${MINIO_ACCESS_KEY:-minioadmin} S3_SECRET_KEY: ${MINIO_SECRET_KEY:-minioadmin} S3_BUCKET: storage-storage STORAGE_S3_PUBLIC_URL: https://storage-files.mana.how MAX_FILE_SIZE: 104857600 MAX_FILES_PER_UPLOAD: 10 ADMIN_SERVICE_KEY: ${MANA_CORE_SERVICE_KEY} GLITCHTIP_DSN: https://f38d9b20ba2d416b80d1c559b81fc275@glitchtip.mana.how/17 ports: - "3035:3035" healthcheck: test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://127.0.0.1:3035/api/v1/health"] interval: 30s timeout: 10s retries: 3 start_period: 40s presi-backend: build: context: . dockerfile: apps/presi/apps/backend/Dockerfile image: presi-backend:local container_name: mana-app-presi-backend restart: always depends_on: mana-auth: condition: service_healthy environment: NODE_ENV: production PORT: 3036 DATABASE_URL: postgresql://postgres:${POSTGRES_PASSWORD:-mana123}@postgres:5432/presi MANA_CORE_AUTH_URL: http://mana-auth:3001 CORS_ORIGINS: https://presi.mana.how,https://mana.how ADMIN_SERVICE_KEY: ${MANA_CORE_SERVICE_KEY} GLITCHTIP_DSN: https://24df6aad72b646ba9fb68e54b566ad3e@glitchtip.mana.how/14 ports: - "3036:3036" healthcheck: test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://127.0.0.1:3036/api/v1/health"] interval: 30s timeout: 10s retries: 3 start_period: 40s nutriphi-backend: build: context: . dockerfile: apps/nutriphi/apps/backend/Dockerfile image: nutriphi-backend:local container_name: mana-app-nutriphi-backend restart: always depends_on: mana-auth: condition: service_healthy environment: NODE_ENV: production PORT: 3037 DATABASE_URL: postgresql://postgres:${POSTGRES_PASSWORD:-mana123}@postgres:5432/nutriphi DB_HOST: postgres DB_PORT: 5432 DB_USER: postgres MANA_CORE_AUTH_URL: http://mana-auth:3001 GEMINI_API_KEY: ${GEMINI_API_KEY:-} CORS_ORIGINS: https://nutriphi.mana.how,https://mana.how GLITCHTIP_DSN: https://61b5689b903746b698bd1f77ae9e0be1@glitchtip.mana.how/11 ports: - "3037:3037" healthcheck: test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://127.0.0.1:3037/api/v1/health"] interval: 30s timeout: 10s retries: 3 start_period: 40s skilltree-backend: build: context: . dockerfile: apps/skilltree/apps/backend/Dockerfile image: skilltree-backend:local container_name: mana-app-skilltree-backend restart: always depends_on: mana-auth: condition: service_healthy environment: NODE_ENV: production PORT: 3038 DATABASE_URL: postgresql://postgres:${POSTGRES_PASSWORD:-mana123}@postgres:5432/skilltree DB_HOST: postgres DB_PORT: 5432 DB_USER: postgres MANA_CORE_AUTH_URL: http://mana-auth:3001 CORS_ORIGINS: https://skilltree.mana.how,https://mana.how GLITCHTIP_DSN: https://93548ec4e2a14586bfef9f4f98e72fe1@glitchtip.mana.how/16 ports: - "3038:3038" healthcheck: test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://127.0.0.1:3038/health"] interval: 30s timeout: 10s retries: 3 start_period: 40s photos-backend: build: context: . dockerfile: apps/photos/apps/backend/Dockerfile image: photos-backend:local container_name: mana-app-photos-backend restart: always depends_on: mana-auth: condition: service_healthy mana-media: condition: service_healthy environment: NODE_ENV: production PORT: 3039 DATABASE_URL: postgresql://postgres:${POSTGRES_PASSWORD:-mana123}@postgres:5432/photos DB_HOST: postgres DB_PORT: 5432 DB_USER: postgres MANA_CORE_AUTH_URL: http://mana-auth:3001 MANA_MEDIA_URL: http://mana-media:3015 CORS_ORIGINS: https://photos.mana.how,https://mana.how ADMIN_SERVICE_KEY: ${MANA_CORE_SERVICE_KEY} GLITCHTIP_DSN: https://032aef0f1da94497b8b8f6accb0c4587@glitchtip.mana.how/12 ports: - "3039:3039" healthcheck: test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://127.0.0.1:3039/api/v1/health"] interval: 30s timeout: 10s retries: 3 start_period: 40s zitare-backend: build: context: . dockerfile: apps/zitare/apps/backend/Dockerfile image: zitare-backend:local container_name: mana-app-zitare-backend restart: always depends_on: mana-auth: condition: service_healthy environment: NODE_ENV: production PORT: 3007 DATABASE_URL: postgresql://postgres:${POSTGRES_PASSWORD:-mana123}@postgres:5432/zitare DB_HOST: postgres DB_PORT: 5432 DB_USER: postgres MANA_CORE_AUTH_URL: http://mana-auth:3001 CORS_ORIGINS: https://zitare.mana.how,https://mana.how ADMIN_SERVICE_KEY: ${MANA_CORE_SERVICE_KEY} GLITCHTIP_DSN: https://53b871913d864628a8c7cb97b3f69e06@glitchtip.mana.how/8 ports: - "3007:3007" healthcheck: test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://127.0.0.1:3007/health"] interval: 30s timeout: 10s retries: 3 start_period: 40s mukke-backend: build: context: . dockerfile: apps/mukke/apps/backend/Dockerfile image: mukke-backend:local container_name: mana-app-mukke-backend restart: always depends_on: mana-auth: condition: service_healthy environment: NODE_ENV: production PORT: 3010 DATABASE_URL: postgresql://postgres:${POSTGRES_PASSWORD:-mana123}@postgres:5432/mukke MANA_CORE_AUTH_URL: http://mana-auth:3001 CORS_ORIGINS: https://mukke.mana.how,https://mana.how S3_ENDPOINT: http://minio:9000 S3_PUBLIC_ENDPOINT: https://minio.mana.how S3_REGION: us-east-1 S3_ACCESS_KEY: ${MINIO_ACCESS_KEY:-minioadmin} S3_SECRET_KEY: ${MINIO_SECRET_KEY:-minioadmin} S3_BUCKET: mukke-storage RUN_DB_PUSH: "true" GLITCHTIP_DSN: https://9f792851d49d4f018625f45855f0a030@glitchtip.mana.how/9 ports: - "3010:3010" healthcheck: test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://127.0.0.1:3010/health"] interval: 30s timeout: 10s retries: 3 start_period: 40s planta-backend: build: context: . dockerfile: apps/planta/apps/backend/Dockerfile image: planta-backend:local container_name: mana-app-planta-backend restart: always depends_on: mana-auth: condition: service_healthy minio: condition: service_healthy environment: NODE_ENV: production PORT: 3022 DATABASE_URL: postgresql://postgres:${POSTGRES_PASSWORD:-mana123}@postgres:5432/planta DB_HOST: postgres DB_PORT: 5432 DB_USER: postgres MANA_CORE_AUTH_URL: http://mana-auth:3001 CORS_ORIGINS: https://planta.mana.how,https://mana.how GOOGLE_GEMINI_API_KEY: ${GOOGLE_GEMINI_API_KEY} S3_ENDPOINT: http://minio:9000 S3_PUBLIC_ENDPOINT: https://minio.mana.how S3_REGION: us-east-1 S3_ACCESS_KEY: ${MINIO_ACCESS_KEY:-minioadmin} S3_SECRET_KEY: ${MINIO_SECRET_KEY:-minioadmin} S3_BUCKET: planta-storage GLITCHTIP_DSN: https://646a927be6c54c989a75c145247d89f9@glitchtip.mana.how/13 ports: - "3022:3022" healthcheck: test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://127.0.0.1:3022/api/v1/health"] interval: 30s timeout: 10s retries: 3 start_period: 40s # ============================================ # Tier 4: Matrix Stack (Ports 4000-4099) # ============================================ synapse: image: matrixdotorg/synapse:latest container_name: mana-matrix-synapse restart: always depends_on: postgres: condition: service_healthy environment: SYNAPSE_CONFIG_PATH: /config/homeserver.yaml TZ: Europe/Berlin SYNAPSE_DB_PASSWORD: ${SYNAPSE_DB_PASSWORD:-synapse-secure-password} SYNAPSE_PASSWORD_PEPPER: ${SYNAPSE_PASSWORD_PEPPER:-change-me-pepper} SYNAPSE_FORM_SECRET: ${SYNAPSE_FORM_SECRET:-change-me-form-secret} SYNAPSE_MACAROON_SECRET: ${SYNAPSE_MACAROON_SECRET:-change-me-macaroon-secret} SYNAPSE_REGISTRATION_SECRET: ${SYNAPSE_REGISTRATION_SECRET:-change-me-registration-secret} SYNAPSE_OIDC_CLIENT_SECRET: ${SYNAPSE_OIDC_CLIENT_SECRET} volumes: - ./docker/matrix/homeserver.yaml:/config/homeserver.yaml:ro - ./docker/matrix/log.config.yaml:/config/log.config.yaml:ro - ./docker/matrix/appservices:/appservices:ro - ./docker/matrix/data:/data ports: - "4000:8008" - "9002:9002" # Metrics healthcheck: test: ["CMD", "curl", "-fSs", "http://localhost:8008/health"] interval: 30s timeout: 10s retries: 3 start_period: 60s element-web: image: vectorim/element-web:latest container_name: mana-matrix-element restart: always depends_on: synapse: condition: service_healthy volumes: - ./docker/matrix/element-config.json:/app/config.json:ro ports: - "4080:80" healthcheck: test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://localhost:80/"] interval: 30s timeout: 10s retries: 3 matrix-web: build: context: . dockerfile: apps/matrix/apps/web/Dockerfile image: matrix-web:latest container_name: mana-matrix-web restart: always depends_on: synapse: condition: service_healthy environment: NODE_ENV: production PORT: 5180 PUBLIC_MANA_CORE_AUTH_URL: https://auth.mana.how ports: - "4090:5180" healthcheck: test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://127.0.0.1:5180/health"] interval: 30s timeout: 10s retries: 3 # Matrix Bots (Ports 4010-4029) matrix-mana-bot: build: context: . dockerfile: services/matrix-mana-bot/Dockerfile image: matrix-mana-bot:local platform: linux/arm64 container_name: mana-matrix-bot-mana restart: always depends_on: synapse: condition: service_healthy environment: NODE_ENV: production PORT: 4010 TZ: Europe/Berlin MATRIX_HOMESERVER_URL: http://synapse:8008 MATRIX_ACCESS_TOKEN: ${MATRIX_MANA_BOT_TOKEN} MATRIX_ALLOWED_ROOMS: ${MATRIX_MANA_BOT_ROOMS:-} MATRIX_STORAGE_PATH: /app/data/mana-bot-storage.json OLLAMA_URL: http://host.docker.internal:11434 OLLAMA_MODEL: ${OLLAMA_MODEL:-gemma3:4b} OLLAMA_TIMEOUT: 120000 CLOCK_API_URL: http://mana-matrix-bot-clock:4018/api/v1 TODO_STORAGE_PATH: /app/data/todos.json CALENDAR_STORAGE_PATH: /app/data/calendar.json STT_URL: http://host.docker.internal:3026 STT_API_KEY: ${STT_INTERNAL_API_KEY:-} TTS_URL: http://host.docker.internal:3022 volumes: - matrix_bots_data:/app/data ports: - "4010:4010" healthcheck: test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://127.0.0.1:4010/health"] interval: 30s timeout: 10s retries: 3 start_period: 40s matrix-ollama-bot: image: ghcr.io/memo-2023/matrix-ollama-bot:latest platform: linux/amd64 container_name: mana-matrix-bot-ollama restart: always depends_on: synapse: condition: service_healthy environment: NODE_ENV: production PORT: 4011 TZ: Europe/Berlin MATRIX_HOMESERVER_URL: http://synapse:8008 MATRIX_ACCESS_TOKEN: ${MATRIX_OLLAMA_BOT_TOKEN} MATRIX_ALLOWED_ROOMS: ${MATRIX_OLLAMA_BOT_ROOMS:-} OLLAMA_URL: http://host.docker.internal:11434 OLLAMA_MODEL: ${OLLAMA_MODEL:-gemma3:4b} OLLAMA_TIMEOUT: 120000 volumes: - matrix_bots_data:/app/data ports: - "4011:4011" healthcheck: test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://127.0.0.1:4011/health"] interval: 30s timeout: 10s retries: 3 start_period: 40s matrix-stats-bot: image: matrix-stats-bot:local #platform: linux/amd64 container_name: mana-matrix-bot-stats restart: always depends_on: synapse: condition: service_healthy victoriametrics: condition: service_healthy redis: condition: service_healthy environment: NODE_ENV: production PORT: 4012 TZ: Europe/Berlin # Redis for session storage (Matrix-SSO-Link) REDIS_HOST: redis REDIS_PASSWORD: ${REDIS_PASSWORD:-redis123} # Mana Core Auth for Matrix-SSO-Link auto-login MANA_CORE_AUTH_URL: http://mana-auth:3001 MANA_CORE_SERVICE_KEY: ${MANA_CORE_SERVICE_KEY} MATRIX_HOMESERVER_URL: http://synapse:8008 MATRIX_ACCESS_TOKEN: ${MATRIX_STATS_BOT_TOKEN} MATRIX_REPORT_ROOM_ID: ${MATRIX_STATS_REPORT_ROOM:-} UMAMI_API_URL: http://umami:3000 UMAMI_USERNAME: ${UMAMI_USERNAME:-admin} UMAMI_PASSWORD: ${UMAMI_PASSWORD} PROMETHEUS_URL: http://victoriametrics:9090 DATABASE_URL: postgresql://postgres:${POSTGRES_PASSWORD:-mana123}@postgres:5432/mana_auth volumes: - matrix_bots_data:/app/data ports: - "4012:4012" healthcheck: test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://127.0.0.1:4012/health"] interval: 30s timeout: 10s retries: 3 start_period: 40s matrix-project-doc-bot: image: ghcr.io/memo-2023/matrix-project-doc-bot:latest platform: linux/amd64 container_name: mana-matrix-bot-projectdoc restart: always depends_on: synapse: condition: service_healthy environment: NODE_ENV: production PORT: 4013 TZ: Europe/Berlin MATRIX_HOMESERVER_URL: http://synapse:8008 MATRIX_ACCESS_TOKEN: ${MATRIX_PROJECT_DOC_BOT_TOKEN} MATRIX_ALLOWED_USERS: ${MATRIX_PROJECT_DOC_ALLOWED_USERS:-} DATABASE_URL: postgresql://postgres:${POSTGRES_PASSWORD:-mana123}@postgres:5432/project_doc_bot S3_ENDPOINT: http://minio:9000 S3_REGION: us-east-1 S3_ACCESS_KEY: ${MINIO_ACCESS_KEY:-minioadmin} S3_SECRET_KEY: ${MINIO_SECRET_KEY:-minioadmin} S3_BUCKET: project-doc-bot OPENAI_API_KEY: ${OPENAI_API_KEY:-} OPENAI_MODEL: gpt-4o-mini volumes: - matrix_bots_data:/app/data ports: - "4013:4013" healthcheck: test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://127.0.0.1:4013/health"] interval: 30s timeout: 10s retries: 3 start_period: 40s matrix-todo-bot: image: matrix-todo-bot:local build: context: . dockerfile: services/matrix-todo-bot/Dockerfile platform: linux/amd64 container_name: mana-matrix-bot-todo restart: always depends_on: synapse: condition: service_healthy todo-backend: condition: service_healthy environment: NODE_ENV: production PORT: 4014 TZ: Europe/Berlin REDIS_HOST: redis REDIS_PASSWORD: ${REDIS_PASSWORD:-redis123} MANA_CORE_AUTH_URL: http://mana-auth:3001 MANA_CORE_SERVICE_KEY: ${MANA_CORE_SERVICE_KEY} TODO_BACKEND_URL: http://todo-backend:3031 MATRIX_HOMESERVER_URL: http://synapse:8008 MATRIX_ACCESS_TOKEN: ${MATRIX_TODO_BOT_TOKEN} MATRIX_ALLOWED_ROOMS: ${MATRIX_TODO_BOT_ROOMS:-} volumes: - matrix_bots_data:/app/data ports: - "4014:4014" healthcheck: test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://127.0.0.1:4014/health"] interval: 30s timeout: 10s retries: 3 start_period: 40s matrix-calendar-bot: image: matrix-calendar-bot:local pull_policy: never platform: linux/amd64 container_name: mana-matrix-bot-calendar restart: always depends_on: synapse: condition: service_healthy calendar-backend: condition: service_healthy environment: NODE_ENV: production PORT: 4015 TZ: Europe/Berlin REDIS_HOST: redis REDIS_PASSWORD: ${REDIS_PASSWORD:-redis123} MANA_CORE_AUTH_URL: http://mana-auth:3001 MANA_CORE_SERVICE_KEY: ${MANA_CORE_SERVICE_KEY} CALENDAR_BACKEND_URL: http://calendar-backend:3032 MATRIX_HOMESERVER_URL: http://synapse:8008 MATRIX_ACCESS_TOKEN: ${MATRIX_CALENDAR_BOT_TOKEN} MATRIX_ALLOWED_ROOMS: ${MATRIX_CALENDAR_BOT_ROOMS:-} volumes: - matrix_bots_data:/app/data ports: - "4015:4015" healthcheck: test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://127.0.0.1:4015/health"] interval: 30s timeout: 10s retries: 3 start_period: 40s matrix-nutriphi-bot: image: ghcr.io/memo-2023/matrix-nutriphi-bot:latest platform: linux/amd64 container_name: mana-matrix-bot-nutriphi restart: always depends_on: synapse: condition: service_healthy mana-media: condition: service_healthy environment: NODE_ENV: production PORT: 4016 TZ: Europe/Berlin REDIS_HOST: redis REDIS_PASSWORD: ${REDIS_PASSWORD:-redis123} MANA_CORE_SERVICE_KEY: ${MANA_CORE_SERVICE_KEY} MANA_CORE_AUTH_URL: http://mana-auth:3001 MATRIX_HOMESERVER_URL: http://synapse:8008 MATRIX_ACCESS_TOKEN: ${MATRIX_NUTRIPHI_BOT_TOKEN} MATRIX_ALLOWED_ROOMS: ${MATRIX_NUTRIPHI_BOT_ROOMS:-} NUTRIPHI_BACKEND_URL: http://nutriphi-backend:3037 MANA_MEDIA_URL: http://mana-media:3015 volumes: - matrix_bots_data:/app/data ports: - "4016:4016" healthcheck: test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://127.0.0.1:4016/health"] interval: 30s timeout: 10s retries: 3 start_period: 40s matrix-zitare-bot: image: ghcr.io/memo-2023/matrix-zitare-bot:latest platform: linux/amd64 container_name: mana-matrix-bot-zitare restart: always depends_on: synapse: condition: service_healthy zitare-backend: condition: service_healthy environment: NODE_ENV: production PORT: 4017 TZ: Europe/Berlin MATRIX_HOMESERVER_URL: http://synapse:8008 MATRIX_ACCESS_TOKEN: ${MATRIX_ZITARE_BOT_TOKEN} MATRIX_ALLOWED_ROOMS: ${MATRIX_ZITARE_BOT_ROOMS:-} ZITARE_BACKEND_URL: http://zitare-backend:3007 MANA_CORE_AUTH_URL: http://mana-auth:3001 volumes: - matrix_bots_data:/app/data ports: - "4017:4017" healthcheck: test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://127.0.0.1:4017/health"] interval: 30s timeout: 10s retries: 3 start_period: 40s matrix-clock-bot: build: context: . dockerfile: services/matrix-clock-bot/Dockerfile image: matrix-clock-bot:local container_name: mana-matrix-bot-clock restart: always depends_on: synapse: condition: service_healthy mana-auth: condition: service_healthy redis: condition: service_healthy environment: NODE_ENV: production PORT: 4018 TZ: Europe/Berlin MATRIX_HOMESERVER_URL: http://synapse:8008 MATRIX_ACCESS_TOKEN: ${MATRIX_CLOCK_BOT_TOKEN} MATRIX_ALLOWED_ROOMS: ${MATRIX_CLOCK_BOT_ROOMS:-} CLOCK_API_URL: http://clock-backend:3033/api/v1 STT_URL: http://host.docker.internal:3026 STT_API_KEY: ${STT_INTERNAL_API_KEY:-} MANA_CORE_AUTH_URL: http://mana-core-auth:3001 MANA_CORE_SERVICE_KEY: ${MANA_CORE_SERVICE_KEY} REDIS_HOST: redis REDIS_PORT: 6379 REDIS_PASSWORD: ${REDIS_PASSWORD:-redis123} WIDGET_PUBLIC_URL: ${CLOCK_BOT_WIDGET_URL:-https://clock-bot.mana.how/widget} volumes: - matrix_bots_data:/app/data ports: - "4018:4018" healthcheck: test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://127.0.0.1:4018/health"] interval: 30s timeout: 10s retries: 3 start_period: 40s matrix-tts-bot: build: context: . dockerfile: services/matrix-tts-bot/Dockerfile image: matrix-tts-bot:local platform: linux/amd64 container_name: mana-matrix-bot-tts restart: always depends_on: synapse: condition: service_healthy environment: NODE_ENV: production PORT: 4019 TZ: Europe/Berlin MATRIX_HOMESERVER_URL: http://synapse:8008 MATRIX_ACCESS_TOKEN: ${MATRIX_TTS_BOT_TOKEN} MATRIX_ALLOWED_ROOMS: ${MATRIX_TTS_BOT_ROOMS:-} TTS_URL: http://host.docker.internal:3022 TTS_API_KEY: ${TTS_INTERNAL_API_KEY:-} DEFAULT_VOICE: de_kerstin DEFAULT_SPEED: 1.0 MAX_TEXT_LENGTH: 500 volumes: - matrix_bots_data:/app/data ports: - "4019:4019" healthcheck: test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://127.0.0.1:4019/health"] interval: 30s timeout: 10s retries: 3 start_period: 40s matrix-stt-bot: build: context: . dockerfile: services/matrix-stt-bot/Dockerfile image: matrix-stt-bot:local platform: linux/amd64 container_name: mana-matrix-bot-stt restart: always depends_on: synapse: condition: service_healthy environment: NODE_ENV: production PORT: 4021 TZ: Europe/Berlin MATRIX_HOMESERVER_URL: http://synapse:8008 MATRIX_ACCESS_TOKEN: ${MATRIX_STT_BOT_TOKEN} MATRIX_ALLOWED_ROOMS: ${MATRIX_STT_BOT_ROOMS:-} STT_URL: http://host.docker.internal:3026 STT_API_KEY: ${STT_INTERNAL_API_KEY:-} DEFAULT_LANGUAGE: de DEFAULT_MODEL: whisper volumes: - matrix_bots_data:/app/data ports: - "4021:4021" healthcheck: test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://127.0.0.1:4021/health"] interval: 30s timeout: 10s retries: 3 start_period: 40s matrix-onboarding-bot: build: context: . dockerfile: services/matrix-onboarding-bot/Dockerfile image: matrix-onboarding-bot:local container_name: mana-matrix-bot-onboarding restart: always depends_on: synapse: condition: service_healthy mana-auth: condition: service_healthy redis: condition: service_healthy environment: NODE_ENV: production PORT: 4020 TZ: Europe/Berlin MATRIX_HOMESERVER_URL: http://synapse:8008 MATRIX_ACCESS_TOKEN: ${MATRIX_ONBOARDING_BOT_TOKEN} MATRIX_ALLOWED_ROOMS: ${MATRIX_ONBOARDING_BOT_ROOMS:-} MANA_CORE_AUTH_URL: http://mana-auth:3001 MANA_CORE_SERVICE_KEY: ${MANA_CORE_SERVICE_KEY} REDIS_HOST: redis REDIS_PORT: 6379 REDIS_PASSWORD: ${REDIS_PASSWORD:-redis123} volumes: - matrix_bots_data:/app/data ports: - "4020:4020" healthcheck: test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://127.0.0.1:4020/health"] interval: 30s timeout: 10s retries: 3 start_period: 40s matrix-planta-bot: build: context: . dockerfile: services/matrix-planta-bot/Dockerfile image: matrix-planta-bot:local container_name: mana-matrix-bot-planta restart: always depends_on: synapse: condition: service_healthy mana-auth: condition: service_healthy redis: condition: service_healthy planta-backend: condition: service_healthy environment: NODE_ENV: production PORT: 4022 TZ: Europe/Berlin MATRIX_HOMESERVER_URL: http://synapse:8008 MATRIX_ACCESS_TOKEN: ${MATRIX_PLANTA_BOT_TOKEN} MATRIX_ALLOWED_ROOMS: ${MATRIX_PLANTA_BOT_ROOMS:-} PLANTA_BACKEND_URL: http://planta-backend:3022 PLANTA_API_PREFIX: /api MANA_CORE_AUTH_URL: http://mana-auth:3001 REDIS_HOST: redis REDIS_PORT: 6379 REDIS_PASSWORD: ${REDIS_PASSWORD:-redis123} volumes: - matrix_bots_data:/app/data ports: - "4022:4022" healthcheck: test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://127.0.0.1:4022/health"] interval: 30s timeout: 10s retries: 3 start_period: 40s # ============================================ # Tier 5: Web Frontends (Ports 5000-5099) # ============================================ mana-web: build: context: . dockerfile: apps/manacore/apps/web/Dockerfile image: manacore-web:local container_name: mana-app-web restart: always depends_on: mana-auth: condition: service_healthy environment: NODE_ENV: production PORT: 5000 PUBLIC_MANA_CORE_AUTH_URL: http://mana-auth:3001 PUBLIC_MANA_CORE_AUTH_URL_CLIENT: https://auth.mana.how PUBLIC_TODO_API_URL: http://todo-backend:3031 PUBLIC_TODO_API_URL_CLIENT: https://todo-api.mana.how PUBLIC_CALENDAR_API_URL: http://calendar-backend:3032 PUBLIC_CALENDAR_API_URL_CLIENT: https://calendar-api.mana.how PUBLIC_CLOCK_API_URL: http://clock-backend:3033 PUBLIC_CLOCK_API_URL_CLIENT: https://clock-api.mana.how PUBLIC_CONTACTS_API_URL: http://contacts-backend:3034 PUBLIC_CONTACTS_API_URL_CLIENT: https://contacts-api.mana.how ports: - "5000:5000" healthcheck: test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://127.0.0.1:5000/health"] interval: 30s timeout: 10s retries: 3 start_period: 40s chat-web: image: ghcr.io/memo-2023/chat-web:latest container_name: mana-app-chat-web restart: always depends_on: chat-backend: condition: service_healthy environment: NODE_ENV: production PORT: 5010 PUBLIC_BACKEND_URL: http://chat-backend:3030 PUBLIC_MANA_CORE_AUTH_URL: http://mana-auth:3001 PUBLIC_BACKEND_URL_CLIENT: https://chat-api.mana.how PUBLIC_MANA_CORE_AUTH_URL_CLIENT: https://auth.mana.how ports: - "5010:5010" healthcheck: test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://127.0.0.1:5010/health"] interval: 30s timeout: 10s retries: 3 start_period: 40s todo-web: build: context: . dockerfile: apps/todo/apps/web/Dockerfile image: todo-web:local container_name: mana-app-todo-web restart: always depends_on: todo-backend: condition: service_healthy environment: NODE_ENV: production PORT: 5011 PUBLIC_BACKEND_URL: http://todo-backend:3031 PUBLIC_MANA_CORE_AUTH_URL: http://mana-auth:3001 PUBLIC_BACKEND_URL_CLIENT: https://todo-api.mana.how PUBLIC_MANA_CORE_AUTH_URL_CLIENT: https://auth.mana.how ports: - "5011:5011" healthcheck: test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://127.0.0.1:5011/health"] interval: 30s timeout: 10s retries: 3 start_period: 40s zitare-web: build: context: . dockerfile: apps/zitare/apps/web/Dockerfile image: zitare-web:local container_name: mana-app-zitare-web restart: always depends_on: zitare-backend: condition: service_healthy environment: NODE_ENV: production PORT: 5018 PUBLIC_ZITARE_API_URL: http://zitare-backend:3007 PUBLIC_MANA_CORE_AUTH_URL: http://mana-auth:3001 PUBLIC_ZITARE_API_URL_CLIENT: https://zitare-api.mana.how PUBLIC_MANA_CORE_AUTH_URL_CLIENT: https://auth.mana.how ports: - "5018:5018" healthcheck: test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://127.0.0.1:5018/health"] interval: 30s timeout: 10s retries: 3 start_period: 40s calendar-web: build: context: . dockerfile: apps/calendar/apps/web/Dockerfile image: calendar-web:local container_name: mana-app-calendar-web restart: always depends_on: calendar-backend: condition: service_healthy environment: NODE_ENV: production PORT: 5012 PUBLIC_BACKEND_URL: http://calendar-backend:3032 PUBLIC_MANA_CORE_AUTH_URL: http://mana-auth:3001 PUBLIC_BACKEND_URL_CLIENT: https://calendar-api.mana.how PUBLIC_MANA_CORE_AUTH_URL_CLIENT: https://auth.mana.how PUBLIC_TODO_BACKEND_URL: https://todo-api.mana.how PUBLIC_CONTACTS_API_URL: https://contacts-api.mana.how ports: - "5012:5012" healthcheck: test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://127.0.0.1:5012/health"] interval: 30s timeout: 10s retries: 3 start_period: 40s clock-web: image: ghcr.io/memo-2023/clock-web:latest container_name: mana-app-clock-web restart: always depends_on: clock-backend: condition: service_healthy environment: NODE_ENV: production PORT: 5013 PUBLIC_BACKEND_URL: http://clock-backend:3033 PUBLIC_MANA_CORE_AUTH_URL: http://mana-auth:3001 PUBLIC_BACKEND_URL_CLIENT: https://clock-api.mana.how PUBLIC_MANA_CORE_AUTH_URL_CLIENT: https://auth.mana.how ports: - "5013:5013" healthcheck: test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://127.0.0.1:5013/health"] interval: 30s timeout: 10s retries: 3 start_period: 40s contacts-web: build: context: . dockerfile: apps/contacts/apps/web/Dockerfile args: PUBLIC_BACKEND_URL: http://contacts-backend:3034 PUBLIC_MANA_CORE_AUTH_URL: http://mana-auth:3001 image: contacts-web:local container_name: mana-app-contacts-web restart: always depends_on: contacts-backend: condition: service_healthy environment: NODE_ENV: production PORT: 5014 PUBLIC_BACKEND_URL: http://contacts-backend:3034 PUBLIC_MANA_CORE_AUTH_URL: http://mana-auth:3001 PUBLIC_BACKEND_URL_CLIENT: https://contacts-api.mana.how PUBLIC_MANA_CORE_AUTH_URL_CLIENT: https://auth.mana.how PUBLIC_TODO_BACKEND_URL: https://todo-api.mana.how ports: - "5014:5014" healthcheck: test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://127.0.0.1:5014/health"] interval: 30s timeout: 10s retries: 3 start_period: 40s storage-web: build: context: . dockerfile: apps/storage/apps/web/Dockerfile args: PUBLIC_BACKEND_URL: http://storage-backend:3035 PUBLIC_MANA_CORE_AUTH_URL: http://mana-auth:3001 image: storage-web:local container_name: mana-app-storage-web restart: always depends_on: storage-backend: condition: service_healthy environment: NODE_ENV: production PORT: 5015 PUBLIC_BACKEND_URL: http://storage-backend:3035 PUBLIC_MANA_CORE_AUTH_URL: http://mana-auth:3001 PUBLIC_BACKEND_URL_CLIENT: https://storage-api.mana.how PUBLIC_MANA_CORE_AUTH_URL_CLIENT: https://auth.mana.how ports: - "5015:5015" healthcheck: test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://127.0.0.1:5015/health"] interval: 30s timeout: 10s retries: 3 start_period: 40s presi-web: image: ghcr.io/memo-2023/presi-web:latest container_name: mana-app-presi-web restart: always depends_on: presi-backend: condition: service_healthy environment: NODE_ENV: production PORT: 5016 PUBLIC_BACKEND_URL: http://presi-backend:3036 PUBLIC_MANA_CORE_AUTH_URL: http://mana-auth:3001 PUBLIC_BACKEND_URL_CLIENT: https://presi-api.mana.how PUBLIC_MANA_CORE_AUTH_URL_CLIENT: https://auth.mana.how ports: - "5016:5016" healthcheck: test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://127.0.0.1:5016/health"] interval: 30s timeout: 10s retries: 3 start_period: 40s nutriphi-web: image: ghcr.io/memo-2023/nutriphi-web:latest container_name: mana-app-nutriphi-web restart: always depends_on: nutriphi-backend: condition: service_healthy environment: NODE_ENV: production PORT: 5017 PUBLIC_BACKEND_URL: http://nutriphi-backend:3037 PUBLIC_MANA_CORE_AUTH_URL: http://mana-auth:3001 PUBLIC_BACKEND_URL_CLIENT: https://nutriphi-api.mana.how PUBLIC_MANA_CORE_AUTH_URL_CLIENT: https://auth.mana.how ports: - "5017:5017" healthcheck: test: ["CMD", "node", "-e", "const http = require('http'); http.get('http://127.0.0.1:5017/health', (r) => process.exit(r.statusCode === 200 ? 0 : 1)).on('error', () => process.exit(1))"] interval: 30s timeout: 10s retries: 3 start_period: 40s skilltree-web: build: context: . dockerfile: apps/skilltree/apps/web/Dockerfile args: PUBLIC_BACKEND_URL: http://skilltree-backend:3038 PUBLIC_MANA_CORE_AUTH_URL: http://mana-auth:3001 image: skilltree-web:local container_name: mana-app-skilltree-web restart: always depends_on: skilltree-backend: condition: service_healthy environment: NODE_ENV: production PORT: 5020 PUBLIC_BACKEND_URL: http://skilltree-backend:3038 PUBLIC_MANA_CORE_AUTH_URL: http://mana-auth:3001 PUBLIC_BACKEND_URL_CLIENT: https://skilltree-api.mana.how PUBLIC_MANA_CORE_AUTH_URL_CLIENT: https://auth.mana.how ports: - "5020:5020" healthcheck: test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://127.0.0.1:5020/health"] interval: 30s timeout: 10s retries: 3 start_period: 40s photos-web: build: context: . dockerfile: apps/photos/apps/web/Dockerfile args: PUBLIC_BACKEND_URL: http://photos-backend:3039 PUBLIC_MANA_CORE_AUTH_URL: http://mana-auth:3001 PUBLIC_MANA_MEDIA_URL: http://mana-media:3015 image: photos-web:local container_name: mana-app-photos-web restart: always depends_on: photos-backend: condition: service_healthy environment: NODE_ENV: production PORT: 5019 PUBLIC_BACKEND_URL: http://photos-backend:3039 PUBLIC_MANA_CORE_AUTH_URL: http://mana-auth:3001 PUBLIC_MANA_MEDIA_URL: http://mana-media:3015 PUBLIC_BACKEND_URL_CLIENT: https://photos-api.mana.how PUBLIC_MANA_CORE_AUTH_URL_CLIENT: https://auth.mana.how PUBLIC_MANA_MEDIA_URL_CLIENT: https://media.mana.how ports: - "5019:5019" healthcheck: test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://127.0.0.1:5019/health"] interval: 30s timeout: 10s retries: 3 start_period: 40s mukke-web: build: context: . dockerfile: apps/mukke/apps/web/Dockerfile args: PUBLIC_BACKEND_URL: http://mukke-backend:3010 PUBLIC_MANA_CORE_AUTH_URL: http://mana-auth:3001 image: mukke-web:local container_name: mana-app-mukke-web restart: always depends_on: mukke-backend: condition: service_healthy environment: NODE_ENV: production PORT: 5180 PUBLIC_BACKEND_URL: http://mukke-backend:3010 PUBLIC_MANA_CORE_AUTH_URL: http://mana-auth:3001 PUBLIC_BACKEND_URL_CLIENT: https://mukke-api.mana.how PUBLIC_MANA_CORE_AUTH_URL_CLIENT: https://auth.mana.how ports: - "5180:5180" healthcheck: test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://127.0.0.1:5180/health"] interval: 30s timeout: 10s retries: 3 start_period: 40s picture-backend: build: context: . dockerfile: apps/picture/apps/backend/Dockerfile image: picture-backend:local container_name: mana-app-picture-backend restart: always depends_on: mana-auth: condition: service_healthy minio: condition: service_healthy environment: NODE_ENV: production PORT: 3040 DATABASE_URL: postgresql://postgres:${POSTGRES_PASSWORD:-mana123}@postgres:5432/picture DB_HOST: postgres DB_PORT: 5432 DB_USER: postgres MANA_CORE_AUTH_URL: http://mana-auth:3001 REPLICATE_API_TOKEN: ${REPLICATE_API_TOKEN} APP_ID: picture-app MANA_CORE_SERVICE_KEY: ${MANA_CORE_SERVICE_KEY} S3_ENDPOINT: http://minio:9000 S3_PUBLIC_ENDPOINT: https://minio.mana.how S3_REGION: us-east-1 S3_ACCESS_KEY: ${MINIO_ACCESS_KEY:-minioadmin} S3_SECRET_KEY: ${MINIO_SECRET_KEY:-minioadmin} S3_BUCKET: picture-storage CORS_ORIGINS: https://picture.mana.how,https://mana.how ports: - "3040:3040" healthcheck: test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://127.0.0.1:3040/health"] interval: 30s timeout: 10s retries: 3 start_period: 40s picture-web: build: context: . dockerfile: apps/picture/apps/web/Dockerfile args: PUBLIC_BACKEND_URL: http://picture-backend:3040 PUBLIC_MANA_CORE_AUTH_URL: http://mana-auth:3001 image: picture-web:local container_name: mana-app-picture-web restart: always depends_on: picture-backend: condition: service_healthy environment: NODE_ENV: production PORT: 5021 PUBLIC_BACKEND_URL: http://picture-backend:3040 PUBLIC_MANA_CORE_AUTH_URL: http://mana-auth:3001 PUBLIC_BACKEND_URL_CLIENT: https://picture-api.mana.how PUBLIC_MANA_CORE_AUTH_URL_CLIENT: https://auth.mana.how ports: - "5021:5021" healthcheck: test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://127.0.0.1:5021/health"] interval: 30s timeout: 10s retries: 3 start_period: 40s mana-llm: build: context: ./services/mana-llm dockerfile: Dockerfile container_name: mana-service-llm restart: unless-stopped depends_on: redis: condition: service_healthy environment: PORT: 3025 LOG_LEVEL: info OLLAMA_URL: http://host.docker.internal:11434 OLLAMA_DEFAULT_MODEL: gemma3:4b OLLAMA_TIMEOUT: 120 REDIS_URL: redis://redis:6379 OPENROUTER_API_KEY: ${OPENROUTER_API_KEY:-} GROQ_API_KEY: ${GROQ_API_KEY:-} TOGETHER_API_KEY: ${TOGETHER_API_KEY:-} CORS_ORIGINS: https://playground.mana.how,https://mana.how,https://chat.mana.how extra_hosts: - "host.docker.internal:host-gateway" ports: - "3025:3025" healthcheck: test: ["CMD", "python", "-c", "import httpx; httpx.get('http://localhost:3025/health').raise_for_status()"] interval: 30s timeout: 10s retries: 3 start_period: 30s llm-playground: build: context: . dockerfile: services/llm-playground/Dockerfile container_name: mana-app-llm-playground restart: unless-stopped depends_on: mana-auth: condition: service_healthy mana-llm: condition: service_healthy environment: NODE_ENV: production PORT: 5090 PUBLIC_MANA_CORE_AUTH_URL: http://mana-auth:3001 PUBLIC_MANA_CORE_AUTH_URL_CLIENT: https://auth.mana.how PUBLIC_MANA_LLM_URL: http://mana-llm:3025 PUBLIC_MANA_LLM_URL_CLIENT: https://llm.mana.how ports: - "5090:5090" healthcheck: test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://127.0.0.1:5090/health"] interval: 30s timeout: 10s retries: 3 start_period: 10s labels: - "com.centurylinklabs.watchtower.enable=true" # ============================================ # Tier 6: Automation & Workflows (Ports 6000-6099) # ============================================ n8n: image: n8nio/n8n:latest container_name: mana-auto-n8n restart: always depends_on: postgres: condition: service_healthy environment: DB_TYPE: postgresdb DB_POSTGRESDB_HOST: postgres DB_POSTGRESDB_PORT: 5432 DB_POSTGRESDB_DATABASE: n8n DB_POSTGRESDB_USER: postgres DB_POSTGRESDB_PASSWORD: ${POSTGRES_PASSWORD:-mana123} N8N_ENCRYPTION_KEY: ${N8N_ENCRYPTION_KEY:-change-me-n8n-encryption-key} N8N_USER_MANAGEMENT_JWT_SECRET: ${N8N_JWT_SECRET:-change-me-n8n-jwt-secret} N8N_HOST: n8n.mana.how N8N_PROTOCOL: https WEBHOOK_URL: https://n8n.mana.how/ N8N_BASIC_AUTH_ACTIVE: "false" N8N_PORT: 6000 GENERIC_TIMEZONE: Europe/Berlin TZ: Europe/Berlin N8N_DIAGNOSTICS_ENABLED: "false" N8N_VERSION_NOTIFICATIONS_ENABLED: "false" volumes: - n8n_data:/home/node/.n8n ports: - "6000:6000" healthcheck: test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://127.0.0.1:6000/healthz"] interval: 30s timeout: 10s retries: 3 start_period: 40s # ============================================ # Tier 7: Monitoring Dashboards (Ports 8000-8099) # ============================================ grafana: image: grafana/grafana:10.4.1 container_name: mana-mon-grafana restart: always depends_on: victoriametrics: condition: service_healthy environment: GF_SECURITY_ADMIN_USER: admin GF_SECURITY_ADMIN_PASSWORD: ${GRAFANA_PASSWORD:-admin} GF_USERS_ALLOW_SIGN_UP: false GF_AUTH_ANONYMOUS_ENABLED: true GF_AUTH_ANONYMOUS_ORG_ROLE: Viewer GF_SERVER_ROOT_URL: https://grafana.mana.how GF_SERVER_HTTP_PORT: 8000 GF_INSTALL_PLUGINS: yesoreyeram-infinity-datasource GF_DASHBOARDS_DEFAULT_HOME_DASHBOARD_PATH: /var/lib/grafana/dashboards/master-overview.json volumes: - ./docker/grafana/provisioning:/etc/grafana/provisioning:ro - ./docker/grafana/dashboards:/var/lib/grafana/dashboards:ro - grafana_data:/var/lib/grafana ports: - "8000:8000" healthcheck: test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://127.0.0.1:8000/api/health"] interval: 30s timeout: 10s retries: 3 umami: image: ghcr.io/umami-software/umami:postgresql-latest container_name: mana-mon-umami restart: always depends_on: postgres: condition: service_healthy environment: DATABASE_URL: postgresql://postgres:${POSTGRES_PASSWORD:-mana123}@postgres:5432/umami DATABASE_TYPE: postgresql APP_SECRET: ${UMAMI_APP_SECRET:-change-me-umami-secret} DISABLE_TELEMETRY: 1 ports: - "8010:3000" healthcheck: test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://127.0.0.1:3000/api/heartbeat"] interval: 30s timeout: 10s retries: 3 start_period: 40s # ============================================ # Tier 8: Metrics & Exporters (Ports 9000-9199) # ============================================ victoriametrics: image: victoriametrics/victoria-metrics:v1.99.0 container_name: mana-mon-victoria restart: always command: - '-storageDataPath=/storage' - '-retentionPeriod=2y' - '-httpListenAddr=:9090' - '-promscrape.config=/etc/prometheus/prometheus.yml' - '-promscrape.config.strictParse=false' - '-selfScrapeInterval=15s' - '-search.latencyOffset=0s' volumes: - ./docker/prometheus/prometheus.yml:/etc/prometheus/prometheus.yml:ro - ./docker/prometheus/alerts.yml:/etc/prometheus/alerts.yml:ro - victoriametrics_data:/storage ports: - "9090:9090" healthcheck: test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://127.0.0.1:9090/health"] interval: 30s timeout: 10s retries: 3 pushgateway: image: prom/pushgateway:v1.7.0 container_name: mana-mon-pushgateway restart: always ports: - "9091:9091" healthcheck: test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://127.0.0.1:9091/-/healthy"] interval: 30s timeout: 10s retries: 3 cadvisor: image: gcr.io/cadvisor/cadvisor:v0.49.1 container_name: mana-mon-cadvisor restart: always privileged: true volumes: - /:/rootfs:ro - /var/run:/var/run:ro - /sys:/sys:ro - /var/lib/docker/:/var/lib/docker:ro - /dev/disk/:/dev/disk:ro ports: - "9110:8080" healthcheck: test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://127.0.0.1:8080/healthz"] interval: 30s timeout: 10s retries: 3 postgres-exporter: image: prometheuscommunity/postgres-exporter:v0.15.0 container_name: mana-mon-postgres-exporter restart: always depends_on: postgres: condition: service_healthy environment: DATA_SOURCE_NAME: postgresql://postgres:${POSTGRES_PASSWORD:-mana123}@postgres:5432/postgres?sslmode=disable ports: - "9187:9187" redis-exporter: image: oliver006/redis_exporter:v1.58.0 container_name: mana-mon-redis-exporter restart: always depends_on: redis: condition: service_healthy environment: REDIS_ADDR: redis://redis:6379 REDIS_PASSWORD: ${REDIS_PASSWORD:-redis123} ports: - "9121:9121" node-exporter: image: prom/node-exporter:v1.7.0 container_name: mana-mon-node-exporter restart: always # macOS Docker runs in a Linux VM, so we can only monitor the VM's metrics # For full host metrics on macOS, install node_exporter natively command: - '--collector.disable-defaults' - '--collector.cpu' - '--collector.meminfo' - '--collector.loadavg' - '--collector.filesystem' - '--collector.netdev' - '--collector.time' - '--collector.uname' - '--collector.filesystem.mount-points-exclude=^/(sys|proc|dev|host|etc)($$|/)' ports: - "9100:9100" healthcheck: test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://127.0.0.1:9100/metrics"] interval: 30s timeout: 10s retries: 3 # ============================================ # Alerting Stack (Ports 9093-9095) # ============================================ vmalert: image: victoriametrics/vmalert:v1.99.0 container_name: mana-mon-vmalert restart: always depends_on: victoriametrics: condition: service_healthy alertmanager: condition: service_healthy command: - '-datasource.url=http://victoriametrics:9090' - '-notifier.url=http://alertmanager:9093' - '-remoteWrite.url=http://victoriametrics:9090' - '-remoteRead.url=http://victoriametrics:9090' - '-rule=/etc/alerts/*.yml' - '-evaluationInterval=30s' - '-httpListenAddr=:8880' volumes: - ./docker/prometheus/alerts.yml:/etc/alerts/alerts.yml:ro ports: - "8880:8880" healthcheck: test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://127.0.0.1:8880/health"] interval: 30s timeout: 10s retries: 3 alertmanager: image: prom/alertmanager:v0.27.0 container_name: mana-mon-alertmanager restart: always depends_on: alert-notifier: condition: service_healthy command: - '--config.file=/etc/alertmanager/alertmanager.yml' - '--storage.path=/alertmanager' - '--web.listen-address=:9093' volumes: - ./docker/alertmanager/alertmanager.yml:/etc/alertmanager/alertmanager.yml:ro - alertmanager_data:/alertmanager ports: - "9093:9093" healthcheck: test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://127.0.0.1:9093/-/healthy"] interval: 30s timeout: 10s retries: 3 alert-notifier: build: context: ./docker/alert-notifier dockerfile: Dockerfile image: alert-notifier:local container_name: mana-mon-alert-notifier restart: always environment: PORT: 8080 TELEGRAM_BOT_TOKEN: ${TELEGRAM_BOT_TOKEN:-} TELEGRAM_CHAT_ID: ${TELEGRAM_CHAT_ID:-} NTFY_TOPIC: ${NTFY_TOPIC:-} ports: - "9095:8080" healthcheck: test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://127.0.0.1:8080/health"] interval: 30s timeout: 5s retries: 3 start_period: 5s # ============================================ # Auto-Update (Watchtower) # ============================================ watchtower: image: nickfedor/watchtower:latest container_name: mana-auto-watchtower restart: always volumes: - /var/run/docker.sock:/var/run/docker.sock environment: TZ: Europe/Berlin DOCKER_API_VERSION: 1.45 WATCHTOWER_POLL_INTERVAL: 300 WATCHTOWER_CLEANUP: "true" WATCHTOWER_INCLUDE_STOPPED: "false" # Notifications disabled - configure Matrix if needed # ============================================ # Volumes (Naming: mana-{service}-data) # ============================================ # ============================================ # GlitchTip Error Tracking (Sentry-compatible) # ============================================ glitchtip: image: glitchtip/glitchtip:latest container_name: mana-mon-glitchtip restart: always environment: DATABASE_URL: postgres://postgres:${POSTGRES_PASSWORD:-mana123}@postgres:5432/glitchtip REDIS_URL: redis://:${REDIS_PASSWORD:-redis123}@redis:6379/1 SECRET_KEY: ${GLITCHTIP_SECRET_KEY:-change-me-in-production} PORT: "8020" GLITCHTIP_DOMAIN: https://glitchtip.mana.how DEFAULT_FROM_EMAIL: glitchtip@mana.how CELERY_WORKER_AUTOSCALE: "1,3" ENABLE_USER_REGISTRATION: "true" ports: - "8020:8020" depends_on: postgres: condition: service_healthy redis: condition: service_healthy healthcheck: test: ["CMD", "python3", "-c", "import urllib.request; urllib.request.urlopen('http://localhost:8020/_health/')"] interval: 30s timeout: 10s retries: 3 glitchtip-worker: image: glitchtip/glitchtip:latest container_name: mana-mon-glitchtip-worker restart: always command: ./bin/run-celery-with-beat.sh environment: DATABASE_URL: postgres://postgres:${POSTGRES_PASSWORD:-mana123}@postgres:5432/glitchtip REDIS_URL: redis://:${REDIS_PASSWORD:-redis123}@redis:6379/1 SECRET_KEY: ${GLITCHTIP_SECRET_KEY:-change-me-in-production} GLITCHTIP_DOMAIN: https://glitchtip.mana.how CELERY_WORKER_AUTOSCALE: "1,3" depends_on: postgres: condition: service_healthy redis: condition: service_healthy # ============================================ # Games # ============================================ whopixels: build: context: . dockerfile: games/whopixels/Dockerfile container_name: mana-game-whopixels restart: unless-stopped environment: PORT: 5100 AZURE_OPENAI_API_KEY: ${AZURE_OPENAI_API_KEY:-} AZURE_OPENAI_ENDPOINT: ${AZURE_OPENAI_ENDPOINT:-} AZURE_OPENAI_DEPLOYMENT: ${AZURE_OPENAI_DEPLOYMENT:-} AZURE_OPENAI_API_VERSION: ${AZURE_OPENAI_API_VERSION:-} ports: - "5100:5100" healthcheck: test: ["CMD", "wget", "-q", "--spider", "http://localhost:5100/"] interval: 30s timeout: 10s retries: 3 volumes: redis_data: name: mana-redis-data victoriametrics_data: name: mana-victoria-data alertmanager_data: name: mana-alertmanager-data grafana_data: name: mana-grafana-data analytics_data: name: mana-analytics-data n8n_data: name: mana-n8n-data matrix_bots_data: name: mana-matrix-bots-data