Files
clinicpro/docs/deploy-liara-php.md
T

209 lines
10 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# راهنمای دیپلوی 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://<domain>
```
همهٔ پروسه‌ها (وب + هر دو 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://<user>:<pass>@<db-private-host>:3306/<db>?serverVersion=mariadb-11.8.0&charset=utf8mb4" --app clinicpro-api
liara env set REDIS_URL="redis://:<pass>@<redis-private-host>:6379" --app clinicpro-api
liara env set MESSENGER_TRANSPORT_DSN="redis://:<pass>@<redis-private-host>: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://<domain> DEFAULT_URI=https://<domain> --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="<output>" CORS_ALLOW_ORIGIN="<output>" --app clinicpro-api
liara env set API_IR_BASE_URL=https://s.api.ir API_IR_TOKEN=<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://<domain>/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` را همزمان نگه ندار.