# راهنمای دیپلوی ClinicPro روی لیارا (پلتفرم PHP) دیپلوی بک‌اند Symfony روی **پلتفرم PHP لیارا** (نوع برنامه `php` هنگام «ساخت برنامه‌ی جدید»). اینجا داکری در کار نیست؛ لیارا کد را می‌گیرد، خودش `composer install` می‌زند و روی Apache + PHP-FPM سرو می‌کند. > مسیر جایگزین (داکر) در [docs/deploy-liara.md](deploy-liara.md) است. **همزمان فقط یک مسیر** را نگه دار — هر دو از یک `liara.json` استفاده می‌کنند. --- ## نمای کلی ``` ┌──────────────── Liara private network ─────────────────┐ │ │ │ ┌──────────────────────────────┐ ┌──────────────┐ │ │ │ clinicpro-api (PHP app) │ │ MariaDB 11.8 │ │ │ │ • Apache + PHP-FPM (docroot │◄─►│ (managed) │ │ │ │ = public/) :80 │ └──────────────┘ │ │ │ • supervisor.conf: │ ┌──────────────┐ │ │ │ worker-async │◄─►│ Redis │ │ │ │ worker-scheduler │ │ (managed) │ │ │ └──────────────────────────────┘ └──────────────┘ │ │ disks: jwt / uploads / var-uploads │ └────────────────────────────────────────────────────────┘ │ :80 ▼ https:// ``` همهٔ پروسه‌ها (وب + هر دو worker) در **یک** کانتینر اجرا می‌شوند؛ workerها کانتینر جدا ندارند (برخلاف نسخهٔ docker-compose). --- ## فایل‌های دخیل (همه ساخته شده‌اند) | فایل | نقش | |---|---| | [`liara.json`](../liara.json) | `platform: php`، `php.version: 8.2`، `documentRoot: public`، دیسک‌ها | | [`public/.htaccess`](../public/.htaccess) | rewrite front-controller سیمفونی روی Apache | | [`liara_pre_build.sh`](../liara_pre_build.sh) | قبل `composer install`: ساخت `.env` مینیمال prod | | [`liara_pre_start.sh`](../liara_pre_start.sh) | قبل start: انتظار DB، تولید JWT، cache، migration | | [`supervisor.conf`](../supervisor.conf) | دو worker مسنجر (`async` + `scheduler_default`) | | [`liara_php.ini`](../liara_php.ini) | memory_limit، حجم آپلود، زمان اجرا | | [`.liaraignore`](../.liaraignore) | کنترل آپلود (تا `public/build` آپلود شود، سکرت‌ها مستثنی) | | [`.env.liara.example`](../.env.liara.example) | مرجع متغیرهای محیطی | --- ## پیش‌نیاز ```bash npm i -g @liara/cli liara login ``` مقادیر آماده: ```bash php -r "echo bin2hex(random_bytes(32)).\"\n\";" # APP_SECRET openssl rand -hex 32 # JWT_PASSPHRASE ddev exec php docker/gen-cors-env.php # ALLOWED_FRONTEND_HOSTS + CORS_ALLOW_ORIGIN ``` --- ## گام ۱ — build محلی asset‌ها (حیاتی) پلتفرم PHP لیارا **`yarn` اجرا نمی‌کند** و asset‌های React را نمی‌سازد. قبل هر دیپلوی محلی build کن (خروجی در `public/build`؛ `.liaraignore` آن را آپلود می‌کند): ```bash ddev exec yarn install --frozen-lockfile ddev exec yarn build ``` > اگر این مرحله را رد کنی، پنل ادمین `/admin` لود نمی‌شود. --- ## گام ۲ — ساخت دیتابیس و Redis کنسول لیارا: 1. **MariaDB 11.8** بساز (هماهنگ با `serverVersion=mariadb-11.8.0`). 2. **Redis** بساز. 3. روی هر دو **شبکهٔ خصوصی** فعال؛ هاست خصوصی/کاربر/رمز را یادداشت کن. --- ## گام ۳ — ساخت برنامهٔ PHP 1. New App → نوع **PHP** → نسخهٔ **8.2** (پروژه `php: >=8.2` می‌خواهد) → شناسه `clinicpro-api`. 2. آن را به **همان شبکهٔ خصوصیِ** DB و Redis وصل کن. --- ## گام ۴ — ساخت دیسک‌های ماندگار در صفحهٔ برنامه، بخش Disks، این سه دیسک را با همین نام‌ها بساز (mount از `liara.json`): | نام | mountTo | محتوا | |---|---|---| | `jwt` | `/var/www/config/jwt` | کلید JWT (نباید هر دیپلوی نو شود) | | `uploads` | `/var/www/public/uploads` | فایل‌های عمومی | | `var-uploads` | `/var/www/var/uploads` | فایل‌های خصوصی | > ⚠️ ریشهٔ اپ فرض شده `/var/www`. اگر در لاگ مسیر دیگری دیدی، `mountTo` در `liara.json` را اصلاح کن. --- ## گام ۵ — متغیرهای محیطی از روی [`.env.liara.example`](../.env.liara.example) ست کن (تب Environment یا CLI). یک‌بار روی app؛ workerها همان را می‌گیرند. ```bash liara env set APP_ENV=prod APP_DEBUG=0 --app clinicpro-api liara env set APP_SECRET=<...> JWT_PASSPHRASE=<...> --app clinicpro-api liara env set DATABASE_URL="mysql://:@:3306/?serverVersion=mariadb-11.8.0&charset=utf8mb4" --app clinicpro-api liara env set REDIS_URL="redis://:@:6379" --app clinicpro-api liara env set MESSENGER_TRANSPORT_DSN="redis://:@:6379/messages" --app clinicpro-api liara env set JWT_SECRET_KEY='%kernel.project_dir%/config/jwt/private.pem' JWT_PUBLIC_KEY='%kernel.project_dir%/config/jwt/public.pem' --app clinicpro-api liara env set APP_BASE_URL=https:// DEFAULT_URI=https:// --app clinicpro-api liara env set TRUSTED_PROXIES="10.0.0.0/8,172.16.0.0/12,192.168.0.0/16,127.0.0.1" --app clinicpro-api liara env set ALLOWED_FRONTEND_HOSTS="" CORS_ALLOW_ORIGIN="" --app clinicpro-api liara env set API_IR_BASE_URL=https://s.api.ir API_IR_TOKEN= --app clinicpro-api liara env set REFRESH_TOKEN_TTL=2592000 OTP_TTL=1200 MAX_FILE_SIZE_BYTES=5242880 UPLOAD_DIR=var/uploads --app clinicpro-api ``` نکته‌ها: - `RUN_INIT` را ست **نکن** — init یک‌بار در `liara_pre_start.sh` اجرا می‌شود. - `APP_ENV=prod` موقع build هم لازم است (composer اسکریپت `cache:clear` را اجرا می‌کند). - کلیدهای SMS و درگاه پرداخت از **دیتابیس** خوانده می‌شوند، نه env. --- ## گام ۶ — دیپلوی از ریشهٔ `clinicpro/`: ```bash liara deploy ``` روند خودکار: 1. `liara_pre_build.sh` → `.env` مینیمال prod (اگر نبود). 2. `composer install` (لیارا). 3. `liara_pre_start.sh` → انتظار DB → تولید JWT (روی دیسک) → warmup → migration. 4. Apache (docroot=`public`) + `supervisor.conf` (هر دو worker) بالا می‌آیند. --- ## گام ۷ — اتصال دامنه و تأیید 1. بخش Domains: دامنهٔ API را وصل کن، TLS بگیر. 2. سلامت: ```bash curl -i https:///health # باید 200 ``` 3. workerها: ```bash # در کنسول/CLI برنامه: supervisorctl status # worker-async و worker-scheduler = RUNNING ``` 4. ورود `/admin` و تست یک endpoint (تأیید DB/Redis). --- ## دیپلوی‌های بعدی ```bash ddev exec yarn build # اگر assets عوض شد liara deploy ``` migrationها خودکار در `liara_pre_start.sh` اجرا می‌شوند. دیسک‌ها و env حفظ می‌شوند. --- ## نگاشت compose → لیارا (PHP platform) در `docker-compose.yml` هر worker یک کانتینر جدا بود؛ اینجا هر دو در همان کانتینر با `supervisor.conf`: | compose | لیارا | |---|---| | سرویس `app` (php-fpm+nginx) | خود پلتفرم PHP (Apache+PHP-FPM)، docroot=`public` | | `worker-async` (کانتینر جدا) | `[program:worker-async]` در `supervisor.conf` | | `worker-scheduler` (کانتینر جدا) | `[program:worker-scheduler]` در `supervisor.conf` | | `environment: *app-env` + `RUN_INIT` | env روی app؛ init در `liara_pre_start.sh` | | `volumes` | دیسک‌های `liara.json` | | `networks: [coolify]` | شبکهٔ خصوصی لیارا | | `restart`/`healthcheck` | `autorestart=true` | | `stop_grace_period: 30s` | `stopsignal=TERM` + `stopwaitsecs=30` | --- ## رفع اشکال | نشانه | علت | راه‌حل | |---|---|---| | پنل `/admin` سفید/۴۰۴ asset | `public/build` آپلود نشده | `ddev exec yarn build` قبل deploy؛ `.liaraignore` build را مستثنی نکند | | کل سایت ۴۰۳/۴۰۴ | documentRoot روی `public` نیست یا `.htaccess` نیست | `documentRoot: public` در liara.json + `public/.htaccess` | | `Database not reachable after 60s` | شبکهٔ خصوصی/`DATABASE_URL` غلط | DB و app یک شبکه؛ هاست خصوصی را چک کن | | توکن‌ها بعد هر دیپلوی باطل | دیسک `jwt` mount نشده | دیسک `jwt` → `/var/www/config/jwt` | | worker بالا نمی‌آید / messenger خطای redis | افزونهٔ `redis` روی پلتفرم نیست | `php -m \| grep redis`؛ نبود → `MESSENGER_TRANSPORT_DSN=doctrine://default` + کش فایل‌سیستم | | build به‌خاطر composer scripts شکست | `cache:clear` موقع نصب | مطمئن شو `APP_ENV=prod` ست است؛ در صورت لزوم نصب را `--no-scripts` کن و همه‌چیز را به `liara_pre_start.sh` بسپار | | خطای CORS از فرانت | `CORS_ALLOW_ORIGIN` قدیمی | `docker/gen-cors-env.php` دوباره؛ env به‌روز | --- ## ریسک‌های شناخته‌شده - **ext-redis:** اگر پلتفرم PHP لیارا phpredis نداشته باشد، Redis (cache + messenger) کار نمی‌کند → fallback به Doctrine transport و کش فایل‌سیستم. قبل اتکا verify کن. - **مسیر دیسک:** ریشهٔ `/var/www` فرض است؛ با لاگ واقعی تطبیق بده. - **انتخاب مسیر:** یا Docker یا PHP platform — هر دو `liara.json` را همزمان نگه ندار.