# Moving jarocon.com off Bluehost → AWS Lightsail

**Why this is a small move:** the app has no database on the server — Airtable holds
all data. The server only carries: the PHP code (this repo), the `ops/uploads`
files, the secrets file (`private/airtable-config.php`, already in this repo on
your Mac), and one outgoing `mail()` call. Client GFE/share links are signed with
the secrets, not stored — carry the same secrets file over and **every link ever
sent keeps working**.

**Time:** ~2–4 focused hours to a tested server; DNS cutover the same day.
**Cost:** Lightsail 2 GB instance ≈ $12/month, fixed. No surprise bills.

---

## Step 0 — Prep you can do TODAY (even while Bluehost is down)

1. **AWS account** at https://aws.amazon.com (needs a credit card; use the
   msstoday123 email). Enable MFA on the root account.
2. When the Bluehost panel is reachable again:
   - **Full cPanel backup** (cPanel → Backup → Download a Full Account Backup).
     This is your `ops/uploads` content + the web root extras + insurance.
   - **Lower DNS TTL now**: cPanel → Zone Editor → set the `A` records for
     `jarocon.com` and `www` to TTL **300** (5 min). Do this at least a day
     before cutover so the switch propagates in minutes, not hours.
   - Note where your **email/MX records** point. If your inbox is through
     Bluehost/Google/Microsoft — we do NOT touch MX. Only the website moves.

## Step 1 — Launch the server (~20 min)

Lightsail console → Create instance:
- Region: **us-east-2 (Ohio)** or us-east-1 — anywhere US is fine.
- Blueprint: **OS Only → Ubuntu 24.04 LTS** (NOT the Bitnami LAMP blueprint —
  our setup script builds a cleaner standard stack).
- Plan: **2 GB RAM / 2 vCPU (~$12/mo)**. (1 GB works; 2 GB gives headroom for
  parallel matrix batches.)
- Name it `jarocon-web`.

After it starts:
- Networking tab → **Create static IP** and attach it. Write it down: `<IP>`.
- Networking tab → firewall: keep SSH (22), HTTP (80); **add HTTPS (443)**.
- Account → SSH keys → download the default key to `~/.ssh/`, then:
  ```bash
  chmod 600 ~/.ssh/LightsailDefaultKey-*.pem
  # add to ~/.ssh/config:
  Host jarocon-aws
      HostName <IP>
      User ubuntu
      IdentityFile ~/.ssh/LightsailDefaultKey-<region>.pem
  ```
  Test: `ssh jarocon-aws` → should land in a shell.

## Step 2 — Set up the stack (~10 min, one command)

From the repo folder on your Mac:
```bash
scp -r deploy jarocon-aws:
ssh jarocon-aws "sudo bash deploy/server-setup.sh"
```
Installs Apache + PHP (curl, gd, mbstring), creates `/var/www/jarocon/public`
(web root) and `/var/www/private` (secrets), applies the PHP tuning for the
15-minute AI generations, enables the vhost, and installs the legacy
`/estimating` redirect shims.

## Step 3 — Secrets + code (~10 min)

```bash
# secrets (from this repo's private/ folder — outside the web root on the server)
scp private/airtable-config.php jarocon-aws:/tmp/
ssh jarocon-aws "sudo mv /tmp/airtable-config.php /var/www/private/ \
  && sudo chown root:www-data /var/www/private/airtable-config.php \
  && sudo chmod 640 /var/www/private/airtable-config.php"

# the app
chmod +x deploy/deploy.sh
./deploy/deploy.sh jarocon-aws
```
`ops/lib/config.php` already knows the `/var/www/private/...` path (added
July 15, 2026), so no code edits are needed. From now on, **`./deploy/deploy.sh
jarocon-aws` replaces every cPanel upload.**

## Step 4 — Restore `ops/uploads` (~15 min)

From the Bluehost full backup (or cPanel File Manager → compress & download
`ops/uploads`), then:
```bash
scp uploads-backup.zip jarocon-aws:/tmp/
ssh jarocon-aws "cd /var/www/jarocon/public/ops && sudo unzip -o /tmp/uploads-backup.zip \
  && sudo chown -R www-data:www-data uploads"
```
(If Bluehost stays down, the site still works — only previously uploaded
estimate documents/photos are missing until restored.)

## Step 5 — Outbound email (~20 min, can be done after go-live)

One feature sends email: the GFE client-response notification (`mail()` in
`ops/estimating/action.php`). A fresh server's raw `mail()` lands in spam.
Easiest fix: install msmtp pointed at authenticated SMTP you already have
(your Bluehost/Google/Microsoft mailbox for the COMPANY_EMAIL address):
```bash
ssh jarocon-aws "sudo apt-get install -y msmtp-mta && sudo tee /etc/msmtprc" <<'EOF'
defaults
auth on
tls on
account default
host <smtp.yourmailhost.com>
port 587
user <your-full-email>
password <app-password>
from <your-full-email>
EOF
ssh jarocon-aws "sudo chmod 600 /etc/msmtprc"
```
(Amazon SES is the long-term option; SMTP relay is fine at this volume.)

## Step 6 — TEST before touching DNS (~30–60 min)

Point only YOUR Mac at the new server:
```bash
sudo sh -c 'echo "<IP> jarocon.com www.jarocon.com" >> /etc/hosts'
```
Browse http://jarocon.com/ops/ and walk the greatest hits: login, open an
estimate, edit a matrix cell, Generate/Review scope (AI), GFE page, GFE PDF
download, upload a document, an OLD client share link, `/estimating/...`
legacy link redirect. When happy:
```bash
sudo sed -i '' '/jarocon.com/d' /etc/hosts   # remove the override
```

## Step 7 — Cutover (~5 min + propagation)

In the DNS zone (Bluehost Zone Editor, unless you move DNS):
- `A  jarocon.com     → <IP>`
- `A  www             → <IP>`  (or CNAME www → jarocon.com)
- **Touch nothing else** — MX, TXT/SPF for email stay as they are.

Then issue the HTTPS certificate (needs DNS pointing here first):
```bash
ssh jarocon-aws "sudo certbot --apache -d jarocon.com -d www.jarocon.com \
  --redirect -m msstoday123@gmail.com --agree-tos --no-eff-email"
```
Auto-renews via systemd; nothing more to do.

## Step 8 — Parallel run & decommission

Keep the Bluehost account alive ~2 weeks (old IP still serves anyone with
cached DNS; nothing breaks either way since both read the same Airtable).
Verify new uploads land on the new server, then cancel Bluehost hosting —
**but keep the domain registration/DNS (and email, if hosted there) unless
you migrate those too.** Optional hardening later: move DNS to Route 53,
Lightsail automatic snapshots (enable in console — $1–2/mo, daily backups).

---

## Day-2 cheatsheet

| Task | Command |
|---|---|
| Deploy code changes | `./deploy/deploy.sh jarocon-aws` |
| Server shell | `ssh jarocon-aws` |
| Apache logs | `ssh jarocon-aws "sudo tail -f /var/log/apache2/jarocon-error.log"` |
| PHP errors | `ssh jarocon-aws "sudo tail -f /var/log/php_errors.log"` |
| Restart web server | `ssh jarocon-aws "sudo systemctl restart apache2"` |
| Reboot box | Lightsail console → instance → Reboot |

No more entry-process caps, no shared-hosting neighbors, no cPanel uploads.
