45cd028d1c
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>
3.0 KiB
3.0 KiB
Meezi — Production deployment (Arvan Cloud)
Prerequisites
- Arvan Cloud account (Iran region)
- Domain
meezi.irDNS 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
- Sandbox first: set
ZarinPal__Sandbox=trueand a sandbox merchant; complete subscribe flow; confirm redirect?billing=successand JWT refresh on settings. - Production: set
ZarinPal__Sandbox=falseand productionZarinPal__MerchantId; verify callback URL is reachable from ZarinPal. - 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}(seeApp:QrPublicBaseUrl). - Next.js route
web/dashboard/src/app/q/[code]/page.tsxresolves via publicGET /api/q/{code}. - Flutter app parses scanned URL and calls the same API.
Arvan checklist
- Postgres + Redis on private network (no public ports)
api_uploadspersistent volume mounted at/app/uploadsRUN_MIGRATIONS=trueon API deploy only- Hangfire
/hangfirebehind VPN or basic auth - CORS origins: dashboard + marketing domain
App__QrPublicBaseUrl=https://meezi.irBilling__DashboardBaseUrl=https://app.meezi.ir(locale path added by API)- TLS on load balancer for
api.*andapp.* - Kavenegar + ZarinPal production keys in Arvan secrets (not in git)
Deploy steps
- Build and push Docker images (
docker composeDockerfiles indocker/). - Run EF migrations on API startup (
RUN_MIGRATIONS=true) once per release. - Configure Hangfire dashboard behind auth in production.
- Smoke test: OTP login, POS terminal register, create order, menu images visible, ZarinPal subscribe (sandbox first).
CI suggestion
dotnet build+dotnet teston PRnpm run buildinweb/dashboard- Deploy on tag to Arvan registry