# Deployment Guide — Sama Baghdad (cPanel + PostgreSQL)
# دليل النشر — سما بغداد للصرافة (cPanel + PostgreSQL)

This guide walks you through deploying the **Sama Baghdad** currency-exchange
platform (Next.js 16 + Prisma + PostgreSQL) on a cPanel-hosted server.

> **TL;DR**
> 1. Create a PostgreSQL database + user in cPanel.
> 2. Import `sama_baghdad_postgresql.sql`.
> 3. Configure `.env`.
> 4. `bun install` → switch Prisma provider to `postgresql` → `bun run db:generate` → `bun run build`.
> 5. Start with PM2 or cPanel's Node.js app manager.

---

## 0. Prerequisites

| Requirement             | Version   | Notes                                                       |
|-------------------------|-----------|-------------------------------------------------------------|
| Node.js / Bun           | 18+ / 1.1+| Bun is the recommended runtime (faster, native TS support). |
| PostgreSQL              | 12+       | cPanel ships 13/14 by default.                              |
| cPanel                  | recent    | With "PostgreSQL Databases" + "Terminal" features enabled.  |
| SSH access              | optional  | Strongly recommended for `psql`, `pm2`, `bun`.              |
| Domain + SSL cert       | —         | Use AutoSSL in cPanel, or Let's Encrypt.                    |

---

## 1. Create the PostgreSQL database in cPanel

1. Log in to **cPanel**.
2. Go to **Databases → PostgreSQL Databases**.
3. Under **Create New Database**:
   - Database name: `sama_baghdad`
   - cPanel prefixes it with your username, so the full name becomes
     `<cpanel_user>_sama_baghdad`.
4. Under **Add New User**:
   - Username: `sama_admin`
   - Password: generate a strong password (save it — you need it in step 3).
5. Under **Add User to Database**:
   - Select `sama_admin` → `sama_baghdad`.
   - Tick **ALL PRIVILEGES** → click **Add**.

> **Tip:** cPanel PostgreSQL users can only connect from `localhost` by default,
> which is what we want (the Next.js app runs on the same host).

---

## 2. Import the SQL schema

You have two options.

### Option A — phpPgAdmin (web UI)

1. cPanel → **Databases → phpPgAdmin**.
2. Select your database (`<cpanel_user>_sama_baghdad`) on the left sidebar.
3. Click the **SQL** tab.
4. Open `/home/z/my-project/sama_baghdad_postgresql.sql`, copy its full contents,
   paste into the SQL box, and click **Go**.

### Option B — psql via SSH (recommended, faster)

```bash
ssh <cpanel_user>@yourdomain.com
cd ~/apps/sama_baghdad        # or wherever you deployed the repo
psql -U <cpanel_user>_sama_admin -d <cpanel_user>_sama_baghdad \
     -h localhost -f sama_baghdad_postgresql.sql
```

You should see a long stream of `CREATE TABLE` / `CREATE INDEX` / `INSERT 0 1`
messages with no errors. The final lines confirm the admin row + page-content
rows + 4 payment methods + 9 currencies + 6 services + 9 blocked countries + 6
terms rows have been seeded.

Verify the import:

```bash
psql -U <cpanel_user>_sama_admin -d <cpanel_user>_sama_baghdad -h localhost \
     -c "SELECT COUNT(*) FROM admins; SELECT COUNT(*) FROM currencies;"
-- Expect: 1 admin, 9 currencies
```

---

## 3. Configure environment variables

Create a `.env` file at the project root:

```bash
# Database (PostgreSQL on cPanel — note the cPanel username prefix)
DATABASE_URL="postgresql://<cpanel_user>_sama_admin:<DB_PASSWORD>@localhost:5432/<cpanel_user>_sama_baghdad?schema=public"

# NextAuth
NEXTAUTH_SECRET="<see step 6 — generate a 32-char secret>"
NEXTAUTH_URL="https://yourdomain.com"

# Node env
NODE_ENV="production"
```

> **Important:** the `?schema=public` query param is mandatory for Prisma +
> PostgreSQL. Do NOT omit it.

---

## 4. Switch Prisma provider + install + build

### 4a. Edit `prisma/schema.prisma`

Change the `datasource` block from SQLite to PostgreSQL:

```prisma
datasource db {
  // Production: PostgreSQL on cPanel. Dev: switch back to "sqlite".
  provider = "postgresql"
  url      = env("DATABASE_URL")
}
```

> If you want to keep using SQLite for local dev, copy `schema.prisma` to
> `schema.dev.prisma` and use `--schema=` flag, or commit two branches.

### 4b. Install dependencies

```bash
bun install
```

### 4c. Regenerate the Prisma client

```bash
bun run db:generate
```

This regenerates `node_modules/.prisma/client` with the PostgreSQL adapter.

### 4d. (Optional) Re-seed to regenerate the admin password

The SQL file already ships with a valid Argon2id hash of `admin123`. If you
prefer a freshly-salted hash on your server:

```bash
bun run db:seed
```

The seed script is fully idempotent — it uses `upsert` with `update: {}`, so
running it on top of an already-imported SQL file is a no-op (it won't
overwrite any customizations).

### 4e. Build the Next.js app

```bash
bun run build
```

This produces `.next/standalone/` (a self-contained Node server bundle).

---

## 5. Start the server

### Option A — PM2 (recommended for SSH users)

```bash
# Install PM2 globally (one-time)
bun add -g pm2

# Start the Next.js standalone server
cd /path/to/project
NODE_ENV=production pm2 start .next/standalone/server.js \
  --name "sama-baghdad" \
  --env production

# Save PM2 process list so it auto-restarts on reboot
pm2 save
pm2 startup    # follow the printed instructions to enable boot-on-start
```

Make sure your reverse proxy (Nginx in cPanel, or Caddy) routes HTTPS traffic
from your domain to `127.0.0.1:3000`.

### Option B — cPanel Node.js App Manager

1. cPanel → **Software → Setup Node.js App**.
2. **Create Application**:
   - Node.js version: 18 or 20
   - Application mode: **Production**
   - Application root: `/home/<user>/apps/sama_baghdad`
   - Application URL: `https://yourdomain.com`
   - Application startup file: `server.js` (inside `.next/standalone/`)
3. Under **Environment variables**, add the same vars from `.env`:
   `DATABASE_URL`, `NEXTAUTH_SECRET`, `NEXTAUTH_URL`, `NODE_ENV=production`.
4. Click **Run NPM Install** (or run `bun install` from the cPanel Terminal).
5. Click **Start App**.

cPanel will run the app under Phusion Passenger with the `PORT` env var
auto-set — your `next.config.ts` and `server.js` already honour it.

---

## 6. Generate the NextAuth secret

The `NEXTAUTH_SECRET` is used to sign JWT cookies — without it, login will fail
silently. Generate a strong random secret:

```bash
openssl rand -base64 32
# Example output: K7s8L9pQ2vX1mZ0aB3cD4eF5gH6iJ7kL8mN9oP0qR1sT=
```

Paste the output (including `=` if present) as the value of
`NEXTAUTH_SECRET` in your `.env` file (or cPanel env-vars UI).

---

## 7. Reverse proxy + HTTPS

### Apache (default cPanel)

cPanel auto-creates the vhost for your domain. You just need to proxy `/`
to the Node.js app. Add to your `.htaccess` in `public_html/`:

```apache
RewriteEngine On
RewriteRule ^(.*)$ http://127.0.0.1:3000/$1 [P,L]
```

Or use the cPanel **Application URL** feature (recommended — handles the
proxy automatically when you set up the Node.js app).

### Force HTTPS

cPanel → **Domains → Domains** → toggle **Force HTTPS Redirect** to **On**.
Or use **SSL/TLS Status → Run AutoSSL** to provision a free Let's Encrypt cert.

---

## 8. Post-deploy checklist

| # | Task                                                          | Done |
|---|---------------------------------------------------------------|------|
| 1 | **Change admin password** — log in (`admin` / `admin123`) → Profile → Change password | ☐ |
| 2 | **Set up SSL/HTTPS** — AutoSSL or Let's Encrypt                 | ☐ |
| 3 | **Configure payment methods** — Admin → Payment Methods → edit the 4 default rows with real account numbers + barcode images | ☐ |
| 4 | **Configure bank accounts** — Admin → Bank Accounts → set real account numbers, card numbers, FIB barcode | ☐ |
| 5 | **Set WhatsApp number** — Admin → Settings → Contact → real WhatsApp number (used for order SMS) | ☐ |
| 6 | **Telegram bot** (optional) — Admin → Settings → Telegram → paste `bot_token` + `chat_id` → toggle enabled | ☐ |
| 7 | **SMS provider** (optional) — Admin → Settings → SMS → pick provider (clickatell/infobip/twilio/messagebird) → paste API key + sender | ☐ |
| 8 | **Email provider** (optional) — Admin → Settings → Email → pick provider (mailtrap/smtp/resend) → paste API key + from/to | ☐ |
| 9 | **Set exchange-rate API key** (optional) — Admin → Settings → Currency API → paste exchangerate-api.com key for live rates | ☐ |
| 10 | **Edit homepage CMS** — Admin → Pages → Home → set hero title, subtitle, services, footer, main color (#d4af37 by default) | ☐ |
| 11 | **Edit dollar page** — Admin → Pages → Dollar → set banner image, title, amount options, receive locations | ☐ |
| 12 | **Verify limits** — Admin → Limits → confirm dollar=1000, alipay=100, alibaba=100, western=1000, bank=1000, enter=20000 | ☐ |
| 13 | **Verify currencies** — Admin → Currencies → check 9 default rows; update buy/sell prices to current market rates | ☐ |
| 14 | **Verify blocked countries** — Admin → Blocked Countries → 9 default countries listed; add/remove as needed | ☐ |
| 15 | **Verify terms** — Admin → Terms → 6 default term docs (general/dollar/money/cards/alibaba/alipay); edit as needed | ☐ |
| 16 | **Test order flow** — place a test dollar order, test western order, test card top-up, verify admin receives them | ☐ |
| 17 | **Test tracking page** — place an order, then visit `/tracking` and look it up by order number | ☐ |
| 18 | **Test admin login from a fresh browser** — confirm `admin` / your-new-password works | ☐ |
| 19 | **Backups** — set up a daily PostgreSQL backup via cPanel → Backup → Generate Backup, or `pg_dump` cron | ☐ |
| 20 | **Monitor logs** — `pm2 logs sama-baghdad` or cPanel → Terminal → `tail -f server.log` | ☐ |

---

## 9. Common issues + fixes

### 9a. `PrismaClientInitializationError: Can't reach database server`

- Confirm `DATABASE_URL` uses `localhost` (not `127.0.0.1` if cPanel's pg_hba
  is restrictive — try both).
- Confirm the cPanel PostgreSQL user has `ALL PRIVILEGES` on the database
  (re-check in cPanel → PostgreSQL Databases → **Current Databases**).
- Confirm PostgreSQL is running: cPanel → Service Status (or ask your host).

### 9b. `relation "admins" does not exist`

- You imported the SQL into the wrong database. Re-check the database name in
  `.env` (it should be `<cpanel_user>_sama_baghdad`, with the cPanel prefix).
- You imported into the `postgres` default DB by mistake. Re-import into the
  right DB.

### 9c. `password authentication failed for user`

- The password in `DATABASE_URL` is URL-encoded incorrectly. If your password
  contains special chars (`@`, `#`, `:`, `/`, `?`), percent-encode them
  (e.g. `@` → `%40`).
- Or — simpler — change the DB user password in cPanel to one without
  special chars, then update `.env`.

### 9d. `NEXTAUTH_SECRET is missing`

- The `.env` file isn't being loaded. With PM2: make sure you `cd` into the
  project dir before `pm2 start`. With cPanel App Manager: re-enter the env
  vars in the UI and click **Restart**.

### 9e. Admin login button does nothing / `CredentialsSignin` error

- The admin password hash in the DB is invalid. Run `bun run db:seed` to
  regenerate it (this won't overwrite an existing admin row — to force
  regeneration, run:
  ```bash
  psql -U <user>_sama_admin -d <user>_sama_baghdad -h localhost \
       -c "DELETE FROM admins WHERE username='admin';"
  bun run db:seed
  ```
- Or — simpler — change the password via the **forgot password** flow if
  implemented, or directly update via SQL with a freshly-generated hash:
  ```bash
  bun -e "const {hash} = require('@node-rs/argon2'); hash('NEW_PASSWORD', {algorithm: 2, memoryCost: 19456, timeCost: 2, parallelism: 1}).then(h => console.log(h))"
  # Then:
  psql -c "UPDATE admins SET password='<hash>' WHERE username='admin';"
  ```

### 9f. Arabic text shows as `?????` or `Ø³Ù…Ø§`

- The database encoding is not UTF-8. Recreate it with:
  ```sql
  -- In psql (as superuser):
  ALTER DATABASE <db> SET client_encoding TO 'UTF8';
  ```
- Or, in cPanel, when creating the DB, pick **UTF-8** as the encoding (it's
  the default for PostgreSQL 12+, so this is rarely an issue).

### 9g. Build fails with `@node-rs/argon2` native module error

- Make sure your server architecture matches the build env (`linux-x64-gnu`
  vs `linux-arm64-gnu`). Run `uname -m` on the server; if it's `aarch64`,
  do a clean `rm -rf node_modules && bun install` on the server itself.
- If using cPanel App Manager: upload `node_modules` from the same arch.

### 9h. PGlite / pgsql-parser used during dev

- These were dev-only tools used to validate the SQL file during task DB-SQL-1.
- They are NOT in `package.json` and are NOT needed in production.

---

## 10. File locations (reference)

| File                              | Purpose                                        |
|-----------------------------------|------------------------------------------------|
| `sama_baghdad_postgresql.sql`     | Schema + seed data — import via psql/phpPgAdmin |
| `prisma/schema.prisma`            | Prisma schema (31 models, mirrors the SQL)     |
| `prisma/seed.ts`                  | Idempotent seed script (run with `bun run db:seed`) |
| `prisma/seed-terms.ts`            | Terms-conditions seed (run separately if needed) |
| `src/lib/db.ts`                   | Prisma client singleton                        |
| `src/lib/auth/password.ts`        | Argon2id hash/verify helpers                   |
| `src/lib/auth/config.ts`          | NextAuth credentials provider                  |
| `src/middleware.ts`               | Auth middleware (protects `/admin/*`)          |
| `.env`                            | Environment variables (DB URL, secrets)        |
| `start-server.sh`                 | Shell wrapper for `bun .next/standalone/server.js` |

---

## 11. Rollback / disaster recovery

### Daily backup (cron)

Add to crontab (`crontab -e`):

```cron
0 3 * * *  pg_dump -U <user>_sama_admin -h localhost <user>_sama_baghdad | gzip > /home/<user>/backups/sama_$(date +\%Y\%m\%d).sql.gz
0 4 * * *  find /home/<user>/backups/ -name 'sama_*.sql.gz' -mtime +14 -delete
```

### Restore from backup

```bash
gunzip -c /home/<user>/backups/sama_20250515.sql.gz | \
  psql -U <user>_sama_admin -d <user>_sama_baghdad -h localhost
```

### Reset to fresh state (DESTRUCTIVE)

```bash
psql -U <user>_sama_admin -d <user>_sama_baghdad -h localhost \
     -f sama_baghdad_postgresql.sql
# This drops all 31 tables and recreates them with seed defaults.
```

---

## 12. Support

- **Schema questions:** see comments at the top of `sama_baghdad_postgresql.sql`.
- **Seed data questions:** see `prisma/seed.ts` and `prisma/seed-terms.ts`.
- **App architecture:** see `worklog.md` (task ANALYSIS-1 + downstream tasks).
- **Original PHP source:** preserved at `/tmp/sama-analysis/` for reference.

---

**Generated by Task DB-SQL-1.** Last updated: see `worklog.md` for the latest
task log.
