Files
sase.tr/docker-compose.coolify.yml
Semih Yesilyurt 371aed3645
Some checks failed
QA Gate (P0/P1) / Test affected app (pull_request) Has been cancelled
chore(build): wire VITE_GOOGLE_ADS_* build args for conversion tracking
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-01 18:11:45 +03:00

266 lines
13 KiB
YAML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
services:
api:
build:
context: .
dockerfile: Dockerfile
args:
- VITE_FARO_ENABLED=${VITE_FARO_ENABLED:-false}
- VITE_FARO_COLLECTOR_URL=${VITE_FARO_COLLECTOR_URL:-}
- VITE_POSTHOG_KEY=${VITE_POSTHOG_KEY:-}
- VITE_META_PIXEL_ID=${VITE_META_PIXEL_ID:-}
- VITE_CHATWOOT_BASE_URL=${VITE_CHATWOOT_BASE_URL:-}
- VITE_CHATWOOT_WEBSITE_TOKEN=${VITE_CHATWOOT_WEBSITE_TOKEN:-}
# Sentry browser SDK — gated on DSN presence (unset = skip init).
# VITE_* args must be build-time; runtime env won't reach the bundle.
- VITE_SENTRY_DSN=${VITE_SENTRY_DSN:-}
- VITE_SENTRY_ENVIRONMENT=${VITE_SENTRY_ENVIRONMENT:-production}
- VITE_SENTRY_RELEASE=${VITE_SENTRY_RELEASE:-}
- VITE_GOOGLE_ADS_ID=${VITE_GOOGLE_ADS_ID:-}
- VITE_GOOGLE_ADS_SIGNUP_LABEL=${VITE_GOOGLE_ADS_SIGNUP_LABEL:-}
environment:
- NODE_ENV=production
- PORT=4000
- DATABASE_URL=${DATABASE_URL}
- REDIS_HOST=sase-redis
- REDIS_PORT=6379
- REDIS_PASSWORD=${REDIS_PASSWORD}
- BETTER_AUTH_SECRET=${BETTER_AUTH_SECRET}
- BETTER_AUTH_URL=${BETTER_AUTH_URL}
# Süper Panel ↔ Sase.tr internal admin token (X-Internal-Token header)
- INTERNAL_API_TOKEN=${INTERNAL_API_TOKEN:-}
- INTERNAL_IMPERSONATION_SECRET=${INTERNAL_IMPERSONATION_SECRET:-}
- GOOGLE_CLIENT_ID=${GOOGLE_CLIENT_ID:-}
- GOOGLE_CLIENT_SECRET=${GOOGLE_CLIENT_SECRET:-}
- MINIO_ENDPOINT=http://minio-global:9000
- MINIO_ACCESS_KEY=${MINIO_ACCESS_KEY}
- MINIO_SECRET_KEY=${MINIO_SECRET_KEY}
- MINIO_BUCKET_NAME=${MINIO_BUCKET_NAME:-sase-schemas}
- MINIO_PUBLIC_URL=${MINIO_PUBLIC_URL}
- MINIO_USE_SSL=false
- CORS_ORIGIN=${CORS_ORIGIN}
- STRIPE_SECRET_KEY=${STRIPE_SECRET_KEY:-}
- STRIPE_PUBLISHABLE_KEY=${STRIPE_PUBLISHABLE_KEY:-}
- PL24_BASE_URL=${PL24_BASE_URL:-https://www.partslink24.com}
- PL24_COMPANY_CODE=${PL24_COMPANY_CODE:-}
- PL24_USERNAME=${PL24_USERNAME:-}
- PL24_PASSWORD=${PL24_PASSWORD:-}
- PL24_COMPANY_CODE_2=${PL24_COMPANY_CODE_2:-}
- PL24_USERNAME_2=${PL24_USERNAME_2:-}
- PL24_PASSWORD_2=${PL24_PASSWORD_2:-}
- PL24_PROXY_DE=${PL24_PROXY_DE:-}
- EMEX_USERNAME=${EMEX_USERNAME:-}
- EMEX_PASSWORD=${EMEX_PASSWORD:-}
- EMEX_USE_PROXY=${EMEX_USE_PROXY:-false}
- EMEX_PROXY_HOST=${EMEX_PROXY_HOST:-74.81.81.81}
- EMEX_PROXY_USER=${EMEX_PROXY_USER:-1726bbe361918676d44e}
- EMEX_PROXY_PASS=${EMEX_PROXY_PASS:-f11c7b6128cc86c6}
- PCAT_USE_PROXY=${PCAT_USE_PROXY:-true}
- PCAT_PROXY_HOST=${PCAT_PROXY_HOST:-gw.dataimpulse.com}
- PCAT_PROXY_USER=${PCAT_PROXY_USER:-}
- PCAT_PROXY_PASS=${PCAT_PROXY_PASS:-}
# Vinpin ePER VIN-decode fallback (flag-gated, off by default)
- VINPIN_ENABLED=${VINPIN_ENABLED:-false}
- VINPIN_URL=${VINPIN_URL:-https://login.tr.vinpin.online}
- VINPIN_USER=${VINPIN_USER:-}
- VINPIN_PASS=${VINPIN_PASS:-}
- POSTAL_API_URL=${POSTAL_API_URL:-}
- POSTAL_API_KEY=${POSTAL_API_KEY:-}
- POSTAL_FROM_ADDRESS=${POSTAL_FROM_ADDRESS:-noreply@sase.tr}
- POSTAL_FROM_NAME=${POSTAL_FROM_NAME:-Sase.tr}
# Novu lifecycle e-mail automation (Tailscale-only; sends via Postal)
- NOVU_API_URL=${NOVU_API_URL:-https://api.bildirim.semih.ai}
- NOVU_API_KEY=${NOVU_API_KEY:-}
- APP_PUBLIC_URL=${APP_PUBLIC_URL:-https://sase.tr}
- MAILTRACK_SECRET=${MAILTRACK_SECRET:-}
# PostHog server-side analytics (payments, subscription lifecycle, $revenue).
# Empty key → PostHogService no-ops (server-side analytics disabled).
- POSTHOG_API_KEY=${POSTHOG_API_KEY:-}
# Personal/secure key → LOCAL feature-flag evaluation (source kill switches,
# guarded decode rollout, remote config). Empty → flags fail open (inert).
- POSTHOG_PERSONAL_API_KEY=${POSTHOG_PERSONAL_API_KEY:-}
# "false" on non-prod → evaluate flags but DON'T emit analytics to prod project.
- POSTHOG_CAPTURE_ENABLED=${POSTHOG_CAPTURE_ENABLED:-}
- POSTHOG_HOST=${POSTHOG_HOST:-https://eu.i.posthog.com}
# Meta Conversions API — server-side signup tracking. Empty → CAPI no-ops.
- META_CAPI_PIXEL_ID=${META_CAPI_PIXEL_ID:-}
- META_CAPI_ACCESS_TOKEN=${META_CAPI_ACCESS_TOKEN:-}
- META_CAPI_TEST_EVENT_CODE=${META_CAPI_TEST_EVENT_CODE:-}
- OTEL_ENABLED=${OTEL_ENABLED:-false}
- OTEL_EXPORTER_OTLP_ENDPOINT=${OTEL_EXPORTER_OTLP_ENDPOINT:-}
- OTEL_EXPORTER_OTLP_HEADERS=${OTEL_EXPORTER_OTLP_HEADERS:-}
- OTEL_SERVICE_NAME=${OTEL_SERVICE_NAME:-sase-api}
- OTEL_TRACE_SAMPLE_RATE=${OTEL_TRACE_SAMPLE_RATE:-1.0}
- ML_PREDICTION_ENABLED=${ML_PREDICTION_ENABLED:-false}
# Chatwoot live-chat widget — HMAC secret for verified user identity
- CHATWOOT_HMAC_TOKEN=${CHATWOOT_HMAC_TOKEN:-}
# Local catalog-dump lookup (CategoriesService → PcatSourceDb / EmexSourceDb).
# Defaults off; when CATALOG_SOURCE_DB_ENABLED=true + URLs set, parts fetches
# hit the dump first and only fall through to live upstream on miss.
- CATALOG_SOURCE_DB_ENABLED=${CATALOG_SOURCE_DB_ENABLED:-false}
- PCAT_SOURCE_DB_URL=${PCAT_SOURCE_DB_URL:-}
- EMEX_SOURCE_DB_URL=${EMEX_SOURCE_DB_URL:-}
# Per-source kill switches. pcat default off (dump doesn't cover TR vehicles).
- EMEX_SOURCE_DB_ENABLED=${EMEX_SOURCE_DB_ENABLED:-true}
- PCAT_SOURCE_DB_ENABLED=${PCAT_SOURCE_DB_ENABLED:-false}
# Per-catalog parts-lookup allowlist (comma-separated). Empty → all
# fetchCategoryParts calls return null. See sase-emex-source-db-safety
# memory: catalog-wide bridge had 7-114x noise; only add a catalog once
# its per-vehicle bridge is wired & OEM-verified.
- EMEX_SOURCE_DB_ALLOWED_CATALOGS=${EMEX_SOURCE_DB_ALLOWED_CATALOGS:-}
# P snapshot lookup (db `td`) backing the OEM detail page. Off until
# both vars are set in Coolify; see sase-prod-db-api-access memory.
- P_DB_ENABLED=${P_DB_ENABLED:-false}
- P_DB_URL=${P_DB_URL:-}
# Tedarikçi fiyat geçmişi (takip MySQL, Tailscale 100.82.193.79). Boş →
# part-prices uçları matched:false döner, UI fiyat bölümü çizmez.
- SUPPLIER_PRICE_DB_ENABLED=${SUPPLIER_PRICE_DB_ENABLED:-false}
- SUPPLIER_PRICE_DB_URL=${SUPPLIER_PRICE_DB_URL:-}
# Central Directus CMS (Süper Panel project on Coolify). Prod and staging
# point at the SAME instance so blog content is shared across envs.
# Internal docker-network URL — both stacks join the `coolify` network.
- DIRECTUS_URL=${DIRECTUS_URL:-}
- DIRECTUS_TOKEN=${DIRECTUS_TOKEN:-}
- DIRECTUS_PROJECT=${DIRECTUS_PROJECT:-sase}
# Bearer token for POST /blog/posts/internal (Süper Panel n8n pipeline)
- BLOG_AUTOMATION_TOKEN=${BLOG_AUTOMATION_TOKEN:-}
# Catalog prefetch / backfill tuning (in-process worker lives in THIS api
# container, not worker.js). All empty → compiled-in defaults; set in Coolify
# to ramp without a code change. PL24 rate stays conservative unless rotating
# residential proxies are confirmed (upstream ban risk). See
# sase-coolify-compose-env-injection + sase-catalog-backfill memories.
- CATALOG_BACKFILL_ENABLED=${CATALOG_BACKFILL_ENABLED:-}
- PREFETCH_CONCURRENCY=${PREFETCH_CONCURRENCY:-}
- PREFETCH_RATE_MAX=${PREFETCH_RATE_MAX:-}
- PREFETCH_MAX_DEPTH=${PREFETCH_MAX_DEPTH:-}
- PREFETCH_RATE_PL24=${PREFETCH_RATE_PL24:-}
- PREFETCH_RATE_EMEX=${PREFETCH_RATE_EMEX:-}
- PREFETCH_RATE_PCAT=${PREFETCH_RATE_PCAT:-}
- PREFETCH_PCAT_DELAY_MS=${PREFETCH_PCAT_DELAY_MS:-}
- PREFETCH_PL24_START=${PREFETCH_PL24_START:-}
- PREFETCH_PL24_END=${PREFETCH_PL24_END:-}
- PREFETCH_NORESULT_MAX=${PREFETCH_NORESULT_MAX:-}
- PREFETCH_NORESULT_TTL_DAYS=${PREFETCH_NORESULT_TTL_DAYS:-}
- PREFETCH_COMPLETE_TTL_DAYS=${PREFETCH_COMPLETE_TTL_DAYS:-}
depends_on:
sase-redis:
condition: service_healthy
healthcheck:
test: ["CMD", "wget", "-qO-", "http://127.0.0.1:4000/api/health"]
interval: 15s
timeout: 5s
retries: 5
start_period: 30s
labels:
- "traefik.docker.network=coolify"
expose:
- "4000"
networks:
- default
- coolify
worker:
build:
context: .
dockerfile: Dockerfile
command: ["node", "--enable-source-maps", "apps/api/dist/worker.js"]
environment:
- NODE_ENV=production
- DATABASE_URL=${DATABASE_URL}
- REDIS_HOST=sase-redis
- REDIS_PORT=6379
- REDIS_PASSWORD=${REDIS_PASSWORD}
- MINIO_ENDPOINT=http://minio-global:9000
- MINIO_ACCESS_KEY=${MINIO_ACCESS_KEY}
- MINIO_SECRET_KEY=${MINIO_SECRET_KEY}
- MINIO_BUCKET_NAME=${MINIO_BUCKET_NAME:-sase-schemas}
- MINIO_PUBLIC_URL=${MINIO_PUBLIC_URL}
- MINIO_USE_SSL=false
- PL24_BASE_URL=${PL24_BASE_URL:-https://www.partslink24.com}
- PL24_COMPANY_CODE=${PL24_COMPANY_CODE:-}
- PL24_USERNAME=${PL24_USERNAME:-}
- PL24_PASSWORD=${PL24_PASSWORD:-}
- PL24_COMPANY_CODE_2=${PL24_COMPANY_CODE_2:-}
- PL24_USERNAME_2=${PL24_USERNAME_2:-}
- PL24_PASSWORD_2=${PL24_PASSWORD_2:-}
- PL24_PROXY_DE=${PL24_PROXY_DE:-}
- EMEX_USERNAME=${EMEX_USERNAME:-}
- EMEX_PASSWORD=${EMEX_PASSWORD:-}
- EMEX_USE_PROXY=${EMEX_USE_PROXY:-false}
- EMEX_PROXY_HOST=${EMEX_PROXY_HOST:-74.81.81.81}
- EMEX_PROXY_USER=${EMEX_PROXY_USER:-1726bbe361918676d44e}
- EMEX_PROXY_PASS=${EMEX_PROXY_PASS:-f11c7b6128cc86c6}
- PCAT_USE_PROXY=${PCAT_USE_PROXY:-true}
- PCAT_PROXY_HOST=${PCAT_PROXY_HOST:-gw.dataimpulse.com}
- PCAT_PROXY_USER=${PCAT_PROXY_USER:-}
- PCAT_PROXY_PASS=${PCAT_PROXY_PASS:-}
# Vinpin ePER VIN-decode fallback (worker drives the headless browser)
- VINPIN_ENABLED=${VINPIN_ENABLED:-false}
- VINPIN_URL=${VINPIN_URL:-https://login.tr.vinpin.online}
- VINPIN_USER=${VINPIN_USER:-}
- VINPIN_PASS=${VINPIN_PASS:-}
# Novu lifecycle e-mail automation — the worker fires trial-ending + win-back
- NOVU_API_URL=${NOVU_API_URL:-https://api.bildirim.semih.ai}
- NOVU_API_KEY=${NOVU_API_KEY:-}
- APP_PUBLIC_URL=${APP_PUBLIC_URL:-https://sase.tr}
- MAILTRACK_SECRET=${MAILTRACK_SECRET:-}
# PostHog server-side analytics (payments, subscription lifecycle, $revenue).
# Empty key → PostHogService no-ops (server-side analytics disabled).
- POSTHOG_API_KEY=${POSTHOG_API_KEY:-}
# Personal/secure key → LOCAL feature-flag evaluation (source kill switches,
# guarded decode rollout, remote config). Empty → flags fail open (inert).
- POSTHOG_PERSONAL_API_KEY=${POSTHOG_PERSONAL_API_KEY:-}
# "false" on non-prod → evaluate flags but DON'T emit analytics to prod project.
- POSTHOG_CAPTURE_ENABLED=${POSTHOG_CAPTURE_ENABLED:-}
- POSTHOG_HOST=${POSTHOG_HOST:-https://eu.i.posthog.com}
# Meta Conversions API — server-side signup tracking. Empty → CAPI no-ops.
- META_CAPI_PIXEL_ID=${META_CAPI_PIXEL_ID:-}
- META_CAPI_ACCESS_TOKEN=${META_CAPI_ACCESS_TOKEN:-}
- META_CAPI_TEST_EVENT_CODE=${META_CAPI_TEST_EVENT_CODE:-}
- OTEL_ENABLED=${OTEL_ENABLED:-false}
- OTEL_EXPORTER_OTLP_ENDPOINT=${OTEL_EXPORTER_OTLP_ENDPOINT:-}
- OTEL_EXPORTER_OTLP_HEADERS=${OTEL_EXPORTER_OTLP_HEADERS:-}
- OTEL_SERVICE_NAME=${OTEL_SERVICE_NAME:-sase-worker}
- OTEL_TRACE_SAMPLE_RATE=${OTEL_TRACE_SAMPLE_RATE:-1.0}
# Local catalog-dump lookup (worker drives prefetch which uses CategoriesService).
- CATALOG_SOURCE_DB_ENABLED=${CATALOG_SOURCE_DB_ENABLED:-false}
- PCAT_SOURCE_DB_URL=${PCAT_SOURCE_DB_URL:-}
- EMEX_SOURCE_DB_URL=${EMEX_SOURCE_DB_URL:-}
# Per-source kill switches. pcat default off (dump doesn't cover TR vehicles).
- EMEX_SOURCE_DB_ENABLED=${EMEX_SOURCE_DB_ENABLED:-true}
- PCAT_SOURCE_DB_ENABLED=${PCAT_SOURCE_DB_ENABLED:-false}
# Per-catalog parts-lookup allowlist (comma-separated). Empty → all
# fetchCategoryParts calls return null. See sase-emex-source-db-safety
# memory: catalog-wide bridge had 7-114x noise; only add a catalog once
# its per-vehicle bridge is wired & OEM-verified.
- EMEX_SOURCE_DB_ALLOWED_CATALOGS=${EMEX_SOURCE_DB_ALLOWED_CATALOGS:-}
# Tedarikçi fiyat tazeleme cron'u (19:30 İstanbul) bu env'lerle çalışır;
# boşsa processor sessiz no-op.
- SUPPLIER_PRICE_DB_ENABLED=${SUPPLIER_PRICE_DB_ENABLED:-false}
- SUPPLIER_PRICE_DB_URL=${SUPPLIER_PRICE_DB_URL:-}
depends_on:
sase-redis:
condition: service_healthy
networks:
- default
- coolify
sase-redis:
image: redis:7.4-alpine
command: redis-server --requirepass ${REDIS_PASSWORD}
volumes:
- redis_data:/data
healthcheck:
test: ["CMD", "redis-cli", "-a", "${REDIS_PASSWORD}", "ping"]
interval: 10s
timeout: 5s
retries: 5
networks:
- default
volumes:
redis_data:
networks:
coolify:
external: true