# Production Security Checklist (HostGator VPS / own domain)

Work through every item before exposing the app to the internet. Items map to
docs/MASTER_AUDIT_PROMPT.md Phase 17.

## Application config (enforced by code)

- [ ] `ENV=production` in the server's environment — this **disables /docs**
      and makes the app **refuse to start** unless the next two items are done
- [ ] `SECRET_KEY` = fresh 32+ char random string (never reuse the dev one)
- [ ] `REQUIRE_AUTH=true` — every API call needs a login token
- [ ] `RATE_LIMIT_PER_MINUTE` set (default 240; consider 60 for public)
- [ ] `FRONTEND_ORIGIN=https://yourdomain.com` (exact origin, no wildcard)
- [ ] Register ONE account, then consider disabling `/api/auth/register`
      behind the firewall (single-user deployment)

## Secrets

- [ ] Rotate every credential that ever appeared in chat/email/screenshots:
      Gmail app password, Alpaca keys, any LLM keys
- [ ] `.env` file permissions: `chmod 600`, owned by the app user
- [ ] Never commit `.env` (already git-ignored) — verify with `git status`
- [ ] Alpaca: use paper-trading keys only; live keys must not exist on this
      server during Phase 1/2

## Server (HostGator VPS)

- [ ] SSH: key-based login only, password auth off, root login off
- [ ] Firewall (csf/ufw): allow 22, 80, 443 only; block direct 8000/3000
- [ ] Backend bound to 127.0.0.1 (systemd unit already does this) — only
      nginx is public
- [ ] fail2ban (or cPHulk) enabled for SSH + nginx auth failures
- [ ] Automatic security updates enabled
- [ ] MySQL: local-only bind, strong password, dedicated user with least
      privilege on `trading_lab` only

## TLS / nginx

- [ ] Let's Encrypt / AutoSSL on both the site and api hostnames
- [ ] HTTP → HTTPS redirect (in nginx.conf.example)
- [ ] nginx rate limiting as the outer layer:
      `limit_req_zone $binary_remote_addr zone=api:10m rate=5r/s;`
- [ ] TLS 1.2+ only; test with ssllabs.com after setup

## Data & recovery

- [ ] Nightly MySQL dump to a location OFF the VPS; test a restore once
- [ ] Log rotation for scan/report logs
- [ ] Document a 15-minute recovery runbook (restore DB, redeploy, restart)

## Monitoring

- [ ] Uptime monitor on `/health` (UptimeRobot or similar, free)
- [ ] Alert email if the auto-scan scheduler stops (check
      `/api/scheduler/status` — `last_run` should never lag > 2× interval
      during market hours)

## Non-negotiables (from the audit doc)

- Live trading stays impossible: no brokerage order code may be deployed
- Paper/live separation: this server never holds live brokerage credentials
- Any move toward live trading triggers the full MASTER_AUDIT_PROMPT process
  with independent human review
