# Coolify Docker Compose deployment for fleet-platform. # # Three services from one image, selected by APP_ROLE: # gateway — HTTP: push receivers + dashboard read API + JWT issuance (exposes 8000) # worker — LISTEN parser → projectors # cron — APScheduler: polled ingest, SLO measurement, contract checker # # Coolify-specific notes: # - Domain for `gateway` (api.rahamafresh.com) is configured via the # Coolify UI → Application → Settings → Domains. Coolify generates the # Traefik labels automatically; don't add them here. # - All env values live in Coolify's Environment Variables panel. # Compose only references them with ${VAR_NAME}. # - All three services PULL the same CI-built image from the Forgejo # registry (repo.rahamafresh.com/fleet-platform). Coolify no longer builds # from source here. REQUIRES: (1) a registry credential for # repo.rahamafresh.com configured in Coolify so it can pull, and (2) the # Forgejo build-push CI to have finished pushing :latest for this commit # BEFORE you Redeploy — otherwise Coolify pulls the previous :latest. # - `coolify` network is created by Coolify; we attach so containers can # reach the TimescaleDB by service name. # The TimescaleDB this app talks to lives in another Coolify project # (its compose network is `bo3nov2ija7g8wn9b1g2paxs`). The DB container # has the alias `timescale_db` ONLY on that network, so we attach all # three services to it as an external network — that's what makes the # DATABASE_URL `postgresql://...@timescale_db:5432/fleet_platform` work. # # If/when the DB project is re-created with a different network UUID, # update the name here OR migrate the DB onto the shared `coolify` net. networks: db_project: name: bo3nov2ija7g8wn9b1g2paxs external: true # Traefik runs on `coolify`. The gateway must join it so Host(`api.rahamafresh.com`) # actually resolves to a reachable IP; without it Traefik picks the wrong # interface and times out at 30s → intermittent 504s in the browser. coolify_shared: name: coolify external: true services: gateway: # Pull the CI-built image (Forgejo build-push bakes APP_GIT_SHA=github.sha) # instead of building from source, so /health reports the real commit. # Override FLEET_IMAGE in Coolify to pin/rollback to a specific :. image: ${FLEET_IMAGE:-repo.rahamafresh.com/fleet-platform:latest} pull_policy: always restart: unless-stopped networks: - default - db_project - coolify_shared environment: APP_ROLE: gateway APP_MODE: prod APP_LOG_LEVEL: INFO DATABASE_URL: ${DATABASE_URL} JWT_SECRET: ${JWT_SECRET} JWT_ACCESS_TTL_MIN: ${JWT_ACCESS_TTL_MIN:-15} JWT_REFRESH_TTL_DAYS: ${JWT_REFRESH_TTL_DAYS:-30} TRACKSOLID_API_BASE_URL: ${TRACKSOLID_API_BASE_URL} TRACKSOLID_PUSH_TOKEN: ${TRACKSOLID_PUSH_TOKEN} NOMINATIM_BASE_URL: ${NOMINATIM_BASE_URL:-} MAPBOX_TOKEN: ${MAPBOX_TOKEN:-} expose: - "8000" healthcheck: test: ["CMD", "curl", "-fsS", "http://127.0.0.1:8000/health/gateway"] interval: 15s timeout: 3s retries: 3 start_period: 10s worker: image: ${FLEET_IMAGE:-repo.rahamafresh.com/fleet-platform:latest} pull_policy: always restart: unless-stopped depends_on: gateway: condition: service_started networks: - default - db_project environment: APP_ROLE: worker APP_MODE: prod APP_LOG_LEVEL: INFO DATABASE_URL: ${DATABASE_URL} JWT_SECRET: ${JWT_SECRET} TRACKSOLID_API_BASE_URL: ${TRACKSOLID_API_BASE_URL} TRACKSOLID_PUSH_TOKEN: ${TRACKSOLID_PUSH_TOKEN} NOMINATIM_BASE_URL: ${NOMINATIM_BASE_URL:-} healthcheck: test: ["CMD", "curl", "-fsS", "http://127.0.0.1:8000/health/worker"] interval: 15s timeout: 3s retries: 3 start_period: 10s cron: image: ${FLEET_IMAGE:-repo.rahamafresh.com/fleet-platform:latest} pull_policy: always restart: unless-stopped depends_on: gateway: condition: service_started networks: - default - db_project environment: APP_ROLE: cron APP_MODE: prod APP_LOG_LEVEL: INFO DATABASE_URL: ${DATABASE_URL} JWT_SECRET: ${JWT_SECRET} TRACKSOLID_API_BASE_URL: ${TRACKSOLID_API_BASE_URL} TRACKSOLID_PUSH_TOKEN: ${TRACKSOLID_PUSH_TOKEN} TRACKSOLID_APP_KEY: ${TRACKSOLID_APP_KEY} TRACKSOLID_APP_SECRET: ${TRACKSOLID_APP_SECRET} TRACKSOLID_USER_ID: ${TRACKSOLID_USER_ID} TRACKSOLID_PWD_MD5: ${TRACKSOLID_PWD_MD5} TRACKSOLID_TARGETS: ${TRACKSOLID_TARGETS} TRACKSOLID_POLL_INTERVAL_SEC: ${TRACKSOLID_POLL_INTERVAL_SEC:-60} TRACKSOLID_STALE_POLL_INTERVAL_SEC: ${TRACKSOLID_STALE_POLL_INTERVAL_SEC:-600} TRACKSOLID_STALE_AFTER_SEC: ${TRACKSOLID_STALE_AFTER_SEC:-1800} NOMINATIM_BASE_URL: ${NOMINATIM_BASE_URL:-} GEOCODER_TICK_SEC: ${GEOCODER_TICK_SEC:-30} healthcheck: test: ["CMD", "curl", "-fsS", "http://127.0.0.1:8000/health/cron"] interval: 15s timeout: 3s retries: 3 start_period: 10s