Files
pyre/scripts/README.md
RogueWave 571e5d04d2 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>
2026-05-31 02:34:13 +00:00

4.7 KiB

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 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

# 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:

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.