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

84 lines
3.0 KiB
Markdown

# 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`](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