feat(infra): Phase 0 provisioning + dev status dashboard
- scripts/phase0-provision.sh: idempotent root setup (nginx, PostgreSQL, Redis, certbot/TLS, UFW). Opens 22/2222/80/443 before enabling UFW so SSH and Gitea git-SSH can't be locked out. Redis/Postgres stay localhost-only. - infra/nginx/feedthepyre.com.conf: vhost serving the status page; commented web(:3000)/api(:4000) reverse-proxy blocks ready for app deploy. - infra/status/: data-driven dev status dashboard (status.json + gen-status.mjs + prebuilt index.html), served at feedthepyre.com. - ecosystem.config.cjs (PM2), infra/systemd/pm2-pyre.service, infra/logrotate/pyre, scripts/backup.sh — process mgmt + ops (inert until apps are built). Built by 4 parallel agents, reviewed by 2 audit agents; audit fixes applied (logs dir creation, port-citation accuracy, status truthfulness). pm2 installed user-level. Privileged steps gated on `sudo bash scripts/phase0-provision.sh`. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
102
scripts/README.md
Normal file
102
scripts/README.md
Normal file
@@ -0,0 +1,102 @@
|
||||
# PYRE — `scripts/`
|
||||
|
||||
Operational scripts for the PYRE VPS (Ubuntu 24.04). These cover **Phase 0**
|
||||
(server + repo setup) per `docs/PYRE_MVP_DESIGN.md` §12, §18, §19.
|
||||
|
||||
| Script | Purpose | Who runs it |
|
||||
| --- | --- | --- |
|
||||
| [`phase0-provision.sh`](./phase0-provision.sh) | Idempotent **root** provisioning: nginx, PostgreSQL, Redis, certbot/TLS, UFW, systemd pm2 unit, logrotate, status page. | root (`sudo`) |
|
||||
| `gen-status.mjs` | Generates the public `status.json` for the status page. *(Authored by another agent — see that file's header for usage.)* | `pyre` user |
|
||||
| `backup.sh` | Database / config backup routine. *(Authored by another agent — see that file's header for usage.)* | `pyre` user / cron |
|
||||
|
||||
---
|
||||
|
||||
## `phase0-provision.sh`
|
||||
|
||||
Provisions all **system-level** services PYRE depends on. It is
|
||||
**idempotent and safe to re-run** — every step checks current state before
|
||||
changing anything.
|
||||
|
||||
### What it does NOT do
|
||||
|
||||
- Does **not** install Node.js 22, pnpm, the repo, or app `.env` files
|
||||
(those are handled separately / by the `pyre` user).
|
||||
- Does **not** run a Solana validator/RPC node or any local LLM/image model
|
||||
(explicitly out of scope per design §11/§12).
|
||||
- Does **not** change Postgres `listen_addresses` or expose Redis — both stay
|
||||
**localhost-only**.
|
||||
- Does **not** store any wallet private key. PYRE never holds keys; there is
|
||||
intentionally no key/mnemonic variable anywhere.
|
||||
|
||||
### Steps
|
||||
|
||||
1. `apt-get update` + install `nginx postgresql postgresql-contrib redis-server certbot python3-certbot-nginx ufw`.
|
||||
2. Enable + start `postgresql` and `redis-server`.
|
||||
3. Create Postgres role `pyre` (LOGIN, NOCREATEDB) and database `pyre` owned by it — only if absent. Matches `DATABASE_URL=postgresql://pyre:pyre@localhost:5432/pyre` from `.env.example`.
|
||||
4. Harden Redis: `bind 127.0.0.1 ::1` and `maxmemory-policy noeviction`, then restart.
|
||||
5. UFW: allow `22`, `2222`, `80`, `443` **before** enabling the firewall.
|
||||
6. Install the nginx vhost, remove the default site, validate, reload.
|
||||
7. Create the status-page webroot and copy in `index.html` / `status.json`.
|
||||
8. Obtain/renew the TLS certificate via certbot (nginx plugin), with redirect.
|
||||
9. Install the `pm2-pyre` systemd unit (enable, don't start) and the logrotate config.
|
||||
10. Print versions, service statuses, a checklist, and a reminder to set real secrets.
|
||||
|
||||
### Prerequisites
|
||||
|
||||
- Ubuntu 24.04 with the base setup already done (`pyre` user, SSH key auth,
|
||||
root login disabled, Fail2ban) — per design §12.
|
||||
- The repo present at **`/home/pyre/pyre`**, owned by `pyre`.
|
||||
- The `infra/` config sources present (authored by other agents):
|
||||
- `infra/nginx/feedthepyre.com.conf`
|
||||
- `infra/status/index.html`, `infra/status/status.json`
|
||||
- `infra/systemd/pm2-pyre.service`
|
||||
- `infra/logrotate/pyre`
|
||||
- If any are missing the script **warns and continues** rather than failing,
|
||||
so you can re-run it once the sources exist.
|
||||
- **DNS must already point `feedthepyre.com` and `www.feedthepyre.com` at this
|
||||
box** before the TLS step can succeed. If DNS isn't live yet, certbot is
|
||||
skipped gracefully — just re-run the script later.
|
||||
|
||||
### How to run
|
||||
|
||||
```bash
|
||||
# Default (dev) — uses DB password "pyre" and the built-in certbot email:
|
||||
sudo bash scripts/phase0-provision.sh
|
||||
```
|
||||
|
||||
It must run as **root**. If you forget `sudo`, it re-execs itself under `sudo`
|
||||
(or errors with instructions if `sudo` is unavailable).
|
||||
|
||||
### Overridable environment variables
|
||||
|
||||
| Variable | Default | Notes |
|
||||
| --- | --- | --- |
|
||||
| `PYRE_DB_PASSWORD` | `pyre` | Postgres password for role `pyre`. The default is **dev-only**; the script prints a loud warning when it's used. Set a real one for production. Only applied when the role is first created — re-runs do not change an existing role's password. |
|
||||
| `CERTBOT_EMAIL` | `a31s15.roguewave@gmail.com` | Let's Encrypt registration / expiry-notice email. |
|
||||
|
||||
Pass overrides via `sudo -E` so the environment is preserved:
|
||||
|
||||
```bash
|
||||
PYRE_DB_PASSWORD='a-strong-secret' \
|
||||
CERTBOT_EMAIL='ops@feedthepyre.com' \
|
||||
sudo -E bash scripts/phase0-provision.sh
|
||||
```
|
||||
|
||||
If you set a non-default `PYRE_DB_PASSWORD`, update `DATABASE_URL` in the
|
||||
per-app `.env` files to match.
|
||||
|
||||
### ⚠️ UFW / SSH warning
|
||||
|
||||
This script runs **over SSH** and enables the firewall. It deliberately allows
|
||||
the SSH ports **before** enabling UFW:
|
||||
|
||||
- **`22/tcp` (system SSH)** and **`2222/tcp` (Gitea git-SSH)** MUST stay open.
|
||||
If you remove these allow rules, you will **permanently lose remote access**
|
||||
to the box. The script never removes existing allow rules; if you edit UFW
|
||||
by hand, keep 22 and 2222 open.
|
||||
|
||||
### After provisioning
|
||||
|
||||
Set **real secrets** in the per-app `.env` files (copy from `.env.example`):
|
||||
`DATABASE_URL`, `ANTHROPIC_API_KEY` / `OPENAI_API_KEY` / `IMAGE_GEN_API_KEY`,
|
||||
`ADMIN_API_TOKEN`, `SOLANA_RPC_URL`, etc. Never commit a real `.env`.
|
||||
Reference in New Issue
Block a user