# Creating `.env` on your hosting

Three routes. **Route 1 needs no terminal** — use it unless you know you have SSH.

The three commands I gave you earlier assume SSH:

```bash
cd ~/public_html/aiseo
cp .env.example .env
chmod 600 .env
```

They only work if your plan has SSH enabled, which most cPanel plans do not by
default. Routes 1 and 3 below do the same thing without it.

---

## Route 1 — the setup page (recommended, no terminal)

0. **If you get 403 Forbidden**, the `.htaccess` in that folder is blocking it.
   The version I shipped earlier denied every `.php` except `index.php` — my
   mistake. Replace it with the corrected `.htaccess` from the current zip, or
   temporarily rename it to `.htaccess.off`.
1. Upload `setup-env.php` to `public_html/aiseo/` (it is in the zip).
2. Open `https://dghanalytics.com/aiseo/setup-env.php`
3. Fill in the four database fields, press **Test connection and write .env**.
4. When it succeeds, press **Delete setup-env.php now**.

What it does for you:

- **Tests the database connection before writing anything.** A wrong password
  produces a diagnosis, not a half-written config file.
- **Checks the user can CREATE and DROP tables.** A read-only grant passes
  `SELECT` and then fails at migration time — this catches it now.
- **Generates `APP_KEY`.** No command needed.
- **Detects `APP_URL`** from the page's own address and strips a trailing slash.
- **Quotes the password correctly.** A password containing a space, `#`, `$` or a
  quote is written double-quoted and escaped, and the app unescapes it on read.
  Handling that by hand is the most common way to end up with "Access denied"
  when the password is actually right.
- **Writes the folder paths automatically** if it sees the nested
  `3-source-code/src` layout — so you never need to know your account's absolute
  path.
- **Sets 0600 permissions**, backs up any existing `.env`, and never prints the
  password back to the page.
- If PHP cannot write the folder, it shows the finished file contents to
  copy-paste instead.

**Delete it afterwards.** A page that can write `.env` must not stay on a live
server. It offers a one-click delete when it finishes.

---

## Route 2 — cPanel Terminal (if you have it)

cPanel → **Terminal** (under Advanced). If the icon is missing, your host has
disabled it; use Route 1 or 3.

```bash
cd ~/public_html/aiseo
cp .env.example .env
chmod 600 .env
nano .env          # edit, then Ctrl+O, Enter, Ctrl+X to save and exit
```

To confirm your absolute path for the `AISEO_*_DIR` lines:

```bash
pwd                # prints e.g. /home/dolrad/public_html/aiseo
```

To generate `APP_KEY`:

```bash
php -r "echo bin2hex(random_bytes(32)), PHP_EOL;"
```

---

## Route 3 — cPanel File Manager (no terminal, manual)

The catch: File Manager **hides dotfiles by default**, so `.env` is invisible
until you turn them on.

1. cPanel → **File Manager** → navigate to `public_html/aiseo`
2. Top right → **Settings** → tick **Show Hidden Files (dotfiles)** → Save
3. You can now see `.env.example`. Right-click it → **Copy** → set the
   destination to `/public_html/aiseo/.env` → Copy File(s)
4. Right-click `.env` → **Edit** (confirm the encoding prompt) → fill in the
   values → **Save Changes**
5. Right-click `.env` → **Change Permissions** → untick everything except the
   two **Read**/**Write** boxes on the first row → the number should read **600**

If step 3 does not let you name a file starting with a dot, use **+ File**, name
it `env.txt`, edit and save it, then right-click → **Rename** → `.env`. Renaming
accepts the dot even when creating does not.

---

## What to actually put in it

Only these five lines matter to start. Everything else has a working default.

```
APP_URL=https://dghanalytics.com/aiseo
APP_KEY=<64 random hex characters>
DB_NAME=dolrad_aiseo
DB_USER=dolrad_seo
DB_PASS="your password in double quotes"
```

### Getting the database values

cPanel → **MySQL® Databases**:

1. **Create New Database** — type `aiseo`. cPanel saves it as `dolrad_aiseo`
   (your account prefix, added automatically). **Use the full prefixed name.**
2. **Add New User** — type `seo`, set a password, **copy it now**.
3. **Add User To Database** — pick the user and the database, then on the next
   screen tick **ALL PRIVILEGES** and Make Changes.

**Step 3 is the one people skip**, and it produces "Access denied for user"
even though the username and password are both correct. If you already created
the user and database, go straight to step 3 and confirm the pairing exists.

### Quoting rules for `DB_PASS`

| Password | Write it as |
|---|---|
| `simple123` | `DB_PASS=simple123` |
| `has spaces` | `DB_PASS="has spaces"` |
| `p@ss#word` | `DB_PASS="p@ss#word"` — **unquoted, the `#` starts a comment** |
| `it's$fine` | `DB_PASS="it's$fine"` |
| `has"quote` | `DB_PASS="has\"quote"` — escape the inner quote |

When in doubt, wrap it in double quotes. The safest move is to avoid `#` and `"`
in the password entirely: reset it in cPanel to letters, digits and `-_.` only.

### `AISEO_*_DIR` lines

**Leave them blank** for the `aiseo` layout — the defaults are correct and
the app discovers everything.

Fill them in only if you merge into the existing `/aiseo/` folder, where source
sits in `3-source-code/src`. `setup-env.php` detects that case and writes them
for you.

---

## Permissions: why `chmod 600` sometimes breaks it

`0600` means "only the owner may read". That is correct **only when `.env` is
owned by the user PHP runs as**. If you create `.env` over SSH as one user while
PHP runs as another, PHP cannot read it — and the failure is **silent**: the app
starts with no configuration, so every page 404s and the database banner blames
MySQL. I hit this on a real Apache while testing, which is why the app now
detects it and says so.

| How your host runs PHP | Who owns `.env` | Use |
|---|---|---|
| cPanel with per-user PHP-FPM or suEXEC (most cPanel plans) | your account user | **0600** |
| plain `mod_php` — PHP runs as `www-data` / `apache` / `nobody` | your account user | **0640** with the group set to PHP's group, or **0644** |
| you used `setup-env.php` | the PHP user (it wrote the file) | **0600** — it verifies the read-back and widens only if it must |

**How to tell which you have:** open `preflight.php`. Section 5 now prints
`.env owner / PHP user`. If those two names differ and the line says
`.env readable by PHP: NO`, that is the problem — and it names the fix.

On an isolated cPanel account `0644` is not the exposure it sounds like, because
the `.htaccess` blocks `.env` over HTTP and other accounts cannot read your home
directory. Confirm the HTTP side by requesting `/aiseo/.env` — it must
return 403.

## Confirm it worked

```
https://dghanalytics.com/aiseo/preflight.php
```

Section 5 lists which keys are set — **never their values**. Section 1 checks the
PHP version. If everything is clean:

- with SSH: `php bin/doctor.php` then `php bin/migrate.php`
- without SSH: tell me and I will send you a one-page `migrate-web.php`

Then delete `setup-env.php` and `preflight.php`.
