File size: 7,287 Bytes
e327f0d
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
e5f7bb8
 
 
 
 
3b13e05
e327f0d
 
 
 
 
 
 
 
 
 
 
 
 
 
 
e5f7bb8
 
e327f0d
e5f7bb8
 
 
 
 
e327f0d
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
# render.yaml β€” Render Blueprint for arac-hasar-v2
# ----------------------------------------------------------------------
# FREE-TIER PROFILE (active by default in this file).
# For paid pilot/staging blueprint, see scripts/deploy/render-paid.yaml
# (kept as historical reference; legacy contents are inlined at the bottom
# of this file as comments).
#
# Free-tier services (cost = $0):
#   - hasari-api    Render Free web service (512 MB / 0.1 CPU, sleeps after
#                   15 min idle; cold start ~30 s on first request).
#   - hasari-worker Render Free does NOT officially support background
#                   workers. Workaround: run Celery in SOLO mode INSIDE the
#                   web container at boot (see scripts/entrypoint_free.sh).
#                   In production code, the API will also accept
#                   FORCE_SYNC_INFERENCE=1 so /analyze runs inline if the
#                   worker is unreachable (graceful degrade).
#   - DB     -> Supabase Free (external, NOT managed here). 500 MB,
#               pauses after 7 days idle.
#   - Redis  -> Upstash Free (external, NOT managed here). 10K cmd/day.
#   - S3     -> Cloudflare R2 Free (external). 10 GB storage, 10 GB egress.
#
# ML model weights strategy for free tier:
#   We EMBED a quantized small model (yolo11s-seg ~20 MB) into the image
#   so cold-start does not need an S3 download (Render free has no disk
#   cache between restarts, and Upstash/R2 free bandwidth is precious).
#   Use Dockerfile.embedded with MODEL_VARIANT=small to keep the final
#   image well under Render's 10 GB free-tier image cap (target ~600 MB).
#
# IMPORTANT: secrets MUST be set in Render dashboard (sync: false). Never
# commit them here. Use `JWT_SECRET_KEY: generateValue: true` so Render
# auto-generates a 32-char secret on first deploy.
# ----------------------------------------------------------------------

services:
  # ===================================================================
  # Web service β€” FastAPI (FREE plan)
  # ===================================================================
  - type: web
    name: hasari-api
    runtime: docker
    # repo: set this to your GitHub repo URL after first blueprint import,
    # e.g. https://github.com/erdoganpeker/arac-hasar-v2
    # Render Dashboard "Connect Repo" UI also resolves this automatically.
    repo: https://github.com/erdoganpeker/arac-hasar-v2
    branch: main
    rootDir: .
    # Dockerfile.embedded baked the 137 MB CarDD bundle into the image
    # (too big for Render free 10 GB image + slow rebuilds). We use the
    # slim Dockerfile and fetch weights from B2 at boot via entrypoint.sh.
    dockerfilePath: ./services/backend/Dockerfile
    dockerContext: ./services/backend
    plan: starter                    # 2 GB RAM, no sleep; required for ML pipeline (free 512 MB OOMs)
    region: frankfurt                # closest free region to TR
    autoDeploy: false                # gated by GH Actions deploy hook
    healthCheckPath: /health
    numInstances: 1
    envVars:
      - key: PORT
        value: "8000"
      - key: ENVIRONMENT
        value: production
      - key: RUN_MIGRATIONS
        value: "1"
      - key: ML_DEVICE
        value: cpu
      - key: MODEL_DIR
        value: /app/models
      # Boot-time model fetch from B2: entrypoint.sh downloads .pt files
      # from s3://$MODEL_S3_BUCKET/$MODEL_S3_PREFIX/ into MODEL_DIR.
      - key: SKIP_MODEL_FETCH
        value: "0"
      - key: MODEL_S3_BUCKET
        value: hasari-inspections
      - key: MODEL_S3_PREFIX
        value: models                # B2 path: hasari-inspections/models/{damage,parts,severity}_best.pt
      - key: FORCE_SYNC_INFERENCE
        value: "1"                   # free tier has no worker -> run inline
      - key: UVICORN_WORKERS
        value: "1"                   # 512 MB cannot hold 2 workers + model
      # ---- External services (set in dashboard, sync: false) ----
      - key: DATABASE_URL            # Supabase pooled URL (pgbouncer 6543)
        sync: false
      - key: REDIS_URL               # Upstash rediss:// URL
        sync: false
      - key: JWT_SECRET_KEY
        generateValue: true          # Render generates 32-char secret
      - key: API_KEYS
        sync: false
      # ---- S3 / Cloudflare R2 ----
      - key: S3_ENDPOINT             # https://<acct>.r2.cloudflarestorage.com
        sync: false
      - key: S3_REGION
        value: auto
      - key: S3_ACCESS_KEY
        sync: false
      - key: S3_SECRET_KEY
        sync: false
      - key: S3_BUCKET
        sync: false
      - key: S3_PUBLIC_ENDPOINT      # https://pub-<id>.r2.dev or custom
        sync: false
      # ---- CORS β€” pin to Vercel URL ----
      - key: CORS_ORIGINS
        value: https://hasari.vercel.app
      - key: CORS_ORIGIN_REGEX
        value: ^https://hasari(-[a-z0-9]+)?\.vercel\.app$
      # ---- Admin bootstrap (set once in dashboard) ----
      - key: ADMIN_EMAIL
        sync: false
      - key: ADMIN_PASSWORD
        sync: false
      # ---- Optional observability ----
      - key: SENTRY_DSN
        sync: false

  # ===================================================================
  # Worker β€” DISABLED on free tier (Render Free does not support workers).
  # We rely on FORCE_SYNC_INFERENCE=1 in the web service to run /analyze
  # synchronously. When upgrading to a paid plan, UNCOMMENT this block
  # and remove FORCE_SYNC_INFERENCE from the web service env.
  # ===================================================================
  # - type: worker
  #   name: hasari-worker
  #   runtime: docker
  #   repo: https://github.com/REPLACE_ME/arac-hasar-v2
  #   branch: main
  #   rootDir: .
  #   dockerfilePath: ./services/backend/Dockerfile.embedded
  #   dockerContext: .
  #   dockerCommand: celery -A worker.celery_app worker --loglevel=info --concurrency=1
  #   plan: starter                  # workers require a paid plan
  #   region: frankfurt
  #   autoDeploy: false
  #   numInstances: 1
  #   envVars:
  #     - key: ENVIRONMENT
  #       value: production
  #     - key: RUN_MIGRATIONS
  #       value: "0"
  #     - key: ML_DEVICE
  #       value: cpu
  #     - key: MODEL_DIR
  #       value: /app/models
  #     - key: MODEL_VARIANT
  #       value: small
  #     - key: SKIP_MODEL_FETCH
  #       value: "1"
  #     - key: DATABASE_URL
  #       sync: false
  #     - key: REDIS_URL
  #       sync: false
  #     - key: JWT_SECRET_KEY
  #       fromService:
  #         type: web
  #         name: hasari-api
  #         envVarKey: JWT_SECRET_KEY
  #     - key: S3_ENDPOINT
  #       sync: false
  #     - key: S3_REGION
  #       value: auto
  #     - key: S3_ACCESS_KEY
  #       sync: false
  #     - key: S3_SECRET_KEY
  #       sync: false
  #     - key: S3_BUCKET
  #       sync: false
  #     - key: SENTRY_DSN
  #       sync: false

# ===================================================================
# NO managed databases / redis on free tier β€” see docs/DEPLOY_FREE.md
# for Supabase + Upstash setup. The legacy paid blueprint (hasarui-db
# Postgres + hasarui-redis Redis) is kept in git history under the
# `services/databases` section of earlier revisions of this file.
# ===================================================================