Files
meezi/DEPLOY.md
T
soroush.asadi 45cd028d1c chore: initial project structure and root configuration
Adds root-level config files: solution (.slnx), NuGet, global.json,
Docker Compose files for all services (API, dashboard, website, finder,
admin), environment example, and developer documentation.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-05-27 21:33:10 +03:30

3.0 KiB

Meezi — Production deployment (Arvan Cloud)

Prerequisites

  • Arvan Cloud account (Iran region)
  • Domain meezi.ir DNS pointed to Arvan load balancer
  • ZarinPal merchant ID (production, sandbox off)
  • Kavenegar API key
  • PostgreSQL 16 + Redis managed or VMs

Services

Service Suggested host
API api.meezi.ir → ASP.NET container port 8080
Dashboard app.meezi.ir or meezi.ir → Next.js standalone
QR landing meezi.ir/q/* → same Next.js app (/q/[code] route)
Postgres Private network only
Redis Private network only

Environment variables (API)

ConnectionStrings__DefaultConnection=Host=...;Database=meezi;...
ConnectionStrings__Redis=...
Jwt__Key=<32+ char secret>
App__PublicBaseUrl=https://api.meezi.ir
App__QrPublicBaseUrl=https://meezi.ir
Billing__DashboardBaseUrl=https://app.meezi.ir
ZarinPal__MerchantId=<merchant>
ZarinPal__Sandbox=false
Kavenegar__ApiKey=<key>
Snappfood__WebhookSecret=<secret>
Taraz__Username=<moadian-user>
Taraz__Password=<moadian-pass>
Taraz__CertificatePath=/secrets/taraz.pfx
RUN_MIGRATIONS=true
Cors__Origins__0=https://app.meezi.ir
Cors__Origins__1=https://meezi.ir

ZarinPal / Taraz validation

  1. Sandbox first: set ZarinPal__Sandbox=true and a sandbox merchant; complete subscribe flow; confirm redirect ?billing=success and JWT refresh on settings.
  2. Production: set ZarinPal__Sandbox=false and production ZarinPal__MerchantId; verify callback URL is reachable from ZarinPal.
  3. Taraz: with real credentials, submit from Settings → تاراز; confirm tracking in API logs (stub logs until full SDK wired).

Environment variables (Web)

NEXT_PUBLIC_API_URL=https://api.meezi.ir

Routing

  • Customer QR codes encode https://meezi.ir/q/{qrCode} (see App:QrPublicBaseUrl).
  • Next.js route web/dashboard/src/app/q/[code]/page.tsx resolves via public GET /api/q/{code}.
  • Flutter app parses scanned URL and calls the same API.

Arvan checklist

  • Postgres + Redis on private network (no public ports)
  • api_uploads persistent volume mounted at /app/uploads
  • RUN_MIGRATIONS=true on API deploy only
  • Hangfire /hangfire behind VPN or basic auth
  • CORS origins: dashboard + marketing domain
  • App__QrPublicBaseUrl=https://meezi.ir
  • Billing__DashboardBaseUrl=https://app.meezi.ir (locale path added by API)
  • TLS on load balancer for api.* and app.*
  • Kavenegar + ZarinPal production keys in Arvan secrets (not in git)

Deploy steps

  1. Build and push Docker images (docker compose Dockerfiles in docker/).
  2. Run EF migrations on API startup (RUN_MIGRATIONS=true) once per release.
  3. Configure Hangfire dashboard behind auth in production.
  4. Smoke test: OTP login, POS terminal register, create order, menu images visible, ZarinPal subscribe (sandbox first).

CI suggestion

  • dotnet build + dotnet test on PR
  • npm run build in web/dashboard
  • Deploy on tag to Arvan registry