# استقرار منتکت CRM — `crm.montzar.ir` > **قفل‌شده:** فقط همین فایل منبع دستورات استقرار است. پکیج‌منیجر = **npm** (نه pnpm/yarn). > قانون Cursor: `.cursor/rules/deploy.mdc` ## آپدیت سریع (بعد از هر `git push`) — همیشه همین ```bash ssh -p 3031 montime@185.50.38.53 cd /var/www/crm git pull npm run build -w @mento/shared cd apps/api && npx prisma migrate deploy && npx prisma generate && cd ../.. npm run build -w @mento/api npm run build -w @mento/web pm2 restart mento-crm-api # فقط اگر STT عوض شده: # pm2 restart mento-stt ``` --- هاست مشترک مونتایم: `185.50.38.53` (SSH پورت `3031`، کاربر `montime`) دامنه‌ها (همان اپ و همان مسیر): `https://crm.montzar.ir` و `https://crm.montact.ir` مسیر کد: `/var/www/crm` پورت داخلی API: `3030` PM2: `mento-crm-api` (cwd: `apps/api`، اسکریپت: `dist/src/main.js`) کد از Gitea: `http://get.feep.ir/Mahdi/CRM_Montzar.git` پورت‌های اشغال‌شده روی همین سرور (دست نزنید): ۳۰۰۰ مونتایم · ۳۰۰۱ فوری‌سند · ۳۰۱۰ سوپرادمین · ۳۰۲۰ کاتالوگ پورت داخلی STT (فقط localhost، عمومی نکنید): **۳۰۴۰** — PM2 `mento-stt` --- ## کارهایی که شما باید انجام دهید (قبل/همراه استقرار) 1. **DNS:** رکورد `A` برای `crm.montzar.ir` و `crm.montact.ir` مثل `ktg.montzar.ir` / `adm.montzar.ir` روی همان IP. 2. **پروکسی جلویی SSL:** مثل `crm.montzar.ir`، برای `crm.montact.ir` هم HTTPS تمام شود و به این سرور **HTTP :80** برسد. 3. **Postgres:** دیتابیس و کاربر جدا (`mento_crm`) — به دیتابیس مونتایم دست نزنید. 4. **SMS:** همان حساب ترِز/رایگان مونتایم در `.env` (`SMS_USERNAME` / `SMS_PASSWORD` / `SMS_SENDER`). 5. **دسترسی Gitea** برای `git clone` / `git pull` روی سرور. --- ## روی سرور SSH: ```bash ssh -p 3031 montime@185.50.38.53 ``` ### ۱) کلون ```bash sudo mkdir -p /var/www/crm sudo chown montime:montime /var/www/crm git clone http://get.feep.ir/Mahdi/CRM_Montzar.git /var/www/crm ``` ### ۲) پورت آزاد باشد ```bash pm2 list ss -tlnp | grep -E '3000|3001|3010|3020|3030' || true ``` ۳۰۳۰ باید خالی باشد. ### ۳) فایل `.env` API ```bash cd /var/www/crm cp deploy/.env.production.example apps/api/.env nano apps/api/.env ``` نکته‌های حیاتی: | کلید | مقدار واقعی روی این سرور | |---|---| | `DATABASE_URL` | Postgres روی **`127.0.0.1:15432`** است نه `5432` | | `PORT` | `3030` | | `CORS_ORIGIN` | `https://crm.montzar.ir,https://crm.montact.ir` | | `SMS_*` | همان ترِز مونتایم | | `PORTAL_SHOW_OTP` | در production حتماً `false` | | `INTEGRATIONS_ENCRYPTION_KEY` | ۶۴ کاراکتر hex برای رمز توکن ته‌حساب (`openssl rand -hex 32`) | | `PLATFORM_ADMIN_MOBILE` / `PASSWORD` / `NAME` | حساب اولیه سوپرادمین برای `/adm` (با `npx prisma db seed`) | نمونهٔ اتصال: ```text DATABASE_URL="postgresql://USER:PASS@127.0.0.1:15432/mento_crm?schema=public" ``` ### ۴) نصب وابستگی‌ها اگر `npm ci` روی سرور timeout زد، از ویندوز بیلد لینوکسی بگیرید و بفرستید: ```powershell # روی ویندوز، در ریشهٔ ریپو npm ci --os=linux --cpu=x64 tar -czf crm-node_modules.tgz node_modules scp -P 3031 crm-node_modules.tgz montime@185.50.38.53:/var/www/crm/ ``` روی سرور: ```bash cd /var/www/crm tar -xzf crm-node_modules.tgz chmod +x node_modules/.bin/* find node_modules -path '*esbuild*' -name 'esbuild' -type f -exec chmod +x {} \; # مهم: tarball کپی کهنه از @mento/shared می‌گذارد — همیشه symlink بسازید rm -rf node_modules/@mento/shared ln -s ../../packages/shared node_modules/@mento/shared ``` اگر `npm ci` روی سرور خودش جواب داد، معمولاً symlink workspace درست است؛ باز هم با `ls -la node_modules/@mento/shared` چک کنید که به `packages/shared` اشاره کند. ### ۵) migrate و بیلد `dist/` در git نیست؛ همیشه اول `shared` را بیلد کنید. ```bash cd /var/www/crm npm run build -w @mento/shared # Prisma فقط از apps/api/.env می‌خواند — از ریشه بدون env خطا می‌دهد (P1012) cd /var/www/crm/apps/api npx prisma migrate deploy npx prisma generate cd /var/www/crm npm run build -w @mento/api npm run build -w @mento/web mkdir -p uploads # اختیاری یک‌بار: npm run db:seed ``` ### ۶) تبدیل صوت به متن (Pipecat — Whisper محلی) فقط STT روی همین سرور؛ **بدون GapGPT**. Python 3.11+ و ترجیحاً `ffmpeg`. ```bash cd /var/www/crm/apps/stt python3.11 -m venv .venv .venv/bin/pip install -r requirements.txt cp .env.example .env nano .env ``` در `.env` فقط مدل محلی لازم است (`STT_MODEL=base`، `STT_DEVICE=cpu`). `OPENAI_API_KEY` برای دیکته لازم نیست. `STT_INTERNAL_TOKEN` اگر پر شد باید با `apps/api/.env` یکی باشد. در API: `STT_TIMEOUT_MS=180000` پیشنهاد می‌شود (لود اول مدل طول می‌کشد). ### ۷) PM2 — فقط پروسه‌های جدید پروسه‌های موجود را stop نکنید. ```bash pm2 start /var/www/crm/deploy/ecosystem.config.cjs pm2 save pm2 list curl -sI http://127.0.0.1:3030/api/health curl -s http://127.0.0.1:3040/health ``` باید `200` بیاید. خطا: `pm2 logs mento-crm-api --lines 80` یا `pm2 logs mento-stt --lines 80` ### ۸) Nginx ```bash sudo cp /var/www/crm/deploy/nginx-crm.montzar.ir.conf /etc/nginx/sites-available/crm.montzar.ir sudo ln -sf /etc/nginx/sites-available/crm.montzar.ir /etc/nginx/sites-enabled/ sudo nginx -t && sudo systemctl reload nginx ``` فایل vhost هر دو نام را دارد: `crm.montzar.ir` و `crm.montact.ir` → همان `root` و همان API روی پورت ۳۰۳۰. **HTTPS روی همین باکس:** مثل `ktg.montzar.ir`، فرانت‌پروکسی (`91.247.174.1`) SSL را تمام می‌کند و به این سرور **HTTP :80** می‌زند. اگر Certbot روی این vhost `return 404` یا فقط HTTPS بگذارد، سایت از بیرون قطع می‌شود — vhost را روی الگوی HTTP نگه دارید (فایل `deploy/nginx-crm.montzar.ir.conf`). ### ۸ب) اضافه کردن دامنهٔ alias (`crm.montact.ir`) روی همین استقرار بعد از `git pull` و آپدیت سریع: ```bash # CORS هر دو دامنه nano /var/www/crm/apps/api/.env # CORS_ORIGIN=https://crm.montzar.ir,https://crm.montact.ir sudo cp /var/www/crm/deploy/nginx-crm.montzar.ir.conf /etc/nginx/sites-available/crm.montzar.ir sudo nginx -t && sudo systemctl reload nginx pm2 restart mento-crm-api ``` تست: `https://crm.montact.ir` و `https://crm.montzar.ir` هر دو همان پنل را نشان دهند. ### ۹) تست 1. `https://crm.montzar.ir` → ورود پنل 2. دمو: `owner@demo.local` / `demo1234` (اگر seed زده باشید) 3. پرتال: `https://crm.montzar.ir/p/demo-mento` → OTP باید پیامک شود 4. منوها: گزارشات، کاریز پروژه، باشگاه مشتریان، اتوماسیون (مالک/مدیر) 5. سوپرادمین: `https://crm.montzar.ir/adm` (بعد از seed با `PLATFORM_ADMIN_*`) --- ## پنل سوپرادمین (`/adm`) مسیر جدا روی nginx لازم نیست؛ همان SPA (`crm.montzar.ir`) روت `/adm` را سرو می‌کند. ورود با **موبایل + رمز** است. 1. در `apps/api/.env` این کلیدها را بگذارید (نمونه در `deploy/.env.production.example`): ```text PLATFORM_ADMIN_MOBILE=09121234567 PLATFORM_ADMIN_PASSWORD=change-me-strong-platform-password PLATFORM_ADMIN_NAME=سوپرادمین ``` 2. بعد از `prisma migrate deploy` یک‌بار seed بزنید تا حساب اولیه ساخته شود: ```bash cd /var/www/crm/apps/api npx prisma db seed ``` اگر حساب با همان موبایل از قبل باشد، seed رمز را هم از `.env` به‌روز می‌کند. ادمین‌های بعدی را از داخل پنل (`/adm/admins`) اضافه کنید. ### اشتراک و ماژول‌ها بعد از این نسخه، `prisma migrate deploy` جدول `BillingAccount` و ستون `enabledModules` را می‌سازد و برای مالکان فعلی trial **۱۵ روزه** می‌سازد. از `/adm/users` پلن را تمدید کنید و از `/adm/organizations` ماژول هر محیط را تنظیم کنید. 3. ورود: `https://crm.montzar.ir/adm` → داشبورد `/adm/dashboard` توکن سوپرادمین جدا از JWT کاربران سازمانی است. --- ## آپدیت بعدی (بعد از `git push`) همان بلوک **«آپدیت سریع»** بالای فایل. نکات اضافه فقط در صورت نیاز: ```bash # اگر node_modules از tarball تازه شد، دوباره symlink: # rm -rf node_modules/@mento/shared && ln -s ../../packages/shared node_modules/@mento/shared # chmod +x node_modules/.bin/* # اگر requirements.txt عوض شد: # cd apps/stt && .venv/bin/pip install -r requirements.txt && cd ../.. # pm2 restart mento-stt ``` پاک نکنید: `uploads/` و `apps/api/.env` --- ## پیامک (OTP پرتال) - سرویس: `apps/api/src/common/sms.service.ts` — الگوی ترِز مثل مونتایم - تنظیمات فقط در `apps/api/.env` (نمونه: `deploy/.env.production.example`) - کلیدها: `SMS_PROVIDER=trez`، `SMS_USERNAME`، `SMS_PASSWORD`، `SMS_SENDER`، `SMS_BASE_URL`، `SMS_SEND_PATH`، `SMS_OTP_TEMPLATE` - در production: `PORTAL_SHOW_OTP=false` تا کد فقط با پیامک برود (نه در JSON پاسخ) - تست: ورود پرتال با موبایل ثبت‌شده روی شخص سازمان --- ## مشکلات رایج (تجربهٔ واقعی همین سرور) | علامت | علت | راه حل | |---|---|---| | Prisma `P1012` / `DATABASE_URL` not found | migrate از `/var/www/crm` بدون `.env` | `cd apps/api` سپس `npx prisma migrate deploy` | | اتصال DB رد می‌شود با پورت `5432` | Postgres این سرور روی **15432** است | `DATABASE_URL` را با `:15432` بگذارید | | Nest: `@mento/shared` has no exported member … | `node_modules/@mento/shared` کپی قدیمی از tarball است | `rm -rf node_modules/@mento/shared && ln -s ../../packages/shared node_modules/@mento/shared` سپس بیلد `shared` و `api` | | بعد از بیلد shared هنوز تایپ‌ها نیستند | همان کپی کهنه | `grep AutomationAction node_modules/@mento/shared/dist/index.d.ts` باید match بدهد | | `esbuild` / `.bin` Permission denied | tarball از ویندوز بدون بیت اجرایی | `chmod +x node_modules/.bin/*` و باینری esbuild | | `npm ci` timeout روی سرور | شبکه/رجیستری کند | tarball لینوکسی از ویندوز (`npm ci --os=linux --cpu=x64`) | | سایت از بیرون 404 بعد از Certbot | SSL روی باکس بک‌اند، پروکسی جلویی HTTP می‌زند | vhost را فقط HTTP :80 مثل ktg نگه دارید | | PM2 فایل را پیدا نمی‌کند | خروجی Nest زیر `dist/src/main.js` است | `deploy/ecosystem.config.cjs` را عوض نکنید (`cwd` = `apps/api`) | تشخیص سریع لینک shared: ```bash ls -la /var/www/crm/node_modules/@mento/shared # باید شبیه این باشد: # ... -> ../../packages/shared grep -c AutomationAction /var/www/crm/packages/shared/dist/index.d.ts grep -c AutomationAction /var/www/crm/node_modules/@mento/shared/dist/index.d.ts # هر دو باید یک عدد (>0) باشند ``` --- ## تداخل نداشتن | این پروژه | بقیه — دست نزنید | |---|---| | دامنه‌های `crm.montzar.ir` و `crm.montact.ir` | `ktg` / `adm` / مونتایم | | پورت ۳۰۳۰ و ۳۰۴۰ (STT فقط localhost) | ۳۰۰۰ / ۳۰۰۱ / ۳۰۱۰ / ۳۰۲۰ | | PM2 نام `mento-crm-api` و `mento-stt` | پروسه‌های موجود | | `/var/www/crm` | `/var/www/ktg` و … | | دیتابیس `mento_crm` روی `:15432` | Postgres مونتایم |