# نصب روی Ubuntu Server (22.04 / 24.04)

مسیرها و نام‌ها: کد در `/var/www/gostardeh`، کاربر سیستم `gostardeh`، دامنه `bot.example.com`.

> مسیر سریع: کد را در `/var/www/gostardeh` قرار دهید، دیتابیس را بسازید (بخش ۳)، `.env` را پر کنید و `sudo DOMAIN=bot.example.com bash scripts/install.sh` را اجرا کنید. بخش‌های زیر همان کارها را دستی توضیح می‌دهند.

## ۱. پیش‌نیازها

- دامنه‌ای که به IP سرور اشاره می‌کند (Webhook تلگرام فقط HTTPS با گواهی معتبر می‌پذیرد).
- پورت ۴۴۳ باز.
- توکن ربات از @BotFather.

## ۲. PHP

```bash
sudo add-apt-repository -y ppa:ondrej/php && sudo apt update
sudo apt install -y php8.3-cli php8.3-fpm php8.3-mysql php8.3-curl php8.3-mbstring php8.3-bcmath php8.3-xml php8.3-opcache
```

افزونه‌های لازم: `pdo_mysql`, `curl`, `mbstring`, `bcmath`, `openssl`, `zlib`, `json` (+ `pcntl` که در بسته‌ی CLI هست، برای توقف تمیز Workerها).

## ۳. MySQL / MariaDB

```bash
sudo apt install -y mysql-server
sudo mysql
```

```sql
CREATE DATABASE gostardeh CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE USER 'gostardeh'@'localhost' IDENTIFIED BY '<یک رمز قوی>';
GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, ALTER, INDEX, DROP, REFERENCES, LOCK TABLES ON gostardeh.* TO 'gostardeh'@'localhost';
FLUSH PRIVILEGES;
```

حداقل نسخه: MySQL 8.0.16 یا MariaDB 10.5 (قیود `CHECK` باید اعمال شوند). موتور InnoDB.

## ۴. Redis

```bash
sudo apt install -y redis-server
sudo systemctl enable --now redis-server
```

در `/etc/redis/redis.conf`: `bind 127.0.0.1`، یک `requirepass` قوی، و `appendonly yes` (تا صف با ری‌استارت Redis از بین نرود). همان رمز را در `REDIS_PASSWORD` بگذارید.

## ۵. کد و Composer

```bash
sudo useradd --system --home /var/www/gostardeh --shell /usr/sbin/nologin gostardeh
sudo mkdir -p /var/www/gostardeh && sudo chown gostardeh: /var/www/gostardeh
# کد را در این مسیر کپی کنید، سپس:
sudo chown -R gostardeh: /var/www/gostardeh
```

Composer **اختیاری** است (پروژه وابستگی اجرایی ندارد). فقط اگر PHPUnit می‌خواهید:

```bash
sudo -u gostardeh composer install --no-interaction
```

روی Production: `composer install --no-dev --optimize-autoloader` یا اصلاً هیچ.

## ۶. تنظیمات

```bash
cd /var/www/gostardeh
sudo -u gostardeh cp .env.example .env && sudo chmod 600 .env
sudo -u gostardeh php bin/console key:generate
sudo -u gostardeh nano .env        # DB_*, REDIS_*, APP_URL, TELEGRAM_*, SUPER_ADMIN_IDS, درگاه‌ها
sudo -u gostardeh php bin/console migrate --seed
```

`APP_KEY` را جای امنی نگه دارید: بدون آن توکن ربات‌ها، شماره کارت‌ها و اطلاعات هویتیِ رمزشده قابل خواندن نیستند.

## ۷. PHP-FPM و Nginx

```bash
sudo cp deploy/php/gostardeh-fpm.conf /etc/php/8.3/fpm/pool.d/gostardeh.conf
sudo systemctl restart php8.3-fpm
sudo usermod -a -G gostardeh www-data
sudo cp deploy/nginx/gostardeh.conf /etc/nginx/sites-available/gostardeh.conf
sudo sed -i 's/bot\.example\.com/دامنه‌ی-شما/g' /etc/nginx/sites-available/gostardeh.conf
```

## ۸. SSL (Let's Encrypt)

```bash
sudo apt install -y certbot
sudo mkdir -p /var/www/letsencrypt
sudo certbot certonly --webroot -w /var/www/letsencrypt -d bot.example.com
sudo ln -s /etc/nginx/sites-available/gostardeh.conf /etc/nginx/sites-enabled/
sudo nginx -t && sudo systemctl reload nginx
```

اگر Nginx قبل از صدور گواهی بالا نمی‌آید، ابتدا فقط بلاک پورت ۸۰ را فعال کنید، گواهی را بگیرید و سپس بلاک ۴۴۳ را اضافه کنید. تمدید خودکار با `certbot.timer` انجام می‌شود؛ یک Hook برای `systemctl reload nginx` بگذارید.

## ۹. Workerها (Supervisor)

```bash
sudo apt install -y supervisor
sudo cp deploy/supervisor/gostardeh.conf /etc/supervisor/conf.d/
sudo supervisorctl reread && sudo supervisorctl update
sudo supervisorctl status 'gostardeh:*'
```

## ۱۰. Cron

```bash
sudo cp deploy/cron/gostardeh /etc/cron.d/gostardeh && sudo chmod 644 /etc/cron.d/gostardeh
```

## ۱۱. ربات و Webhook

```bash
sudo -u gostardeh php bin/console bot:add            # توکن را از TELEGRAM_BOT_TOKEN می‌خواند
sudo -u gostardeh php bin/console webhook:set        # https://<دامنه>/webhook/main + secret_token
sudo -u gostardeh php bin/console webhook:set --info
```

ربات را در @BotFather برای دریافت `chat_member` آماده نکنید؛ لازم نیست — `allowed_updates` هنگام `setWebhook` ارسال می‌شود. ولی ربات باید در کانال‌های تبلیغ‌شونده **ادمین** باشد تا رویداد Join/Leave برسد.

سپس خودتان ربات را `/start` کنید. شناسه‌ی عددی‌تان را در `SUPER_ADMIN_IDS` گذاشته‌اید، پس دکمه‌ی «🛠 پنل مدیریت» را می‌بینید. مدیران دیگر:

```bash
sudo -u gostardeh php bin/console admin:create 123456789 --role=finance
```

## ۱۲. بررسی نهایی

```bash
sudo -u gostardeh php bin/console health:check
curl -s https://bot.example.com/health
```

همه‌ی موارد باید `OK` باشند (تا وقتی درگاهی پیکربندی نشده، `payment_gateway` هشدار می‌دهد).

## تست روی MySQL (Staging)

مجموعه‌ی تست به‌صورت پیش‌فرض روی SQLite اجرا می‌شود (نیاز به `php8.3-sqlite3`). برای اطمینان از رفتار قفل‌ها (`SELECT … FOR UPDATE`) و قیود روی موتور واقعی، **قبل از Production** همان مجموعه را روی یک دیتابیس جدا اجرا کنید. نام دیتابیس باید به `_test` ختم شود، چون هر تست همه‌ی جدول‌ها را حذف و از نو می‌سازد:

```bash
sudo mysql -e "CREATE DATABASE gostardeh_test CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; GRANT ALL ON gostardeh_test.* TO 'gostardeh'@'localhost';"
export TEST_DB_DRIVER=mysql TEST_DB_HOST=127.0.0.1 TEST_DB_DATABASE=gostardeh_test TEST_DB_USERNAME=gostardeh
read -rs TEST_DB_PASSWORD && export TEST_DB_PASSWORD      # رمز را تایپ کنید؛ در history نمی‌ماند
php bin/console test
```

تست‌های `ConcurrencyTest` در این حالت چند پردازه‌ی واقعی را روی MySQL با هم رقابت می‌دهند (برداشت هم‌زمان، تأیید هم‌زمان پرداخت، تکمیل هم‌زمان کمپین، Join هم‌زمان).

سپس سناریوهای مالی را با یک ربات آزمایشی و درگاه Sandbox (`ZARINPAL_SANDBOX=true`) مرور کنید: شارژ، سفارش، Join/Leave، برداشت و رد برداشت.

## به‌روزرسانی

```bash
# کد جدید را جایگزین کنید، سپس
sudo bash scripts/deploy.sh      # backup → migrate → reload php-fpm → restart workers → health
```
