# Deploying MyBookingsHub on cPanel (Node.js)

This app is a Noderyx Framework server (`server.js`, ESM, Node 20+) backed by MySQL.
It must run as a **Node.js application**, not as static/PHP hosting.

## 0. Requirements

- cPanel with **Setup Node.js App** (CloudLinux Node.js Selector). If the icon is
  missing, ask the host to enable it — PHP-only plans cannot run this.
- Node.js **20 or newer** (`package.json` → `engines.node: >=20`, and the code uses
  ESM + top-level `await`).
- MySQL database (cPanel → MySQL® Databases).
- SSH or cPanel **Terminal** access — needed to run migrations/seeders.

---

## 1. Package the project

Create a ZIP from the project root **excluding**:

```
node_modules/
.git/
.env
.chrome-*/
*.png                  (screenshots in the repo root)
server-error.log
server-out.log
database/*.sqlite*
public/generated/
{if(typeof         (stray zero-byte file, do not upload)
```

Must be included: `server.js`, `noderyx.config.js`, `package.json`,
`package-lock.json`, `app/`, `routes/`, `resources/`, `public/`, `database/`,
`packages/`, `tooling/`, `scripts/`.

Never upload the local `.env` — production values go in the cPanel env-var fields
(step 4). Treat the `APP_KEY` in the local `.env` as a dev-only key.

---

## 2. Upload and extract

1. cPanel → **File Manager**.
2. Create the application folder **outside** `public_html`, e.g.
   `/home/USER/mybookingshub`.
3. Upload the ZIP there and **Extract**.
4. Confirm `server.js` sits directly in `/home/USER/mybookingshub/`.

Keeping the app out of `public_html` prevents source files and `.env` from being
served over HTTP.

---

## 3. Create the MySQL database

cPanel → **MySQL® Databases**:

1. Create database: `USER_mybookingshub`
2. Create user: `USER_mbh` with a strong password
3. **Add User To Database** → **ALL PRIVILEGES**

Note the real prefixed names — cPanel prepends your account name. Do **not** run
`npm run db:create` here; that script is for local development.

---

## 4. Create the Node.js application

cPanel → **Setup Node.js App** → **Create Application**:

| Field | Value |
|---|---|
| Node.js version | 20.x or newer |
| Application mode | Production |
| Application root | `mybookingshub` |
| Application URL | your domain / subdomain |
| Application startup file | `server.js` |

Then add the environment variables below (**Add Variable** for each).

**Do not set `PORT`** — Passenger/cPanel injects it and `server.js` reads
`process.env.PORT`. Leave `HOST` unset too (defaults to `0.0.0.0`).

```
NODE_ENV=production
APP_DEBUG=false
APP_KEY=<generate, see below>
APP_NAME=MyBookingsHub
APP_URL=https://your-domain.com
APP_TIMEZONE=Asia/Colombo
APP_LOCALE=en
LOG_LEVEL=info

SITE_NAME=MyBookingsHub
SITE_URL=https://your-domain.com
SITE_DESCRIPTION=Find hotels, apartments and unique stays across Sri Lanka.
SUPPORT_EMAIL=support@mybookingshub.com
SUPPORT_PHONE=+94 11 234 5678

DB_TYPE=mysql
DB_HOST=localhost
DB_PORT=3306
DB_USER=USER_mbh
DB_PASSWORD=<db password>
DB_NAME=USER_mybookingshub
DB_POOL_MAX=10

TRUST_PROXY=true
SESSION_SECURE=true
SESSION_COOKIE=noderyx_session
SESSION_SAME_SITE=Lax
CACHE_DRIVER=memory
RATE_LIMIT_MAX=300
AI_ENABLED=false
```

`TRUST_PROXY=true` and `SESSION_SECURE=true` matter: the app sits behind Apache,
so without them logins over HTTPS can fail and client IPs will be wrong.

### Generate APP_KEY

`server.js` starts with `requireAppKey: true` — the app will not boot without it.
Generate a fresh one (locally or in cPanel Terminal):

```bash
node -e "console.log(require('crypto').randomBytes(32).toString('base64url'))"
```

Paste the output as `APP_KEY`. Use a **new** key for production, not the dev one.

---

## 5. Install dependencies

In **Setup Node.js App**, click **Run NPM Install**.

Or from cPanel Terminal — copy the "Enter to the virtual environment" command
shown at the top of the app's page, then:

```bash
source /home/USER/nodevenv/mybookingshub/20/bin/activate && cd /home/USER/mybookingshub
npm ci --omit=dev
```

---

## 6. Run migrations and seeders

Still inside the virtual environment (same `source ...` line as above):

```bash
npm run migrate     # creates all tables from database/migrations
npm run seed        # optional: demo modules, hotels, offers, users
```

Run `npm run seed` only on a fresh install — it inserts sample catalog data.

---

## 7. Start and verify

1. Back in **Setup Node.js App**, click **Restart**.
2. Open `https://your-domain.com/health` — a healthy deploy returns JSON with
   `"status":"ok"`.
3. Then check `/`, `/owner/login`, `/customer/login`, and `/admin/hotels`.

Static assets under `public/` are served by the Node app itself; no extra Apache
config is required. If the domain root shows a default cPanel page instead of the
app, delete or rename `public_html/index.html`.

---

## 8. Updating a live deployment

1. Upload changed files (File Manager or `git pull` over SSH).
2. Run `npm ci --omit=dev` **only if** `package.json` changed.
3. Run `npm run migrate` if new files were added to `database/migrations/`.
4. **Restart Application**.

---

## Troubleshooting

| Symptom | Cause / fix |
|---|---|
| 503 Service Unavailable | App crashed on boot. Check `stderr.log` in the app root and `~/logs/`. |
| `APP_KEY` / app key error | `APP_KEY` env var missing — `requireAppKey: true` in `server.js`. |
| `Cannot use import statement` / syntax errors | Node version below 20 selected. |
| `ECONNREFUSED 3306` | Use `DB_HOST=localhost`; verify prefixed DB and user names. |
| `ER_ACCESS_DENIED` | User not attached to the database with ALL PRIVILEGES. |
| Login redirects in a loop | Set `TRUST_PROXY=true` and `SESSION_SECURE=true` (HTTPS only). |
| Table doesn't exist | Migrations were never run (step 6). |
| CSS/JS 404 | `public/` was excluded from the ZIP. |
| Port already in use | You set `PORT` manually — remove it; cPanel supplies it. |

---

# Appendix A — Command-line setup (without the Node.js App UI)

**This app requires Node.js on the server.** It is a Node HTTP server; there is no
PHP equivalent. If the host provides no Node.js at all, no command will run it —
the options are to ask the host to enable Node.js, or move to a host/VPS that has
it. Everything below assumes Node exists but you are working from a terminal
instead of the cPanel UI.

Which path applies depends on your access:

| Your access | Use |
|---|---|
| root / WHM SSH | **A.1** — `cloudlinux-selector`, the full CLI equivalent of the UI |
| Normal cPanel user + SSH/Terminal | **A.2** — the app must be created once in the UI; everything else is CLI |
| No Node.js Selector on the server at all | **A.3** — self-managed process + reverse proxy (fragile, often blocked) |

---

## A.1 Root: full setup via `cloudlinux-selector`

`cloudlinux-selector` is a **root-only** tool — run it as root over SSH, not from
the cPanel user's Terminal. Replace `USER` and `example.com` throughout.

Create the application (equivalent of step 4):

```bash
cloudlinux-selector create --json --interpreter nodejs \
  --user USER \
  --app-root mybookingshub \
  --app-uri "/" \
  --app-mode production \
  --version 20 \
  --startup-file server.js \
  --domain example.com
```

Set the environment variables (one call, JSON object — same values as step 4):

```bash
cloudlinux-selector set-env-vars --json --interpreter nodejs \
  --user USER --app-root mybookingshub \
  --env-vars '{"NODE_ENV":"production","APP_DEBUG":"false","APP_KEY":"PASTE_GENERATED_KEY","APP_NAME":"MyBookingsHub","APP_URL":"https://example.com","APP_TIMEZONE":"Asia/Colombo","SITE_NAME":"MyBookingsHub","SITE_URL":"https://example.com","DB_TYPE":"mysql","DB_HOST":"localhost","DB_PORT":"3306","DB_USER":"USER_mbh","DB_PASSWORD":"DB_PASSWORD","DB_NAME":"USER_mybookingshub","TRUST_PROXY":"true","SESSION_SECURE":"true","AI_ENABLED":"false"}'
```

Install dependencies, then start:

```bash
cloudlinux-selector install-modules --json --interpreter nodejs \
  --user USER --app-root mybookingshub

cloudlinux-selector start --json --interpreter nodejs \
  --user USER --app-root mybookingshub
```

Run the migrations through the app's own npm scripts:

```bash
cloudlinux-selector run-script --json --interpreter nodejs \
  --user USER --app-root mybookingshub --script migrate

# optional demo data, fresh installs only
cloudlinux-selector run-script --json --interpreter nodejs \
  --user USER --app-root mybookingshub --script seed
```

Restart after any change:

```bash
cloudlinux-selector restart --json --interpreter nodejs \
  --user USER --app-root mybookingshub
```

The MySQL database itself is still created in cPanel → MySQL® Databases (step 3),
or as root with `uapi --user=USER Mysql create_database name=USER_mybookingshub`.

---

## A.2 Normal cPanel user: CLI for everything except creation

A non-root user cannot run `cloudlinux-selector`. The application entry has to be
created **once** in **Setup Node.js App** (step 4) — that is what builds the
`nodevenv` and wires Apache to the app. After that, nothing else needs the UI.

Enter the virtual environment (copy the exact `source` line from the app's page;
the `20` is the Node version directory):

```bash
source /home/USER/nodevenv/mybookingshub/20/bin/activate
cd /home/USER/mybookingshub
```

Then work normally:

```bash
node -v                    # confirm 20+
npm ci --omit=dev          # install dependencies
npm run migrate            # create tables
npm run seed               # optional demo data
```

Restart the app **without the UI** by touching Passenger's restart file:

```bash
mkdir -p /home/USER/mybookingshub/tmp
touch /home/USER/mybookingshub/tmp/restart.txt
```

Passenger picks that up on the next request — this is the CLI equivalent of the
**Restart** button. Read logs with:

```bash
tail -n 100 /home/USER/mybookingshub/stderr.log
```

Environment variables still have to be set in the UI on this path, **or** by
placing a `.env` file in the app root — `loadEnvironment()` in
[server.js](../server.js) reads it. If you use `.env`, keep the app root outside
`public_html` (step 2) so the file is never web-accessible, and `chmod 600` it.

---

## A.3 No Node.js Selector: self-managed process + proxy

Only worth attempting on a VPS or a host that permits long-running user
processes. Most shared cPanel plans kill background processes and disable
`mod_proxy`, in which case this will not work and the host must enable Node.js.

Install Node in your home directory:

```bash
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.1/install.sh | bash
source ~/.bashrc
nvm install 20
```

Configure the app to listen on loopback only — create `/home/USER/mybookingshub/.env`
with the step-4 values plus:

```
HOST=127.0.0.1
PORT=3000
```

Both are read by [server.js](../server.js). Install and run under a supervisor:

```bash
cd /home/USER/mybookingshub
npm ci --omit=dev
npm run migrate
npm install -g pm2
pm2 start server.js --name mybookingshub
pm2 save
pm2 startup          # prints a command; needs root to survive reboots
```

Then proxy the domain to it in `/home/USER/public_html/.htaccess`:

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

This needs `mod_proxy` and `mod_rewrite` with `P` allowed. If you get
**500** or *"proxying not enabled"* in the Apache error log, the host has it
disabled — there is no user-side workaround.

Restart after changes: `pm2 restart mybookingshub`.
