# Installation — ExamCert Release 02.01.00

These instructions assume root SSH access to the cPanel/WHM VPS and the Phase 01 PHP 8.5 configuration already completed.

## 1. Identify the cPanel owner and home directory

Run as `root`:

```bash
CPUSER=$(/scripts/whoowns examcert.org)
CPHOME=$(getent passwd "$CPUSER" | cut -d: -f6)
CPGROUP=$(id -gn "$CPUSER")

printf 'User: %s\nHome: %s\nGroup: %s\n' "$CPUSER" "$CPHOME" "$CPGROUP"
```

Do not continue if `CPUSER` or `CPHOME` is empty.

## 2. Create an isolated staging domain

In **cPanel → Domains → Create A New Domain**:

- Domain: `v2.examcert.org` or another dedicated staging hostname
- Document root: `examcert_v2_public`
- Do not share the document root with `examcert.org`

Then run AutoSSL and select **PHP 8.5** for that staging domain in MultiPHP Manager.

The legacy production document root must remain unchanged.

## 3. Upload and extract the release

Upload `ExamCert-Release-02.1.0.zip` into the cPanel account home directory, not into `public_html`.

As `root`:

```bash
cd "$CPHOME"
unzip -q ExamCert-Release-02.1.0.zip

rsync -a --delete \
  ExamCert-Release-02.1.0/examcert/ \
  "$CPHOME/examcert/"

rsync -a --delete \
  ExamCert-Release-02.1.0/examcert_v2_public/ \
  "$CPHOME/examcert_v2_public/"

chown -R "$CPUSER:$CPGROUP" \
  "$CPHOME/examcert" \
  "$CPHOME/examcert_v2_public"
```

The `--delete` option is safe only because these are new dedicated Phase 02 directories. Never point either command at the live legacy document root.

## 4. Apply permissions

```bash
find "$CPHOME/examcert" -type d -exec chmod 750 {} \;
find "$CPHOME/examcert" -type f -exec chmod 640 {} \;
chmod 750 "$CPHOME/examcert/bin/console" "$CPHOME/examcert/bin/install"
chmod 700 \
  "$CPHOME/examcert/storage/sessions" \
  "$CPHOME/examcert/storage/tmp" \
  "$CPHOME/examcert/storage/uploads/private"
chmod 750 \
  "$CPHOME/examcert/logs" \
  "$CPHOME/examcert/storage/cache"

find "$CPHOME/examcert_v2_public" -type d -exec chmod 755 {} \;
find "$CPHOME/examcert_v2_public" -type f -exec chmod 644 {} \;
```

## 5. Prepare `.env` and generate the application key

```bash
runuser -u "$CPUSER" -- env \
  PHP_BIN=/opt/cpanel/ea-php85/root/usr/bin/php \
  "$CPHOME/examcert/bin/install"
```

This creates:

```text
/home/CPANEL_USER/examcert/.env
```

with mode `0600`, creates private writable directories and generates a 256-bit `APP_KEY`.

## 6. Create the empty Phase 02 database

In **cPanel → MySQL Databases**:

1. Create a database such as `examcert_v2`.
2. Create a dedicated database user with a strong unique password.
3. Add that user to the database with all privileges.
4. Copy the actual cPanel-prefixed database and username exactly.

No tables are imported in Release 02.01.00. The migration engine and schema begin in Release 02.02.00.

## 7. Edit the environment configuration

```bash
nano "$CPHOME/examcert/.env"
```

Set at minimum:

```dotenv
APP_ENV="staging"
APP_DEBUG=false
APP_URL="https://v2.examcert.org"
APP_ALLOWED_HOSTS="v2.examcert.org"
APP_FORCE_HTTPS=true

DB_HOST="localhost"
DB_PORT=3306
DB_DATABASE="CPANELPREFIX_examcert_v2"
DB_USERNAME="CPANELPREFIX_examcert_v2user"
DB_PASSWORD="THE_STRONG_DATABASE_PASSWORD"
```

Do not change the generated `APP_KEY` after encrypted production data is introduced. Keep:

```dotenv
SESSION_SECURE_COOKIE=true
HSTS_INCLUDE_SUBDOMAINS=false
HSTS_PRELOAD=false
```

Then enforce ownership and permissions again:

```bash
chown "$CPUSER:$CPGROUP" "$CPHOME/examcert/.env"
chmod 600 "$CPHOME/examcert/.env"
```

## 8. Run verification as the cPanel user

```bash
PHP85=/opt/cpanel/ea-php85/root/usr/bin/php

runuser -u "$CPUSER" -- "$PHP85" "$CPHOME/examcert/bin/console" app:check
runuser -u "$CPUSER" -- "$PHP85" "$CPHOME/examcert/bin/console" db:check
runuser -u "$CPUSER" -- "$PHP85" "$CPHOME/examcert/bin/console" route:list
runuser -u "$CPUSER" -- "$PHP85" "$CPHOME/examcert/tests/run.php"
```

Required final results:

- `app:check`: **0 failures**
- `db:check`: **PASS**
- automated tests: **7 passed, 0 failed**

Warnings about the CLI handler should be compared with the PHP 8.5 FPM settings for the staging domain.

## 9. Verify through HTTPS

Replace the hostname if a different staging domain was chosen:

```bash
curl -sS -I https://v2.examcert.org/
curl -sS https://v2.examcert.org/_health/live
curl -sS -w '\nHTTP %{http_code}\n' https://v2.examcert.org/_health/ready
curl -sS -D - https://v2.examcert.org/_security/csrf -o /dev/null
```

Expected:

- `/` → HTTP 200
- `/_health/live` → HTTP 200 and `"status":"ok"`
- `/_health/ready` → HTTP 200 and `"status":"ready"`
- `/_security/csrf` → HTTP 200 and a cookie containing `Secure`, `HttpOnly`, `SameSite=Lax`
- Responses contain `Content-Security-Policy`, `X-Frame-Options`, `X-Content-Type-Options`, `Permissions-Policy`, `Strict-Transport-Security` and `X-Request-ID`

## 10. Finish the staging verification

After readiness is confirmed, change:

```dotenv
HEALTHCHECK_SHOW_DETAILS=false
```

Keep `robots.txt` set to `Disallow: /` throughout development.
