# Hosting the NCA site

## Which hosting should you pick?

| Stage | What you need | Good choice |
|---|---|---|
| **Now: front end only** (preview, staging, show it to the team) | Any PHP 8.2+ host with a MySQL database or none | **Namecheap shared hosting (Stellar or higher)** works |
| **MVP with registration, no live payments** | Same, plus cron | Namecheap shared hosting still works |
| **Production with M-Pesa, SMS, queues, 2FA, backups** (the Build Plan stack) | Redis, queue workers that stay running (Supervisor), full control | **A VPS** (2 vCPU, 4 GB RAM is enough to start), ideally managed with Laravel Forge or Ploi |

**My recommendation for NCA:** start on Namecheap shared hosting for the front end and early testing, because it is cheap and simple. Move to a VPS **before** you switch on real M-Pesa payments and member data. The Build Plan (sections 2 and 15) assumes Redis, Horizon and Supervisor, and shared hosting cannot run those. A Kenyan data centre or a nearby cloud region also keeps the site faster for your members. Check current plans and prices yourself before buying, because I could not verify them.

> Whatever you choose, never test payments on production, keep `APP_DEBUG=false`, and use HTTPS.

---

## A. Deploy on Namecheap shared hosting (cPanel)

You will run the site on a **subdomain**, for example `nca.novaexcellenceawards.org` (the Build Plan's suggested start), with its document root pointing at Laravel's `public` folder.

### Before you start (on your computer)
1. Run the site locally first (see `INSTALL-AND-RUN.md`) and confirm it works.
2. Install production dependencies and build the assets:
   ```bash
   composer install --no-dev --optimize-autoloader
   npm run build
   ```
   (Keep the `filament/*`, `spatie/*` packages: they are required, not dev-only.)
   Shared hosting has no Node, so the built files in `public/build` must be uploaded. They are already there after `npm run build`.
3. Create a production `.env` (copy `.env.example`) with:
   ```
   APP_NAME="Nova Community Alliance"
   APP_ENV=production
   APP_DEBUG=false
   APP_URL=https://nca.novaexcellenceawards.org
   APP_KEY=            # run: php artisan key:generate --show   and paste the result

   DB_CONNECTION=mysql
   DB_HOST=localhost
   DB_DATABASE=cpanelprefix_nca
   DB_USERNAME=cpanelprefix_ncauser
   DB_PASSWORD=choose-a-long-random-password

   SESSION_DRIVER=database
   QUEUE_CONNECTION=database
   CACHE_STORE=database
   NCA_DEMO=false      # must be false on a public site (true shows SMS codes on screen)
   # plus the SMS, M-Pesa and email values from .env.nca.example (see CONNECT-SERVICES.md)
   ```
4. Make a zip of the project **without** `node_modules`, `.git`, and `.env` (you will add `.env` on the server). **Include** `vendor` if your plan has no SSH or Composer.

### On the server
1. **Create the database.** cPanel, then **MySQL Databases**: create a database, a user, and add the user to the database with all privileges.
2. **Set the PHP version.** cPanel, then **Select PHP Version** (or MultiPHP Manager): choose **8.3** (8.2 is the minimum for Laravel 12). Enable extensions: `mbstring`, `openssl`, `pdo_mysql`, `fileinfo`, `tokenizer`, `xml`, `ctype`, `json`, `gd`, `intl`, `zip`, `curl`.
3. **Upload the project** to a folder **outside** `public_html`, for example `/home/YOURUSER/nca`. Use File Manager (upload the zip and Extract) or SFTP. Upload your production `.env` into the same folder.
4. **Create the subdomain.** cPanel, then **Domains** (or Subdomains): add `nca.novaexcellenceawards.org` and set its **Document Root** to `/home/YOURUSER/nca/public`. If the domain uses Namecheap's nameservers, the DNS record is created for you. If DNS is elsewhere, add an A record for `nca` pointing to your hosting IP.
5. **Run the setup commands.** Open cPanel **Terminal** (or SSH, if your plan includes it):
   ```bash
   cd ~/nca
   php artisan migrate --force
   php artisan filament:assets
   php artisan storage:link
   php artisan nca:install              # counties, sectors, tiers, roles (safe to re-run)
   php artisan nca:make-staff you@example.com super_admin --name="Your Name"
   php artisan nca:check --live         # fix every FAIL before launch
   php artisan config:cache
   php artisan route:cache
   php artisan view:cache
   ```
   If your plan has no Terminal or SSH, run `php artisan migrate` locally against the production database credentials, or export the tables to SQL and import them in phpMyAdmin.
6. **File permissions.** `storage` and `bootstrap/cache` must be writable by the web user. Use `755` for folders and `644` for files; try `775` on those two folders only if needed. Do **not** use `777`.
7. **HTTPS.** In cPanel, turn on **AutoSSL** (free certificate) for the subdomain, then force HTTPS by adding these lines at the top of `public/.htaccess`:
   ```apache
   RewriteEngine On
   RewriteCond %{HTTPS} off
   RewriteRule ^(.*)$ https://%{HTTP_HOST}/$1 [L,R=301]
   ```
8. **Scheduled jobs (cron).** cPanel, then **Cron Jobs**, add two entries, each every minute:
   ```
   * * * * * cd /home/YOURUSER/nca && /usr/local/bin/php artisan schedule:run >> /dev/null 2>&1
   ```
   One line is enough: the schedule already runs the queue worker every minute (`routes/console.php`), plus payment reconciliation every 5 minutes, renewals daily at 08:00 and housekeeping nightly.
   The path to `php` may differ; cPanel shows it in Cron Jobs help or **Select PHP Version**.
9. **Test.** Open the site, register a test member (use your own phone), and open `/admin`. On shared hosting use the Daraja **sandbox** only; move to a VPS before real money.

### If you cannot change the subdomain's document root
Put the Laravel project in `/home/YOURUSER/nca`, then copy the **contents** of its `public` folder into the web folder (`public_html` or the subdomain folder) and edit `index.php` so the paths point back to the project:
```php
require __DIR__.'/../nca/vendor/autoload.php';
$app = require_once __DIR__.'/../nca/bootstrap/app.php';
```
Remember to repeat the copy whenever you run `npm run build`.

### Updating the site later
Upload changed files (or the whole zip again), then run `php artisan optimize:clear` followed by the three cache commands above. Always keep a backup of the database first.

### Limits to know about on shared hosting
- No Redis, Horizon, or Supervisor, so queues run through cron once a minute using the database. Fine for the MVP, too slow and fragile for payment-heavy production.
- Shared CPU and memory limits. One article reports trouble beyond roughly 5,000 visits a month; your own traffic will vary.
- M-Pesa (Daraja) needs a public HTTPS callback URL. That works on a subdomain with a valid certificate, but you cannot restrict it by IP the way a VPS firewall can.

---

## B. Deploy on a VPS (recommended for production)

Follows the Build Plan, section 15.

1. Create an Ubuntu 24.04 server (2 vCPU, 4 GB RAM).
2. Easiest path: connect it to **Laravel Forge** or **Ploi**, which installs Nginx, PHP 8.3, MySQL, Redis and Supervisor for you, handles SSL, and deploys from GitHub on every push to `main`.
3. Create the site `nca.novaexcellenceawards.org`, point DNS to the server, enable the free SSL certificate.
4. Set the production `.env` (use `QUEUE_CONNECTION=redis`, `CACHE_STORE=redis`, `SESSION_DRIVER=redis`; Horizon is optional, the plain `queue:work` daemon under Supervisor also works). With a real queue daemon you can remove the `queue:work` line from `routes/console.php`.
5. Deploy script:
   ```bash
   composer install --no-dev --optimize-autoloader
   php artisan migrate --force
   php artisan filament:upgrade
   php artisan optimize
   npm ci && npm run build      # or build in GitHub Actions
   php artisan queue:restart
   ```
6. Add the scheduler (`php artisan schedule:run` every minute) and a Horizon daemon.
7. Turn on nightly encrypted backups (`spatie/laravel-backup`) to off-site storage and test a restore once.

---

## Go-live checklist
- [ ] `APP_DEBUG=false`, `APP_ENV=production`, a real `APP_KEY`
- [ ] HTTPS working, forced, and `APP_URL` uses `https://`
- [ ] Real Terms and Privacy text (reviewed by a lawyer); ODPC registration done
- [ ] Fees in `config/nca.php` (later the database) confirmed
- [ ] `NCA_DEMO=false` once the real SMS and Daraja services are connected
- [ ] `php artisan nca:check --live` shows no FAIL (and you understand each WARN)
- [ ] A real super admin created, the sample `@nca.test` accounts do not exist (they are only created by `nca:install --demo`)
- [ ] M-Pesa callback URL registered with Safaricom and tested in sandbox first (CONNECT-SERVICES.md)
- [ ] Africa's Talking sender ID approved; SMTP sending tested
- [ ] `APP_KEY` copied somewhere safe (encrypted ID numbers cannot be read without it)
- [ ] Learner photos used only with school and guardian consent
- [ ] Backups running and a restore tested

---

## Sources
- Truehost: [Deploy Laravel on shared hosting](https://truehost.co.ke/deploy-laravel-on-shared-hosting/) (keep the app outside `public_html`, PHP 8.2+ for Laravel 12, Composer may be unavailable on some plans)
- vicradon: [Laravel on a Namecheap subdomain (gist, 2021, unofficial)](https://gist.github.com/vicradon/d7d46a0c54122b7757f5c70bcc13cefd) (subdomain, A record, SSH deploy flow; check against current Namecheap docs)
