{"repo": "bbarnes4318/hoppwhistle", "files": {"infra/docker/docker-compose.yml": {"4f02c8aa6d735e608430d9a165dc54763ea5534a": {"t": 1786068533.3504794, "n": 11479, "h": "4d31477e999b78bf", "c": "version: '3.8'\n\nservices:\n # ===========================================\n # REDIS - Message Queue & Caching\n # ===========================================\n redis:\n image: redis:7-alpine\n ports:\n - '6379:6379'\n volumes:\n - redis_data:/data\n healthcheck:\n test: ['CMD', 'redis-cli', 'ping']\n interval: 10s\n timeout: 5s\n retries: 5\n restart: unless-stopped\n\n # ===========================================\n # CLICKHOUSE - Analytics Database\n # ===========================================\n clickhouse:\n image: clickhouse/clickhouse-server:latest\n ports:\n - '8123:8123'\n - '9000:9000'\n volumes:\n - clickhouse_data:/var/lib/clickhouse\n environment:\n - CLICKHOUSE_DB=hopwhistle_analytics\n - CLICKHOUSE_USER=default\n - CLICKHOUSE_PASSWORD=clickhouse_dev\n healthcheck:\n test: ['CMD', 'wget', '--spider', '-q', 'http://localhost:8123/ping']\n interval: 30s\n timeout: 10s\n retries: 3\n restart: unless-stopped\n\n # ===========================================\n # MINIO - S3-Compatible Storage for Recordings\n # ===========================================\n minio:\n image: minio/minio:latest\n ports:\n - '9002:9000'\n - '9001:9001'\n environment:\n - MINIO_ROOT_USER=${MINIO_ROOT_USER:-minioadmin}\n - MINIO_ROOT_PASSWORD=${MINIO_ROOT_PASSWORD:-minioadmin}\n volumes:\n - minio_data:/data\n command: server /data --console-address \":9001\"\n healthcheck:\n test: ['CMD', 'curl', '-f', 'http://localhost:9000/minio/health/live']\n interval: 30s\n timeout: 10s\n retries: 3\n restart: unless-stopped\n\n # ===========================================\n # JAEGER - Distributed Tracing\n # ===========================================\n jaeger:\n image: jaegertracing/all-in-one:latest\n ports:\n - '16686:16686'\n - '14268:14268'\n environment:\n - COLLECTOR_OTLP_ENABLED=true\n restart: unless-stopped\n\n # ===========================================\n # RTPENGINE - Media Proxy for RTP\n # ===========================================\n rtpengine:\n image: drachtio/rtpengine:latest\n privileged: true\n cap_add:\n - NET_ADMIN\n - SYS_NICE\n ports:\n - '22222:22222/udp'\n - '10000-10100:10000-10100/udp'\n environment:\n - LOCAL_IP=${PUBLIC_IP}\n - PORT_MIN=10000\n - PORT_MAX=10100\n - LOG_LEVEL=6\n restart: unless-stopped\n\n # ===========================================\n # FREESWITCH - Telephony Server\n # ===========================================\n freeswitch:\n build:\n context: ../../\n dockerfile: apps/freeswitch/Dockerfile\n args:\n SIGNALWIRE_TOKEN: ${SIGNALWIRE_TOKEN}\n ports:\n - '5062:5060/udp'\n - '5062:5060/tcp'\n - '5080:5080/udp'\n - '5080:5080/tcp'\n - '5070:5070/udp' # Vapi SIP profile\n - '5070:5070/tcp' # Vapi SIP profile\n - '5063:5061/tcp'\n - '8021:8021/tcp'\n - '8082:8082/tcp' # Verto WebSocket (secure)\n - '8083:8083/tcp' # Verto WebSocket (dev)\n - '7443:7443/tcp' # WSS for WebRTC SIP (Call Center)\n # RTP media ports (audio) - MUST be exposed for call audio to work\n - '16384-16484:16384-16484/udp'\n environment:\n # Hardcoded to verify fix\n - FREESWITCH_ESL_PASSWORD=ClueCon\n - API_URL=http://api:3001\n - API_KEY=${API_KEY:-demo-key}\n - S3_ENDPOINT=http://minio:9000\n - S3_BUCKET=${S3_BUCKET:-hopwhistle-recordings}\n - S3_ACCESS_KEY=${S3_ACCESS_KEY:-minioadmin}\n - S3_SECRET_KEY=${S3_SECRET_KEY:-minioadmin}\n - S3_REGION=${S3_REGION:-us-east-1}\n - RECORDINGS_FORMAT=${RECORDINGS_FORMAT:-wav}\n - ENABLE_TLS=${ENABLE_TLS:-false}\n - ENABLE_SRTP=${ENABLE_SRTP:-optional}\n - PUBLIC_IP=${PUBLIC_IP}\n - MEDIA_DOMAIN=${MEDIA_DOMAIN}\n - OUTBOUND_SIP_PROXY=${OUTBOUND_SIP_PROXY}\n - OUTBOUND_SIP_USER=${OUTBOUND_SIP_USER}\n - OUTBOUND_SIP_PASS=${OUTBOUND_SIP_PASS}\n - OUTBOUND_CALLER_ID=${OUTBOUND_CALLER_ID}\n - FRACTEL_DEFAULT_CALLER_ID=${FRACTEL_DEFAULT_CALLER_ID:-${OUTBOUND_CALLER_ID:-12816991120}}\n - SIP_DOMAIN=${SIP_DOMAIN:-freeswitch}\n volumes:\n - freeswitch_recordings:/recordings\n # NOTE: Do NOT mount freeswitch_conf here - config is baked into the image via Dockerfile\n # SSL certs for WSS (WebRTC) on port 7443\n - /etc/letsencrypt:/etc/letsencrypt:ro\n # Writable so entrypoint can generate combined wss.pem from fullchain+privkey\n - /etc/letsencrypt/live/hopwhistle.com:/etc/freeswitch/letsencrypt\n # STIR/SHAKEN ES256 private key for local PASSporT signing (local_shaken.lua)\n - /opt/hopwhistle/252L-20250710.key:/etc/freeswitch/stir-shaken/private.key:ro\n depends_on:\n redis:\n condition: service_healthy\n minio:\n condition: service_healthy\n restart: unless-stopped\n\n # ===========================================\n # KAMAILIO - SIP Proxy\n # ===========================================\n kamailio:\n build:\n context: ../../\n dockerfile: apps/kamailio/Dockerfile\n ports:\n - '5060:5060/udp'\n - '5060:5060/tcp'\n - '5061:5061/tcp'\n environment:\n - PUBLIC_IP=${PUBLIC_IP}\n - FREESWITCH_NODES=freeswitch:5062\n - RTPENGINE_SOCK=udp:rtpengine:22222\n - DB_URL=${KAMAILIO_DB_URL}\n volumes:\n - kamailio_data:/var/run/kamailio\n depends_on:\n - freeswitch\n restart: unless-stopped\n\n # ===========================================\n # API - Backend REST API\n # ===========================================\n api:\n build:\n context: ../../\n dockerfile: apps/api/Dockerfile\n ports:\n - '3001:3001'\n environment:\n - NODE_ENV=production\n - PORT=3001\n - API_KEY=${API_KEY:-demo-key}\n - DATABASE_URL=postgresql://callfabric:callfabric_dev@hopwhistle-postgres-dev:5432/callfabric\n - REDIS_URL=redis://redis:6379\n - CLICKHOUSE_URL=http://clickhouse:8123\n - CLICKHOUSE_USER=default\n - CLICKHOUSE_PASSWORD=clickhouse_dev\n - CLICKHOUSE_DATABASE=hopwhistle_analytics\n - S3_ENDPOINT=http://minio:9000\n - S3_BUCKET=${S3_BUCKET:-hopwhistle-recordings}\n - S3_ACCESS_KEY=${S3_ACCESS_KEY:-minioadmin}\n - S3_SECRET_KEY=${S3_SECRET_KEY:-minioadmin}\n - S3_REGION=${S3_REGION:-us-east-1}\n - JWT_SECRET=${JWT_SECRET:-change-me}\n - SIGNALWIRE_PROJECT_ID=${SIGNALWIRE_PROJECT_ID}\n - SIGNALWIRE_API_TOKEN=${SIGNALWIRE_API_TOKEN}\n - SIGNALWIRE_SPACE=${SIGNALWIRE_SPACE}\n - JAEGER_ENDPOINT=http://jaeger:14268/api/traces\n - ENABLE_TRACING=false\n - DEEPSEEK_API_KEY=${DEEPSEEK_API_KEY}\n - DEEPSEEK_ENDPOINT=${DEEPSEEK_ENDPOINT:-https://api.deepseek.com/chat/completions}\n - DEEPSEEK_MODEL=${DEEPSEEK_MODEL:-deepseek-chat}\n # Anveo Direct Carrier Integration\n - ANVEO_API_KEY=${ANVEO_API_KEY}\n - ANVEO_EMAIL=${ANVEO_EMAIL}\n - ANVEO_SECURE_PHRASE=${ANVEO_SECURE_PHRASE}\n - PUBLIC_IP=${PUBLIC_IP}\n # Vapi AI Voice Integration\n - VAPI_API_KEY=${VAPI_API_KEY}\n - API_PUBLIC_URL=${API_PUBLIC_URL:-https://hopwhistle.com}\n # FronterBot Binding\n - SOCKET_LISTENER_HOST=0.0.0.0\n - SOCKET_LISTENER_PORT=8021\n # TCPA Litigator Validation (Realvalidito)\n - TCPA_API_KEY=${TCPA_API_KEY}\n - TCPA_API_SECRET=${TCPA_API_SECRET}\n # BulkVS Number Provisioning API\n - BULKVS_USERNAME=jimmy@getlifeassurance.com\n - BULKVS_PASSWORD=50e77367256f3bd823f44d13dc1e8d17\n - BULKVS_TRUNK_GROUP=pvn\n # American Amicable carrier-application RPA (values sourced from .env)\n - AMERICAN_AMICABLE_AGENT_ID=${AMERICAN_AMICABLE_AGENT_ID}\n - AMERICAN_AMICABLE_PASSWORD=${AMERICAN_AMICABLE_PASSWORD}\n - AMERICAN_AMICABLE_SIGNATURE_NAME=${AMERICAN_AMICABLE_SIGNATURE_NAME}\n - FIELD_ENCRYPTION_KEY=${FIELD_ENCRYPTION_KEY}\n - PUPPETEER_EXECUTABLE_PATH=${PUPPETEER_EXECUTABLE_PATH:-/usr/bin/chromium-browser}\n depends_on:\n redis:\n condition: service_healthy\n clickhouse:\n condition: service_healthy\n minio:\n condition: service_healthy\n healthcheck:\n test: ['CMD', 'wget', '--spider', '-q', 'http://127.0.0.1:3001/health']\n interval: 30s\n timeout: 10s\n retries: 5\n start_period: 30s\n restart: unless-stopped\n volumes:\n - freeswitch_recordings:/recordings:ro\n\n # ===========================================\n # WORKER - Background Job Processor\n # ===========================================\n worker:\n build:\n context: ../../\n dockerfile: apps/worker/Dockerfile\n environment:\n - NODE_ENV=production\n - DATABASE_URL=postgresql://callfabric:callfabric_dev@hopwhistle-postgres-dev:5432/callfabric\n - REDIS_URL=redis://redis:6379\n - CLICKHOUSE_URL=http://clickhouse:8123\n - CLICKHOUSE_USER=default\n - CLICKHOUSE_PASSWORD=clickhouse_dev\n - CLICKHOUSE_DATABASE=hopwhistle_analytics\n - DEEPSEEK_API_KEY=${DEEPSEEK_API_KEY}\n - DEEPSEEK_ENDPOINT=${DEEPSEEK_ENDPOINT:-https://api.deepseek.com/chat/completions}\n - DEEPSEEK_MODEL=${DEEPSEEK_MODEL:-deepseek-chat}\n - STRIPE_SECRET_KEY=${STRIPE_SECRET_KEY}\n # DIALER / FRONTER CONFIG\n - FREESWITCH_HOST=freeswitch\n - FREESWITCH_ESL_PORT=8021\n # Hardcoded to verify fix\n - FREESWITCH_ESL_PASSWORD=ClueCon\n - OUTBOUND_SIP_PROXY=${OUTBOUND_SIP_PROXY}\n - OUTBOUND_SIP_USER=${OUTBOUND_SIP_USER}\n - OUTBOUND_SIP_PASS=${OUTBOUND_SIP_PASS}\n - MAX_CONCURRENT_CALLS=${MAX_CONCURRENT_CALLS}\n - DIALER_POLL_INTERVAL_MS=${DIALER_POLL_INTERVAL_MS}\n - OUTBOUND_CALLER_ID=${OUTBOUND_CALLER_ID}\n # Worker tells FreeSWITCH to connect to 'api' service hostname\n - SOCKET_LISTENER_HOST=api\n - SOCKET_LISTENER_PORT=8021\n depends_on:\n redis:\n condition: service_healthy\n clickhouse:\n condition: service_healthy\n api:\n condition: service_healthy\n restart: unless-stopped\n\n # ===========================================\n # WEB - Next.js Frontend\n # ===========================================\n web:\n build:\n context: ../../\n dockerfile: apps/web/Dockerfile\n args:\n - NEXT_PUBLIC_API_URL=https://hopwhistle.com\n - NEXT_PUBLIC_WS_URL=wss://hopwhistle.com\n - NEXT_PUBLIC_API_KEY=${API_KEY:-demo-key}\n ports:\n - '3000:3000'\n environment:\n - NODE_ENV=production\n - NEXT_PUBLIC_API_URL=https://hopwhistle.com\n - NEXT_PUBLIC_WS_URL=wss://hopwhistle.com\n - NEXT_PUBLIC_API_KEY=${API_KEY:-demo-key}\n - NEXTAUTH_URL=https://hopwhistle.com\n - NEXTAUTH_SECRET=${NEXTAUTH_SECRET:-change-me}\n - VAPI_API_KEY=${VAPI_API_KEY}\n depends_on:\n api:\n condition: service_healthy\n restart: unless-stopped\n\n # ===========================================\n # TRANSCRIBER - Audio Transcription Service\n # ===========================================\n transcriber:\n build:\n context: ../../\n dockerfile: apps/media/transcriber/Dockerfile\n environment:\n - NODE_ENV=production\n - REDIS_URL=redis://redis:6379\n - DATABASE_URL=postgresql://callfabric:callfabric_dev@hopwhistle-postgres-dev:5432/callfabric\n depends_on:\n redis:\n condition: service_healthy\n restart: unless-stopped\n\nvolumes:\n redis_data:\n clickhouse_data:\n minio_data:\n freeswitch_recordings:\n kamailio_data:\n\nnetworks:\n default:\n driver: bridge\n"}}}}