# Deploying the vCenter Portal on cPanel

This guide walks you through deploying the portal on a cPanel hosting account using cPanel's **Setup Python App** feature (the CloudLinux Python Selector + Phusion Passenger stack that almost all modern cPanel hosts use).

---

## ⚠ Before you start — read this

The portal connects from the web server to your vCenter on port 443. For that to work, **the cPanel server must be able to reach the vCenter server over the network**.

That is usually NOT possible on standard shared cPanel hosting, because:

- Your cPanel server lives on the hosting provider's public infrastructure.
- Your vCenter typically lives on your own private LAN with a non-routable IP (10.x.x.x, 192.168.x.x, etc.).
- Shared hosts also often firewall outbound traffic to non-standard destinations.

**Workable scenarios:**

| Scenario | Will it work? |
|---|---|
| cPanel/WHM on your own VPS or dedicated server, inside the same network as vCenter | ✅ Yes |
| cPanel server with a site-to-site VPN to your office where vCenter lives | ✅ Yes |
| vCenter has a public IP and firewall lets cPanel reach it | ⚠️ Works, but a bad security posture |
| Standard shared cPanel hosting + on-prem vCenter on a private LAN | ❌ No |

Verify reachability **first** by opening cPanel → **Terminal** and running:

```bash
curl -k -v https://YOUR_VCENTER_HOST/sdk -m 5
```

If you don't see TLS handshake output, stop and fix networking before deploying.

---

## Requirements on the cPanel server

- cPanel/WHM with **Setup Python App** enabled (most modern hosts have this; if not, ask support to enable CloudLinux Python Selector).
- Python 3.10 or 3.11 available in the Python Selector.
- Outbound HTTPS allowed to your vCenter host.
- A MySQL database in cPanel **(optional)** — SQLite works too and is simpler.

---

## Step 1 — Upload the project files

1. In cPanel, open **File Manager**.
2. Navigate to your home directory (or a subfolder you want to use).
3. Click **Upload** and upload `vcenter-portal.zip`.
4. Right-click the uploaded zip → **Extract**. You should end up with `/home/<cpanel_user>/vcenter-portal/`.

Alternatively, via cPanel Terminal:

```bash
cd ~
unzip vcenter-portal.zip
cd vcenter-portal
ls
```

---

## Step 2 — Create the Python App

1. In cPanel, open **Setup Python App** (sometimes called "Python Selector").
2. Click **Create Application** and fill in:

   | Field | Value |
   |---|---|
   | **Python version** | 3.10 (or 3.11 — match `PY_VERSION` in `passenger_wsgi.py`) |
   | **Application root** | `vcenter-portal` |
   | **Application URL** | Pick a domain or subdomain (e.g. `portal.yourdomain.com` or `yourdomain.com/portal`) |
   | **Application startup file** | `passenger_wsgi.py` |
   | **Application Entry point** | `application` |
   | **Passenger log file** | leave default |

3. Click **Create**. cPanel will:
   - Create a virtualenv at `/home/<user>/virtualenv/vcenter-portal/3.10/`
   - Create the necessary `.htaccess` entries automatically (Passenger directives)
   - Show a command at the top like `source /home/<user>/virtualenv/vcenter-portal/3.10/bin/activate && cd /home/<user>/vcenter-portal`

4. Copy that activation command — you'll use it for installing dependencies.

> **If you used a different "Application root" name**, edit `passenger_wsgi.py` and update `APP_ROOT_NAME` and `PY_VERSION` to match.

---

## Step 3 — Install dependencies

In cPanel Terminal:

```bash
# Paste the activation command cPanel showed you
source /home/<user>/virtualenv/vcenter-portal/3.10/bin/activate && cd /home/<user>/vcenter-portal

pip install -r requirements.txt
```

If `pyVmomi` fails to install (rare on cPanel, more common on older Python), check `python --version` and confirm you selected 3.10 or 3.11.

**Using MySQL instead of SQLite (optional):**

```bash
pip install -r requirements-mysql.txt
```

---

## Step 4 — Configure environment variables

You have two equivalent options.

### Option A — cPanel UI (recommended)

Back on the **Setup Python App** page, find your app and scroll to **Environment variables**. Click **Add Variable** and add each of these:

| Name | Value |
|---|---|
| `SECRET_KEY` | a long random string (generate with `python -c "import secrets; print(secrets.token_hex(32))"`) |
| `VCENTER_HOST` | your vCenter FQDN or IP |
| `VCENTER_USER` | e.g. `administrator@vsphere.local` |
| `VCENTER_PASSWORD` | your vCenter password |
| `VCENTER_PORT` | `443` |
| `VCENTER_VERIFY_SSL` | `False` for self-signed vCenter cert, `True` for properly trusted |
| `VM_CACHE_TTL` | `60` |
| `DATABASE_URL` | only if using MySQL — see below |

For MySQL:

```
DATABASE_URL=mysql+pymysql://cpaneluser_portal:DBPASSWORD@localhost/cpaneluser_portal
```

Click **Save**, then click **Restart** on the app.

### Option B — `.env` file

Inside your app directory create a `.env`:

```bash
cd ~/vcenter-portal
cp .env.example .env
nano .env   # or edit via cPanel File Manager
```

`passenger_wsgi.py` already loads `.env` automatically. Set file permissions to 600 so it's not world-readable:

```bash
chmod 600 .env
```

---

## Step 5 — Initialize the database and create the first admin

Still in the activated venv:

```bash
INITIAL_ADMIN_PASSWORD='YourStrongPassword!' python init_db_cpanel.py admin admin@yourcompany.com
```

This is safe to re-run — it won't overwrite an existing admin.

**For MySQL users:** make sure you created the database and user in cPanel → **MySQL Databases** first, and that you ran `pip install -r requirements-mysql.txt`.

---

## Step 6 — Restart and test

1. In **Setup Python App**, click **Restart** on your app.
2. Open the **Application URL** you configured in your browser.
3. You should see the login page. Sign in with the admin credentials you just created.
4. Click **Admin → Audit Log** to confirm your `LOGIN_SUCCESS` event was recorded.
5. Click **Virtual Machines** — if the VM table loads, vCenter integration is working. If you see "Unable to contact vCenter", see Troubleshooting below.

---

## Step 7 — Lock things down

- In cPanel → **SSL/TLS Status**, install an AutoSSL or paid certificate for your portal's domain.
- Edit `.htaccess` and uncomment the "Force HTTPS" rewrite block.
- Restart the app.

---

## Updating the application later

When you change code:

```bash
cd ~/vcenter-portal
# upload / edit your files, then:
touch tmp/restart.txt
```

Creating an empty `tmp/restart.txt` is the standard Passenger signal to reload the app. (cPanel's UI **Restart** button does the same thing.)

```bash
mkdir -p tmp
touch tmp/restart.txt
```

---

## Troubleshooting

**Browser shows "Internal Server Error" or a Passenger error page**

Check the Passenger log shown in the Setup Python App UI, or:

```bash
tail -200 ~/vcenter-portal/stderr.log
```

Most common causes:
- A missing Python package → re-run `pip install -r requirements.txt` inside the activated venv.
- Wrong `APP_ROOT_NAME` or `PY_VERSION` in `passenger_wsgi.py` → must match exactly what cPanel created.
- `.env` missing or `SECRET_KEY` not set.

**"Unable to contact vCenter"**

```bash
# From cPanel Terminal:
curl -k -v https://YOUR_VCENTER/sdk -m 10
```

- No TLS handshake → networking/firewall issue between cPanel and vCenter. See the warning at the top of this guide.
- `Connection refused` → wrong port or vCenter not listening.
- `SSL: CERTIFICATE_VERIFY_FAILED` → set `VCENTER_VERIFY_SSL=False` in the env vars (or install your vCenter's CA into the cPanel host).

**"sqlite3.OperationalError: unable to open database file"**

The `instance/` directory doesn't exist or isn't writable:

```bash
mkdir -p ~/vcenter-portal/instance
chmod 755 ~/vcenter-portal/instance
```

**Login page loads but CSS is missing**

Apache isn't serving `/static/`. Make sure the `.htaccess` file uploaded properly and that mod_rewrite is enabled (it is on virtually every cPanel host). Hit the static file directly to check:

```
https://your-portal-url/static/css/style.css
```

**Static files leak through Passenger and look slow**

This is the same problem — the `RewriteRule ^static/(.*)$ static/$1 [L]` line in `.htaccess` should fix it.

**MySQL: `(1045, "Access denied for user ...")`**

Recheck the `DATABASE_URL`. cPanel prefixes the database and username with your cPanel account name (e.g. `myaccount_portal`). Also confirm the user is granted to that database in cPanel → **MySQL Databases**.

**Passenger keeps the old code after I edit a file**

That's expected — touch the restart file:

```bash
touch ~/vcenter-portal/tmp/restart.txt
```

---

## Quick file checklist

These are the files specific to the cPanel deployment:

- `passenger_wsgi.py` — WSGI entry point for Passenger
- `.htaccess` — static file routing + security headers
- `init_db_cpanel.py` — non-interactive DB bootstrap
- `requirements-mysql.txt` — optional MySQL driver
- `cpanel-deploy.md` — this guide

All the other files (`app.py`, `models.py`, templates, etc.) are unchanged from the base project.
