# Going live — step-by-step checklist

Use this on the day you move Ecclesia Ledger from this XAMPP test machine to a real server that churches use.
Nothing here needs doing until then. Tick each box as you go. Allow about half a day, plus 1–2 days
beforehand for the domain and email to be ready.

Technical background for each setup is in [DEPLOYMENT.md](DEPLOYMENT.md); backups and recovery are in
[DR-RUNBOOK.md](DR-RUNBOOK.md).

---

## Stage A — A week or two before

- [ ] **Choose the hosting.**
  - Many churches (SaaS): a VPS with 2 CPU / 4 GB RAM or more, Ubuntu 22.04/24.04, using Docker
    (DEPLOYMENT.md §1) or plain install (§2).
  - One church only: a single VPS (§2) is enough. Avoid running the live system on an office PC.
  - A provider with a Lagos/Johannesburg/Europe region keeps it fast for Nigerian users.
- [ ] **Buy a domain** (e.g. `ecclesialedger.ng`) and point an `A` record at the server's IP address.
- [ ] **Set up sending email** with an email service (e.g. Zoho Mail, Mailgun, Postmark, Amazon SES).
  You need SMTP host, port, username and password, and a "from" address on your domain. Add the SPF/DKIM
  records the email service gives you, or receipts and sign-in codes will land in spam.
- [ ] **Paystack (platform subscriptions)**: complete business verification (KYC) so you can receive live
  payments. Keep the *live* secret key ready; it goes into `.env` later, never into chat or email.
- [ ] **Decide where off-site backups go**: an S3-compatible bucket (Amazon S3, Backblaze B2, Cloudflare R2)
  or another machine. A backup kept only on the same server is lost with the server.
- [ ] **Get a password manager** (Bitwarden, 1Password, KeePass) for the keys created below.

## Stage B — Prepare the server

- [ ] Install the software (DEPLOYMENT.md §1 or §2) and copy the app's code to the server.
  Copy the code only. **Do not copy** this machine's `.env`, `storage/` folder or database, which hold demo data and test keys.
- [ ] **Web root = the `public/` folder only.** Everything else must be unreachable from the web.
- [ ] **HTTPS certificate.** Free with Let's Encrypt (`sudo apt install certbot python3-certbot-nginx`, then
  `sudo certbot --nginx -d yourdomain.ng`), or automatic with Caddy or Cloudflare.
- [ ] **Firewall:** allow only ports 22 (SSH), 80 and 443 (`sudo ufw allow OpenSSH; sudo ufw allow 'Nginx Full'; sudo ufw enable`).
  Never open the database port (3306) to the internet.
- [ ] **SSH:** sign in with a key, not a password, and turn off root login over SSH.
- [ ] **Automatic security updates:** `sudo apt install unattended-upgrades`.
- [ ] **Database:** create a dedicated database and user with a long random password, *not* `root`:

```sql
CREATE DATABASE church_acct CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE USER 'church_app'@'localhost' IDENTIFIED BY 'a-long-random-password';
GRANT ALL PRIVILEGES ON church_acct.* TO 'church_app'@'localhost';
```

## Stage C — Configure the app (`.env`)

Start from the example (`cp .env.example .env`), then set these values:

| Setting | Live value |
|---|---|
| `APP_ENV` | `production` |
| `APP_DEBUG` | `false` |
| `APP_URL` | `https://yourdomain.ng` (with https, no trailing slash) |
| `LOG_LEVEL` | `warning` |
| `DB_DATABASE` / `DB_USERNAME` / `DB_PASSWORD` | the database and user from Stage B |
| `SESSION_PATH` | `/` (the `/church_acct_app/public` value is for XAMPP only) |
| `SESSION_SECURE_COOKIE` | `true` |
| `SECURITY_FORCE_HTTPS` | `true` |
| `TRUSTED_PROXIES` | only if behind Cloudflare or a load balancer: their IP ranges |
| `MAIL_MAILER` | `smtp` |
| `MAIL_HOST`, `MAIL_PORT`, `MAIL_USERNAME`, `MAIL_PASSWORD`, `MAIL_FROM_ADDRESS` | from your email service |
| `BILLING_PAYSTACK_SECRET` | your Paystack **live** secret key |
| `BILLING_SELLER_*`, `BILLING_BANK_*` | your company's real name, address, TIN and bank details (shown on invoices) |
| `BACKUP_OFFSITE_DISK` + `AWS_*` | the off-site backup bucket |
| `EINVOICE_*` | leave `EINVOICE_ENABLED=false` until FIRS/NRS onboarding is complete |

Then create the two secret keys **once**:

```bash
php artisan key:generate
php artisan backup:key
```

- [ ] **Copy `APP_KEY` and `BACKUP_KEY` from `.env` into your password manager now.** If `APP_KEY` is lost,
  encrypted data (welfare notes, 2FA secrets, gateway keys) can never be read again, even from backups.
  Never generate them again on a live system.

## Stage D — Install

```bash
composer install --no-dev --optimize-autoloader
npm ci && npm run build
php artisan migrate --force          # empty tables only. Never run db:seed on live: it loads demo churches
php artisan storage:link
php artisan config:cache && php artisan route:cache && php artisan view:cache
php artisan platform:owner you@yourdomain.ng
```

- [ ] `platform:owner` asks for your password at a hidden prompt. Use a strong password you don't use anywhere else.
- [ ] **Scheduler** (backups, billing, queued email/SMS, bank feeds, scheduled reports). Add this cron line,
  adjusting the folder:
  `* * * * * cd /var/www/church && php artisan schedule:run >> /dev/null 2>&1`
- [ ] File permissions: the web server user owns `storage/` and `bootstrap/cache/`, and `.env` is not readable
  by other users (`chmod 640 .env`).

## Stage E — Check before inviting anyone

- [ ] Run the security checklist. **It must say "All checks passed"**:

```bash
php artisan security:check
composer audit
npm audit --omit=dev
```

- [ ] Open `https://yourdomain.ng`. The padlock shows, and `http://` redirects to `https://`.
- [ ] Sign in as the platform owner and **set up two-factor login** (it is required). Save the recovery codes
  in your password manager.
- [ ] Optional: check the site at https://securityheaders.com (expect A or A+) and https://www.ssllabs.com/ssltest (expect A).
- [ ] **Test email:** register a test church at `/register` with your own address and confirm the welcome
  email arrives (and isn't in spam). Name it "TEST – do not use" so it's easy to spot; it lapses on its
  own when the free trial ends.
- [ ] **Test backups:** `php artisan backup:run`, then `php artisan backup:verify`. Confirm the file reached the
  off-site location. Practise one restore on a spare machine (DR-RUNBOOK.md).
- [ ] **Test payment:** pay one subscription invoice with a real card for a small amount and confirm it
  shows as paid (this proves the Paystack webhook works). Webhook URL in the Paystack dashboard:
  `https://yourdomain.ng/billing-webhooks/paystack`.

## Stage F — Launch day and after

- [ ] Each church signs up at `https://yourdomain.ng/register` (or you onboard them) and enters **their own**
  keys inside the app: online giving (Paystack/Flutterwave), SMS, WhatsApp and Mono bank feeds.
- [ ] Ask each church administrator to turn on two-factor login and to give staff their own accounts.
  Shared logins defeat the audit trail.
- [ ] Monitor `https://yourdomain.ng/up` with a free uptime monitor (UptimeRobot, Better Stack).
- [ ] **Weekly:** check the backup report, and look in the Audit log for `account_locked` and `login_failed` bursts.
- [ ] **Monthly:** `composer audit`, `npm audit`, server updates. For each app update, follow "Updating" in DEPLOYMENT.md
  (it backs up first and re-runs `security:check`).
- [ ] **Every 3 months:** practise a restore from backup, and remove staff accounts for people who have left.

## Never on the live server

- Never run `php artisan db:seed` or `migrate:fresh`. The first loads demo data; the second **erases everything**.
- Never set `APP_DEBUG=true`, even "just for a minute". Error pages would show passwords and keys to visitors.
- Never put `.env`, keys or passwords in email, WhatsApp or chat, or commit them to git.
- Never copy the XAMPP test database to live. Its accounts use the published demo password.
