Files
tehran_taj/docs/SERVER-SETUP-CHECKLIST.md
s.esmaeiliandCursor c34bf80e6f fix(api): start in production with safe fallbacks instead of crash-looping (502)
A production API with incomplete config threw before listening, so the
container restarted forever and every /api request through nginx was a 502.
The problems are now printed as one loud warning and each gets a safe
fallback:

- JWT_SECRET / JWT_CUSTOMER_SECRET missing, weak or equal: a random key is
  generated once and kept in the Setting table (boot-secrets.ts), so tokens
  survive restarts. A strong value in the environment always wins.
  JwtModule now uses registerAsync so it reads the key after boot fills it.
- OTP_MASTER_CODE: ignored in production unless
  TEST_SERVER_ALLOW_MASTER_CODE=yes.
- CORS_ORIGINS: invalid entries dropped; empty allows every origin.

Tests: boot-secrets.spec, production-checks.spec. 118 tests pass.

سرور با تنظیمات ناقص دیگر مدام ریست نمی‌شود و ورود دوباره کار می‌کند.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-10-10 16:19:30 +03:30

4.9 KiB

فهرست تنظیمات سرور اصلی

برای کسی که به سرور اصلی (سرور واقعیِ مشتری‌ها) دسترسی دارد.

اگر موارد زیر درست نباشند، سرور باز هم روشن می‌شود ولی در گزارش سرور فهرست کامل ایرادها با یک هشدار بزرگ چاپ می‌شود و برای هر مورد جایگزین امن به کار می‌رود:

  • کلیدهای JWT_SECRET و JWT_CUSTOMER_SECRET: یک کلید تصادفی یک بار ساخته و در جدول Setting نگه داشته می‌شود، پس با ریستارت عوض نمی‌شود.
  • OTP_MASTER_CODE: بی‌اثر می‌شود و کد ثابت کار نمی‌کند.
  • CORS_ORIGINS: همه‌ی نشانی‌ها مجازند.

باز هم بهتر است هر سه را درست تنظیم کنید و یک بار دوباره راه‌اندازی کنید.

این بررسی فقط در حالت اصلی (NODE_ENV=production) انجام می‌شود. تصویر داکرِ سرور همیشه در این حالت است.


۱. حذف کد ثابت ورود آزمایشی

متغیر مقدار درست
OTP_MASTER_CODE خالی یا کلاً حذف‌شده

تا وقتی این کد هست، هر کسی که آن را بداند وارد حساب هر مشتری می‌شود.

سرور آزمایشیای که عمداً این کد را لازم دارد، باید کنارش TEST_SERVER_ALLOW_MASTER_CODE=yes بگذارد. این را هرگز روی سرور اصلی نگذارید.

۲. کلید جدا برای مشتری‌ها

متغیر مقدار درست
JWT_SECRET یک رشته‌ی تصادفی، دست‌کم ۳۲ نویسه (کلید ورود مدیرها)
JWT_CUSTOMER_SECRET یک رشته‌ی تصادفیِ دیگر، دست‌کم ۳۲ نویسه (کلید ورود مشتری‌ها و کارشناس‌ها)

دو مقدار نباید یکی باشند. ساختن مقدار تصادفی، روی هر سیستمی که Node دارد:

node -e "console.log(require('crypto').randomBytes(32).toString('hex'))"

دو بار اجرا کنید و هر خروجی را برای یکی از دو متغیر بگذارید.

⚠ عوض کردن این کلیدها همه را از حساب بیرون می‌کند. مدیرها و مشتری‌ها یک بار دوباره وارد می‌شوند. اطلاعات کسی از بین نمی‌رود.

⚠ اگر ACCOUNTING_SECRET_KEY خالی باشد، رمز ذخیره‌شده‌ی نرم‌افزار حسابداری از JWT_SECRET ساخته می‌شود. با عوض شدن JWT_SECRET باید یک بار دوباره در «تنظیمات حسابداری» پنل وارد شوید. بهتر است ACCOUNTING_SECRET_KEY هم یک مقدار تصادفیِ جدا بگیرد و دیگر عوض نشود.

۳. نشانی‌های مجاز

متغیر مقدار درست
CORS_ORIGINS نشانی کامل پنل و اپ‌ها، با ویرگول جدا

نمونه:

CORS_ORIGINS=https://adm.henzagold.ir,https://app.henzagold.ir,https://app2.henzagold.ir
  • هر نشانی با https:// شروع شود و مسیر نداشته باشد؛ مثلاً /admin در آخرش نیاید.
  • هر دامنه‌ای که پنل یا یکی از دو اپ از آن باز می‌شود باید در فهرست باشد؛ وگرنه آن صفحه نمی‌تواند با سرور حرف بزند.
  • * پذیرفته نمی‌شود.

۴. پیامک: نشانی سرور

متغیر مقدار درست
SMS_RELAY_HOST نشانی IP عمومی همین سرور

سرویس پیامک، سرور فرستنده را با این مقدار می‌شناسد. اگر خالی باشد، برنامه خودش نشانی عمومی سرور را پیدا می‌کند؛ ولی نوشتن آن مطمئن‌ترین راه است. داخل داکر، نشانیِ خودِ برنامه یک نشانی داخلی (172.x) است و سرویس پیامک آن را نمی‌شناسد.

بعد از راه‌اندازی، در گزارش سرور خطی مثل SMS relay host: … نشانی‌ای را که فرستاده می‌شود نشان می‌دهد. اگر هشدار «private address» دیدید، این متغیر را پر کنید.


بعد از تنظیم

  1. سرور را دوباره راه‌اندازی کنید.
  2. در گزارش سرور باید Nest application successfully started دیده شود. اگر سرور بالا نیامد، فهرست ایرادها همان‌جا چاپ شده است.
  3. پنل مدیریت و هر دو اپ را باز کنید و یک بار وارد شوید.
  4. ورود مشتری با پیامک را امتحان کنید. کد ثابت دیگر نباید کار کند.