# Deploying the White Label CMS on cPanel

A click-by-click guide for deploying the CMS to a standard cPanel/Apache host.
It covers both the **SSH/Terminal path** (recommended) and the **no-Terminal
path** used on cheaper shared plans.

> Requirements on the host: PHP **8.3+**, MySQL **8.0+** (or MariaDB 10.6+),
> Apache with `mod_rewrite`, and the `pdo_mysql`, `mbstring`, `openssl`, `json`
> PHP extensions.

---

## Overview of the steps

1. Set the PHP version and extensions.
2. Upload the code.
3. Point the domain's document root at `public/` (or use the fallback).
4. Create the MySQL database and user.
5. Configure `.env`.
6. Install dependencies (Composer).
7. Build the database (migrate + seed).
8. Set permissions and enable HTTPS.
9. Verify and secure.

---

## 1. Set the PHP version & extensions

1. In cPanel, open **MultiPHP Manager**.
2. Select your domain, set **PHP Version = 8.3** (or higher), and apply.
3. Open **Select PHP Version → Extensions** and confirm these are ticked:
   `pdo_mysql`, `mbstring`, `openssl`, `json`, `fileinfo`.

---

## 2. Upload the code

**Option A — File Manager (no SSH):**
1. Open **File Manager**.
2. Upload `whitelabel-cms.zip` into your home directory (e.g. above
   `public_html`, such as `/home/USER/whitelabel-cms`).
3. Select the zip → **Extract**.

**Option B — Git / SSH:**
```bash
cd ~
git clone <your-repo-url> whitelabel-cms   # or upload & unzip
```

Recommended layout (keeps app code out of the web root):

```
/home/USER/
├── whitelabel-cms/          ← full application (uploaded here)
│   ├── public/              ← the only web-facing folder
│   ├── src/  config/  ...
└── public_html/             ← domain document root
```

---

## 3. Point the domain at `public/`

The CMS is built so **only `public/` is web-accessible**. Choose one:

**Preferred — set the document root (cleanest & most secure):**
- For an **addon/subdomain**: cPanel → **Domains** → set *Document Root* to
  `/home/USER/whitelabel-cms/public` when creating it.
- For the **primary domain**, many hosts let you edit the document root under
  **Domains**; set it to `.../whitelabel-cms/public`.

**Fallback — if you cannot change the document root:**
- Upload the project so its contents sit inside `public_html/`.
- The included root `.htaccess` automatically forwards every request into
  `public/`, so the site still works. (Slightly less clean, but fully
  functional and still blocks direct access to dotfiles.)

---

## 4. Create the MySQL database

1. cPanel → **MySQL® Databases**.
2. **Create New Database** → e.g. `USER_wlcms`.
3. **Add New User** → e.g. `USER_wlcms` with a strong password.
4. **Add User to Database** → grant **ALL PRIVILEGES**.
5. Note the final names — cPanel prefixes them with your account, e.g.
   `USER_wlcms`. You'll need these in `.env`.

---

## 5. Configure `.env`

1. In File Manager, open the app folder, copy `.env.example` to `.env`
   (File Manager → select → Copy, then rename), and **Edit** it.
2. Set at least:

```ini
APP_ENV=production
APP_DEBUG=false
APP_URL=https://yourdomain.com

DB_HOST=localhost
DB_DATABASE=USER_wlcms
DB_USERNAME=USER_wlcms
DB_PASSWORD=your-strong-password

SESSION_SECURE=true
```

3. Generate secrets. With SSH: `php bin/console key:generate` and paste the
   `APP_KEY` and `JWT_SECRET` values in. Without SSH, generate two random
   base64 strings (any password generator, 32+ bytes) and set them manually.

---

## 6. Install dependencies (Composer)

**With SSH/Terminal:**
```bash
cd ~/whitelabel-cms
composer install --no-dev --optimize-autoloader
```

**Without Composer on the host:** run `composer install --no-dev
--optimize-autoloader` on your own computer, then upload the generated
`vendor/` folder. *(If you skip this entirely, the app still runs via the
built-in fallback autoloader — just without Composer's optimised class map.)*

Some cPanel hosts expose Composer under **Terminal** or as a
*Setup Node.js/PHP App* feature; check your host's docs.

---

## 7. Build the database

**With SSH/Terminal:**
```bash
cd ~/whitelabel-cms
php bin/console migrate
php bin/console db:seed
```

**Without Terminal — use a one-off cron job:**
1. cPanel → **Cron Jobs**.
2. Add a job set to run once (e.g. a few minutes ahead):
   ```
   /usr/local/bin/php /home/USER/whitelabel-cms/bin/console migrate
   ```
3. After it runs, add and run a second one for `db:seed`, then **delete both
   cron jobs**. (Confirm your host's PHP CLI path — often
   `/usr/local/bin/php` or an `ea-php83` binary; check **MultiPHP** or ask
   support.)

The seeder creates the roles, permissions, default settings, and the admin
account `admin@18pixels.local` / `ChangeMe!2026`.

> A browser-based `/install` wizard (Phase 3 on the roadmap) will make this
> step click-only, so no cron/SSH is needed for future client setups.

---

## 8. Permissions & HTTPS

- Ensure the `storage/` directory is writable: in File Manager set
  `storage` and its subfolders to **755** (or 775 if the host runs PHP as a
  separate user). Logs, cache, and uploads are written here.
- cPanel → **SSL/TLS Status** → run **AutoSSL** so the domain has HTTPS. This
  is required for `SESSION_SECURE=true` to work.
- Force HTTPS in cPanel → **Domains** → toggle *Force HTTPS Redirect*.

---

## 9. Verify & secure

1. Visit `https://yourdomain.com` → the branded landing page loads.
2. Visit `https://yourdomain.com/api/health` → JSON with
   `"database":"connected"`.
3. Log in and **immediately rotate the default admin password**.
4. Confirm `https://yourdomain.com/.env` returns **403/404** (the `.htaccess`
   rules block it) — never leave `.env` readable.
5. Double-check `APP_DEBUG=false` in production.

---

## Troubleshooting

| Symptom | Likely cause / fix |
|--------|--------------------|
| 500 error, blank page | Set `APP_DEBUG=true` temporarily to see the trace, or check `storage/logs`. Revert after. |
| "Database connection failed" | Wrong `DB_*` values, or user not granted to the DB. Use `localhost` for `DB_HOST` on cPanel. |
| Routes 404 except home | `mod_rewrite` disabled or `.htaccess` not uploaded. Ensure `public/.htaccess` exists. |
| CSS/landing looks unstyled | Outbound CDN blocked, or the page loaded over plain HTTP. Use HTTPS. |
| `storage` write errors | Set `storage/` to 755/775 and ensure the web user owns it. |
| Wrong PHP version in CLI | The cron/SSH PHP differs from the web PHP. Use the full `ea-php83` path. |

---

## Quick reference — minimum `.env` for production

```ini
APP_NAME="Client Brand"
APP_ENV=production
APP_DEBUG=false
APP_KEY=<base64 32 bytes>
APP_URL=https://clientdomain.com

DB_HOST=localhost
DB_DATABASE=USER_wlcms
DB_USERNAME=USER_wlcms
DB_PASSWORD=<strong password>

JWT_SECRET=<base64 48 bytes>
SESSION_SECURE=true
```
