# cPanel shared hosting e setup

`docs/SETUP.md` local development er jonno. Eta cPanel er jonno — kichu jinis
sompurno alada bhabe korte hoy, karon shared hosting e supervisor nai, Node nai,
ar prai shob khetre Postgres nai.

---

## 0. Age check korun — hosting ta kaj korbe to?

cPanel e login kore ei tin ta check korun. **Ei tinta na thakle project ta cholbe na**,
tokhon host change kora chara upay nai.

| Kothay | Ki dekhben | Lagbe |
|---|---|---|
| **Select PHP Version** (ba MultiPHP Manager) | PHP version | **8.2 ba 8.3** |
| **Terminal** | ache ki nai | Thakle onek shoja. Na thakle §3 dekhen |
| **Cron Jobs** | ache ki nai | **Must.** Eta chara subscription bill hobe na |

PHP 8.1 ba tar niche hole Laravel 12 install-i hobe na. Ei khetre host ke bolen
upgrade dite, ba host change korun.

### Extension on korun

**Select PHP Version → Extensions** tab. Ei gulo tick kora ache kina dekhen:

```
pdo_mysql   mbstring   gd   zip   intl   dom   xml   curl   fileinfo   bcmath   openssl
```

`intl` ar `dom` prai bhule jay manush — `dom` chara invoice PDF banabe na.

---

## 1. Postgres nai — MySQL e cholbe

Shared hosting e Postgres prai kokhono thake na. Ami code ta already **duitatei cholar
moto** kore diyechi — `app/Support/Sql.php` driver dekhe nije adjust kore ney (`ILIKE`
vs `LIKE`, `TO_CHAR` vs `DATE_FORMAT`).

Apnar kichu change korte hobe na. Sudhu `.env` e MySQL boshaben:

```env
DB_CONNECTION=mysql
DB_HOST=localhost
DB_PORT=3306
DB_DATABASE=cpanelusername_petalair
DB_USERNAME=cpanelusername_petalair
DB_PASSWORD=strong_password_ekhane
```

> **Database name e prefix ta khyal korben.** cPanel automatically apnar username
> prefix hisebe lagiye dey. cPanel e `petalair` likhle asol name hoy
> `myuser_petalair` — `.env` e **puro name ta** dite hobe.

### Database banan

**cPanel → MySQL® Databases**:

1. "Create New Database" — name: `petalair`
2. "Add New User" — username `petalair`, ekta strong password
3. "Add User To Database" — user ta database e add korun, tarpor **ALL PRIVILEGES** tick

---

## 2. File upload — document root er jhamela

Ei step tai shobcheye beshi bhul hoy, ar bhul korle **`.env` file ta internet theke
download kora jabe** — apnar database password soho. Mon diye porun.

Laravel er `/public` folder ta-i web theke dekha jawa uchit. Baki shob — `app/`,
`.env`, `vendor/` — **web root er baire thakte hobe**.

### Option A — Addon/subdomain (shobcheye bhalo, ei ta korun)

cPanel e domain add korar somoy "Document Root" field e `/public` add kore dite paren:

```
Document Root:  petalair/public          ← /public soho
```

Tarpor project ta `/home/username/petalair/` e upload korun. Web sudhu `public/`
dekhbe, baki shob lukano. **Ei ta i best.**

### Option B — Main domain, root already `public_html`

Main domain er docroot change kora jay na. Tokhon:

1. Project ta `/home/username/petalair/` e rakhun (`public_html` er baire)
2. `petalair/public/` er **bhitorer shob file** `public_html/` e copy korun
3. `public_html/index.php` edit korun — duita line:

```php
// age chilo:
require __DIR__.'/../vendor/autoload.php';
$app = require_once __DIR__.'/../bootstrap/app.php';

// eta korun:
require __DIR__.'/../petalair/vendor/autoload.php';
$app = require_once __DIR__.'/../petalair/bootstrap/app.php';
```

### Upload kivabe

**File Manager → Upload** e zip ta upload kore **Extract** korun. Ek ek kore FTP te
1000+ file dile ek ghonta lagbe ar majhe connection drop korbe.

---

## 3. Composer — Terminal ache kina tar upor

### Terminal thakle (shoja)

```bash
cd ~/petalair
composer install --no-dev --optimize-autoloader
```

`composer: command not found` dile:

```bash
curl -sS https://getcomposer.org/installer | php
php composer.phar install --no-dev --optimize-autoloader
```

### Terminal na thakle

Nijer computer e `vendor/` banie upload korun:

```bash
# apnar laptop e
composer install --no-dev --optimize-autoloader
zip -r vendor.zip vendor
# tarpor File Manager diye upload + extract
```

> ⚠️ Local e PHP version ar server er PHP version **ek** hote hobe. Local e 8.3 ar
> server e 8.2 hole vendor ta bhengey jabe. Local e PHP 8.2 na thakle:
> `composer install --no-dev --optimize-autoloader --ignore-platform-req=php`
> — kintu ei khetre ektu test kore niyen.

---

## 3.5. Notun feature er migration

Menu ar Page feature dutor jonno notun table lage. Purano data thakle
`migrate:fresh` **cholbe na** — sudhu notun migration ta chalan:

```bash
php artisan migrate
php artisan db:seed --class=MenuSeeder   # header/footer menu bhore dey
php artisan optimize:clear
```

`MenuSeeder` idempotent — bar bar chalale duplicate hobe na.

## 4. Assets — kichu korte hobe na, already build kora

**Node lagbe na. Vite nai. `npm` chalate hobe na.**

`public/css/app.css` (36KB, minified Tailwind) ar `public/js/app.js` **already
compile kora obosthay zip er bhitore ache**. Layout gulo shoja `asset()` diye load
kore — apnar ager project e jevabe chilo:

```blade
<link rel="stylesheet" href="{{ asset('css/app.css') }}?v={{ @filemtime(public_path('css/app.css')) ?: '1' }}">
```

Ei `?v=filemtime` ta cache-bust kore — file change hole browser nijei notun ta nibe.

### Sudhu design change korle

Tokhon **kono ek ta machine e** (server e na) Node lagbe:

```bash
npm install
npm run build      # public/css/app.css regenerate hobe
```

Tarpor sudhu `public/css/app.css` file ta re-upload korun. `resources/css/app.css`
holo source — `public/css/app.css` output, ota hate edit korben na.

Design e hat na dile ei ongsho ta apnar kono din lagbe na.

---

## 5. Setup command gulo

Terminal thakle:

```bash
cd ~/petalair
cp .env.example .env
php artisan key:generate
php artisan migrate --seed
php artisan storage:link
```

**Terminal na thakle** — cPanel → Cron Jobs e ekta temporary cron banie ek bar chalan:

```
Minute: *  Hour: *  Day: *  Month: *  Weekday: *
Command: cd /home/username/petalair && /usr/local/bin/php artisan migrate --force --seed
```

Ek minute pore email e output ashbe. Tarpor **cron ta delete kore dite bhulben na** —
noile protti minute e migrate chalate thakbe.

`key:generate` o eibhabe. Ba shoja: nijer laptop e `php artisan key:generate` chalie
`.env` er `APP_KEY=base64:...` line ta copy kore server er `.env` e boshie den.

### storage:link kaj na korle

Onek shared host e `symlink()` disable kora. Tokhon product image dekhabe na. Fix:
`public_html/storage` name e ekta folder banie `storage/app/public` er content
copy korun — ba host ke bole `symlink()` on korte bolun (bhodro bhabe bollei prai
kore dey).

---

## 6. Queue — supervisor nai, cron diye

Shared hosting e supervisor nai. Duita option:

### Option A — cron diye queue chalan (**recommended**)

cPanel → Cron Jobs:

```
Minute: * (protti minute)
Command: cd /home/username/petalair && /usr/local/bin/php artisan queue:work --stop-when-empty --max-time=55 >> /dev/null 2>&1
```

`--stop-when-empty` mane queue faka hole nijei bondho hoye jabe, `--max-time=55` mane
55 second er beshi cholbe na — tai duita worker ek shathe cholbe na. Email ashte
sorbocho ek minute deri hobe, ja invoice email er jonno puropuri thik ache.

### Option B — sync (shoja, kintu slow)

```env
QUEUE_CONNECTION=sync
```

Email queue e na giye sathe sathe pathabe. Kono cron lagbe na. Kintu customer
checkout button chapar por email pathano ses na howa porjonto page ta ghurte thakbe —
SMTP slow hole 3-5 second. Chhoto site e chole, kintu Option A obviously bhalo.

---

## 7. Cron — ei ta bad dile subscription bill hobe na

Ei ta **optional na**. Eta chara auto-billing kono din cholbe na, ar kono error o
dekhabe na — chup kore boshe thakbe.

cPanel → **Cron Jobs** → Add New Cron Job:

```
Common Settings: Once Per Minute (* * * * *)

Command:
cd /home/username/petalair && /usr/local/bin/php artisan schedule:run >> /dev/null 2>&1
```

**PHP path ta thik kina check korun.** cPanel e version-specific path lage:

```
/usr/local/bin/php                        # common
/opt/cpanel/ea-php82/root/usr/bin/php     # cPanel EasyApache, PHP 8.2
```

Terminal e `which php` diye ber korun. Bhul path dile cron chup kore fail korbe —
tai prothom bar `>> ~/cron.log 2>&1` diye output rakhen, kaj korche dekhe tarpor
`/dev/null` e nen.

Verify:

```bash
php artisan schedule:list
php artisan petalair:bill-subscriptions --dry-run   # kichu change korbe na
```

---

## 8. Permission

File Manager e:

```
storage/            → 755 (recursive)
bootstrap/cache/    → 755
.env                → 600     ← important
```

Terminal thakle:

```bash
chmod -R 755 storage bootstrap/cache
chmod 600 .env
```

Kokhono `777` diben na. Onek tutorial e lekha thake — shared hosting e 777 mane
same server er onno account theke apnar file lekha jabe.

---

## 9. Production `.env`

```env
APP_ENV=production
APP_DEBUG=false
APP_URL=https://petalair.com

DB_CONNECTION=mysql
DB_HOST=localhost
DB_DATABASE=cpaneluser_petalair
DB_USERNAME=cpaneluser_petalair
DB_PASSWORD=...

# cPanel er nijer email account use korte paren
MAIL_MAILER=smtp
MAIL_HOST=mail.petalair.com
MAIL_PORT=465
MAIL_USERNAME=hello@petalair.com
MAIL_PASSWORD=...
MAIL_SCHEME=smtps
MAIL_FROM_ADDRESS=hello@petalair.com

QUEUE_CONNECTION=database
SESSION_DRIVER=database
CACHE_STORE=database
```

Tarpor cache korun (site fast hobe):

```bash
php artisan config:cache
php artisan route:cache
php artisan view:cache
```

> `.env` change korar por **obossoi** `php artisan config:cache` abar chalate hobe,
> noile purono value thekei jabe. Eta niye onek somoy nosto hoy.

---

## 10. SSL

cPanel → **SSL/TLS Status** → "Run AutoSSL". Free Let's Encrypt certificate.

Tarpor `.env` e `APP_URL=https://...` (http na) — code e `URL::forceScheme('https')`
already ache production er jonno.

---

## 11. Go-live checklist

- [ ] PHP 8.2+, shob extension on
- [ ] Document root `/public` e (ba §2 Option B kora) — `yoursite.com/.env` browser e
      khule dekhen, **404 ashte hobe**. File download hole ekhoni thamun ar §2 abar poren.
- [ ] `APP_DEBUG=false`
- [ ] `admin@petalair.com` er password change (default `password`)
- [ ] Demo data delete
- [ ] Cron boshano ar test kora
- [ ] Queue cron boshano (ba `QUEUE_CONNECTION=sync`)
- [ ] Ekta test invoice email pathiye dekha
- [ ] `public/css/app.css` upload kora
- [ ] `storage:link` kaj korche — ekta product image dekha jacche
- [ ] SSL on
- [ ] `.env` permission 600

---

## 12. Shared hosting e ki ki problem hobe (age theke jene rakhen)

Sotti kotha bolchi — shared hosting e ei project ta **cholbe**, kintu kichu limit ache:

- **Design change korle protti bar local e build kore upload** korte hobe. Ekta command
  na, ekta ritual.
- **Cron er choto deri** — invoice email ek minute pore jete pare. Somossa na.
- **Memory limit.** Shared hosting e prai 128MB. Report page e 5000+ order hole slow
  hote pare. Ekhon somossa hobe na, kintu 2-3 bochor por hote pare.
- **`exec()` / `symlink()` disabled** thakte pare. Tokhon `storage:link` er bodole
  manual folder (§5).
- **MySQL 5.6** hole migrate fail korbe (`key was too long`). Ei khetre host er kache
  MySQL 5.7+ ba MariaDB 10.2+ chan. Ami `defaultStringLength(191)` already boshie
  rekhechi, tai bhalo chance ache chole jabe.

Client er business jokhon barbe — mash e 500+ order, ba 50+ subscription — tokhon ekta
**VPS** (DigitalOcean/Vultr, mash e ~$6-12) e shift korle onek shoja hoye jabe:
supervisor thakbe, Node thakbe, deploy ekta `git pull` hobe. Kintu **ekhon shuru korar
jonno shared hosting puropuri thik ache** — age site ta chalu koren, business barle
tokhon move korben. Age theke VPS niye boshe thaka manei taka nosto.

---

## 13. Common error

| Error | Karon | Fix |
|---|---|---|
| CSS load hocche na | `public/css/app.css` upload hoy nai | §4 |
| `500` ar kichu na | `storage/` writable na | `chmod -R 755 storage` |
| `.env` browser e download hocche | Document root bhul | **ekhoni** §2 |
| `SQLSTATE[HY000] [1045] Access denied` | DB user er prefix bhul | `.env` e `cpaneluser_petalair` |
| `Specified key was too long` | MySQL 5.6 | Host ke bolen upgrade dite |
| `Class "DOMDocument" not found` | `dom` extension off | Select PHP Version → tick |
| Email jacche na | Queue cron nai | §6 |
| Subscription bill hocche na | schedule:run cron nai | §7 |
| `.env` change korlam, kaj hocche na | Config cached | `php artisan config:cache` |
| `Please provide a valid cache path` | `storage/framework/views` folder nai | Banie `755` diyen |
