# LifeBook Family — Production Installation Guide

**Build:** 2026.08.30.1  
**Installer:** 3.0.0  
**Canonical domain:** `https://lifebook.family`

LifeBook Family is an online biography and life-story platform. The same application supports living stories, family stories and remembrance stories, with permanent QR access.

## 1. What you need before installation

In cPanel create:

1. The domain `lifebook.family` and make sure HTTPS/AutoSSL works.
2. One MySQL database and one MySQL user with **ALL PRIVILEGES**.
3. Node.js 22 / Passenger Application Manager access.

Email, Cloudflare R2 and Turnstile are **not installer questions**. Configure them later from **Admin → Settings**.

## 2. Cloudflare

Point `lifebook.family` to the cPanel server. Once the cPanel origin certificate works, use Cloudflare **Full (strict)**. Do not use Flexible SSL.

Recommended DNS:

- `A @` → cPanel server IP
- `CNAME www` → `lifebook.family`
- optional later: `CNAME media` for public R2 media

## 3. Upload the application

Upload the final LifeBook ZIP to the folder used by `lifebook.family` and extract it. You should see:

- `install.sh`
- `update.sh`
- `rollback.sh`
- `payload.zip`
- `README-FIRST.txt`
- `FINAL-INSTALLATION-GUIDE.md`

## 4. Run the installer

Open **cPanel → Terminal** and enter the domain folder. Example:

```bash
cd ~/lifebook.family
bash install.sh
```

The installer asks only for:

- Website URL — accept `https://lifebook.family`
- MySQL host — normally `localhost`
- MySQL port — normally `3306`
- Database name
- Database user
- Database password
- First administrator email
- Administrator name
- Administrator password

It automatically generates application secrets, writes `.env`, installs dependencies, builds Next.js, runs MySQL migrations, creates the administrator and requests a Passenger restart.

## 5. Register Passenger once

In **cPanel → Application Manager** (or **Setup Node.js App**) use:

- Domain: `lifebook.family`
- Base URL: `/`
- Application path: the folder containing `app.js`
- Environment: `Production`
- Startup file: `app.js`
- Node.js: 22 / `ea-nodejs22`

Then in Terminal:

```bash
touch tmp/restart.txt
```

## 6. First checks

Open:

- `https://lifebook.family/api/health`
- `https://lifebook.family`
- `https://lifebook.family/admin-login`

Sign in with the administrator email/password created during installation.

## 7. Configure backend services

Go to **Admin → Settings**.

### Email
Configure SMTP and save it. Email must be working **before customers activate purchased QR codes**, because customer ownership is confirmed with a six-digit email OTP.

### Cloudflare R2
Configure private/public R2 buckets for photographs and media.

### Cloudflare Turnstile
Add the site key and secret. Set Turnstile Required to `true` once verified. This protects QR activation and login forms from automated abuse.

## 8. Create ready-made QR inventory

Go to:

`https://lifebook.family/admin/qr`

You can generate QR inventory before a buyer exists. Each QR receives:

- a public code such as `LB7K2M9Q`
- a permanent public URL such as `https://lifebook.family/q/LB7K2M9Q`
- a separate private activation code such as `M7K4-92PL`

Download the activation CSV immediately. Private activation codes are not stored in readable form and cannot be displayed later.

**Print only the public QR on the plaque/product.** Put the private activation code inside the customer pack or send it through a separate secure channel.

## 9. Secure purchase assignment

For QR stock generated before sale, use **Admin → QR Management → Assign stock to a purchaser** after purchase.

Enter:

- Public QR code
- Purchaser email
- Order reference

Once bound, that QR can only begin activation using the same purchaser email.

For retail/offline stock where the purchaser email is not known, the QR can remain unbound. In that case the private activation credential is the proof of purchase, followed by email OTP verification during account creation.

## 10. Customer scan → secure account creation

The intended purchase flow is:

1. Customer purchases a LifeBook QR product.
2. Public QR and private activation code are supplied separately.
3. Customer scans the public QR.
4. LifeBook sees that the QR is unclaimed and opens the activation screen.
5. Customer enters the private activation code and email.
6. If the QR was bound at purchase, the email must match the purchaser email.
7. LifeBook sends a six-digit OTP to that email.
8. Customer enters the OTP.
9. Only then is the LifeBook account created/signed in and the QR temporarily reserved.
10. Customer chooses **My own story**, **Someone I love**, or **Our family story**.
11. When the story is created, the QR is permanently connected to it in the same database transaction.
12. Every future scan resolves to that story according to its privacy/publishing state.

### Security rule

**The public QR alone never grants ownership.**

A secure activation requires:

`public QR + private activation code + verified email OTP`

and, when assigned at purchase:

`+ matching purchaser email`

The application also rate-limits activation attempts and supports Cloudflare Turnstile.

## 11. QR states

Admin can monitor:

- unclaimed
- reserved
- claimed
- suspended
- replaced
- retired

A claimed QR remains permanent even if the story name, slug or privacy changes.

## 12. Backup, update and rollback

Before installation or update the scripts create file backups in:

`lifebook-backups/`

Future update packages can be applied with:

```bash
bash update.sh <update-package.zip>
```

To restore a previous application-file backup:

```bash
bash rollback.sh
```

Database migration rollback is intentionally not automatic.

## 13. If installation stops

Run:

```bash
tail -100 lifebook-install.log
```

Keep that output; it identifies the exact npm, build, database or Passenger failure.
