hasari-api / scripts /deploy /render-secrets-template.md
erdoganpeker's picture
v0.3.0 β€” multimodal vehicle damage MVP
e327f0d
# Render Secrets β€” Configuration Checklist
This document lists every environment variable that must be set in the
Render dashboard for `hasarui-api` and `hasarui-worker`. Most are
declared `sync: false` in `render.yaml`, which means Render keeps the
key empty until you set it manually (so they never get committed to
git).
After applying `render.yaml` via **Blueprints -> New Blueprint** in the
dashboard, go to each service -> **Environment** and populate:
---
## 1. JWT / auth
| Key | Service(s) | How to set |
|--------------------|-----------------|---------------------------------------------------|
| `JWT_SECRET_KEY` | api, worker | Auto-generated by Render; worker pulls from api. |
| `API_KEYS` | api, worker | Comma-separated tenant keys, e.g. `client1_xxx,client2_yyy`. |
| `ADMIN_EMAIL` | api | First admin user email. |
| `ADMIN_PASSWORD` | api | First admin password (rotate after first login). |
## 2. S3 (model weights + uploaded images)
Use any S3-compatible provider. Recommended for pilot: **Cloudflare R2**
(zero egress) or **Backblaze B2** (~$0.005/GB).
| Key | Example value | Notes |
|----------------------|--------------------------------------------------------|-----------------------------------------|
| `S3_ENDPOINT` | `https://<accountid>.r2.cloudflarestorage.com` | Empty for plain AWS S3. |
| `S3_REGION` | `auto` (R2) / `eu-central-1` (AWS) / `eu-central-003` (B2) | Match the bucket. |
| `S3_ACCESS_KEY` | (provider IAM access key id) | Use a *scoped* key, not root. |
| `S3_SECRET_KEY` | (provider IAM secret) | Treat as max-sensitive. |
| `S3_BUCKET` | `hasarui-inspections-prod` | Stores uploaded images & artefacts. |
| `S3_PUBLIC_ENDPOINT` | `https://cdn.hasarui.com` or signed-URL base | Used to build URLs returned to clients. |
### Model bundle bucket (can be the same bucket, different prefix)
| Key | Example | Notes |
|--------------------|----------------------------------------|----------------------------------------|
| `MODEL_S3_BUCKET` | `hasarui-models` | Bucket containing model weights. |
| `MODEL_S3_PREFIX` | `models/full_20260515_044630` | Already set in render.yaml. |
### Uploading the model bundle (one-time)
From a machine with the snapshot dir on disk:
```bash
aws s3 sync \
services/ml/runs/bundles/full_20260515_044630/_SNAPSHOT_FOR_BUILD/ \
s3://hasarui-models/models/full_20260515_044630/ \
--endpoint-url https://<accountid>.r2.cloudflarestorage.com
```
After upload, redeploy `hasarui-api` once; the entrypoint will pull the
three `.pt` files into `/app/models/` on boot (~30 s on first boot).
## 3. CORS
| Key | Example |
|----------------------|------------------------------------------------------------------------|
| `CORS_ORIGINS` | `https://hasarui.vercel.app,https://app.hasarui.com,tauri://localhost` |
| `CORS_ORIGIN_REGEX` | `^https://([a-z0-9-]+\.)*hasarui\.com$` |
For the desktop (Tauri) app include `tauri://localhost` and
`http://tauri.localhost`. For Expo dev clients include
`http://localhost:8081`.
## 4. Observability (optional but strongly recommended)
| Key | Where to get it |
|-----------------|--------------------------------------------------|
| `SENTRY_DSN` | Sentry project settings -> Client Keys (DSN). |
## 5. Deploy hooks (set in GitHub repo secrets, NOT Render)
After creating the services, copy each one's **Deploy Hook URL** from
Render -> Service -> Settings -> Deploy Hook, and add to GitHub:
| GitHub secret name | Value |
|--------------------------------|------------------------------------|
| `RENDER_DEPLOY_HOOK_API` | Deploy hook URL for `hasarui-api`. |
| `RENDER_DEPLOY_HOOK_WORKER` | Deploy hook URL for `hasarui-worker`. |
---
## Cost reference (May 2026)
| Component | Plan | Monthly |
|-----------------------------|-----------|---------|
| `hasarui-api` (web) | starter | $7 |
| `hasarui-api` (web) | standard | $25 |
| `hasarui-worker` | starter | $7 |
| `hasarui-redis` | starter | $10 |
| `hasarui-db` (Postgres) | starter | $7 |
| **Total (starter)** | | **~$31** |
| **Total (standard web)** | | **~$49** |
Add S3 (R2: ~$0.015/GB stored, $0 egress) and Sentry developer free tier.
---
## Operational notes
- **Cold start**: starter plans do NOT spin down. Stay on starter
minimum even when traffic is low β€” free tier spins down after 15 min
and the first inference would cost ~45 s of cold boot (uvicorn +
model load).
- **Memory**: the warmed pipeline holds ~700 MB of weights in RAM.
Starter (512 MB) will OOM. Bump `hasarui-api` and `hasarui-worker`
to **standard ($25)** before doing real inference.
- **Filesystem is ephemeral**: every deploy and every restart wipes
`/app/models`. That is why we re-fetch from S3 in
`scripts/entrypoint.sh`. Boot time: ~30 s for the 3 weight files.
- **One worker concurrency**: keep `--concurrency=1` until you
upgrade plans β€” two parallel inferences on a 0.5 CPU plan starve
each other.
- **Secrets rotation**: rotate `S3_ACCESS_KEY` / `JWT_SECRET_KEY`
every 90 days. JWT rotation invalidates active sessions β€” schedule
during a maintenance window.