docs(deploy): correct stale infra facts after GCP name-alignment
The deploy docs predated the GCP name-alignment and described infrastructure that no longer exists. Discovered during the v0.31.4 deploy. Corrections: - Project wiggleverse-rfc -> wiggleverse-ohm; VM rfc-app -> ohm-rfc-app; install path /opt/rfc-app -> /opt/ohm-rfc-app; system user + service rfc-app -> ohm-rfc-app; external IP 34.132.29.41 -> 136.116.40.66. - SSH is now IAP-only (direct port 22 times out): document --tunnel-through-iap on every gcloud compute ssh. - Meta repo wiggleverse/meta -> wiggleverse/ohm-content. - Two-remote reality: the VM's git origin is git.benstull.org/benstull/ rfc-app, a SEPARATE Gitea from the release one (git.wiggleverse.org) that does not auto-mirror — so a release must be pushed to the benstull remote before the VM can fetch it. The VM tracks a detached release TAG, not a branch. - Frontend-only changes are live once dist/ is rebuilt (nginx serves it directly); pip install only when requirements.txt changed. Docs-only; no version bump (cf. the docs-only commit after v0.31.3). The First-Time Deployment blocks keep the structural commands with a substitution note rather than unvalidated rewrites. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -20,15 +20,24 @@ The v1 build is complete (8 slices shipped, 125 passing integration tests). New
|
|||||||
|
|
||||||
The RFC app runs on its own dedicated GCP VM in a separate project from the Gitea VM. The two coexist under `wiggleverse.org` but are otherwise unrelated infrastructure.
|
The RFC app runs on its own dedicated GCP VM in a separate project from the Gitea VM. The two coexist under `wiggleverse.org` but are otherwise unrelated infrastructure.
|
||||||
|
|
||||||
|
> **⚠️ Infrastructure was realigned (GCP name-alignment, ~2026-05).** The
|
||||||
|
> GCP project, VM, install path, system user, and systemd unit were all
|
||||||
|
> renamed, the static IP changed, and SSH is now **IAP-only** (direct
|
||||||
|
> port-22 connections time out). The tables below are the current truth;
|
||||||
|
> if you find an older clone of this doc naming `wiggleverse-rfc` /
|
||||||
|
> `rfc-app` / `/opt/rfc-app` / `34.132.29.41`, it predates the alignment.
|
||||||
|
|
||||||
| Property | Value |
|
| Property | Value |
|
||||||
|----------|-------|
|
|----------|-------|
|
||||||
| GCP project | `wiggleverse-rfc` |
|
| GCP project | `wiggleverse-ohm` |
|
||||||
| VM name | `rfc-app` |
|
| VM name | `ohm-rfc-app` |
|
||||||
| VM type | e2-small |
|
| VM type | e2-small |
|
||||||
| Zone | us-central1-a |
|
| Zone | us-central1-a |
|
||||||
| OS | Debian 12 (bookworm) |
|
| OS | Debian 12 (bookworm) |
|
||||||
| Static IP | 34.132.29.41 |
|
| External IP | `136.116.40.66` |
|
||||||
| Linux user (OS Login) | `benstull` |
|
| SSH | **IAP-only** — `gcloud compute ssh … --tunnel-through-iap` (port 22 is firewalled off the public internet) |
|
||||||
|
| OS Login SSH user | `ben_wiggleverse_org` (auto-derived; you don't type it) |
|
||||||
|
| App system user | `ohm-rfc-app` |
|
||||||
|
|
||||||
For reference, the separate Gitea VM is `wiggleverse` project / `gitea` VM / 34.55.46.221.
|
For reference, the separate Gitea VM is `wiggleverse` project / `gitea` VM / 34.55.46.221.
|
||||||
|
|
||||||
@@ -36,7 +45,7 @@ For reference, the separate Gitea VM is `wiggleverse` project / `gitea` VM / 34.
|
|||||||
|
|
||||||
| Record | Type | Value | Proxy |
|
| Record | Type | Value | Proxy |
|
||||||
|--------|------|-------|-------|
|
|--------|------|-------|-------|
|
||||||
| `ohm.wiggleverse.org` | A | 34.132.29.41 | DNS-only (gray cloud) |
|
| `ohm.wiggleverse.org` | A | `136.116.40.66` | DNS-only (gray cloud) |
|
||||||
| `_dmarc.wiggleverse.org` | TXT | `v=DMARC1; p=none; rua=mailto:ben@wiggleverse.org` | n/a |
|
| `_dmarc.wiggleverse.org` | TXT | `v=DMARC1; p=none; rua=mailto:ben@wiggleverse.org` | n/a |
|
||||||
|
|
||||||
> Note: `ohm.wiggleverse.org` uses **Let's Encrypt via certbot** directly on the VM. Keep the A record **DNS only (gray cloud)** — Cloudflare Flexible SSL would conflict with certbot.
|
> Note: `ohm.wiggleverse.org` uses **Let's Encrypt via certbot** directly on the VM. Keep the A record **DNS only (gray cloud)** — Cloudflare Flexible SSL would conflict with certbot.
|
||||||
@@ -48,24 +57,25 @@ SPF (`v=spf1 include:_spf.google.com ~all`) and DKIM (`google._domainkey`) for `
|
|||||||
| Component | Details |
|
| Component | Details |
|
||||||
|-----------|---------|
|
|-----------|---------|
|
||||||
| Backend | Python 3.11, FastAPI, uvicorn (single process) |
|
| Backend | Python 3.11, FastAPI, uvicorn (single process) |
|
||||||
| Database | SQLite in WAL mode at `/opt/rfc-app/backend/data/rfc-app.db` |
|
| Database | SQLite in WAL mode at `/opt/ohm-rfc-app/backend/data/rfc-app.db` |
|
||||||
| Frontend | React 19, Vite 8, Tiptap 3, React Router 7 |
|
| Frontend | React 19, Vite 8, Tiptap 3, React Router 7 |
|
||||||
| Web server | nginx — serves `frontend/dist/` as static SPA, proxies `/api/` and `/auth/` to uvicorn on `127.0.0.1:8000` |
|
| Web server | nginx — serves `frontend/dist/` as static SPA, proxies `/api/` and `/auth/` to uvicorn on `127.0.0.1:8000` |
|
||||||
| Process manager | systemd unit `rfc-app.service`, runs as `rfc-app` system user |
|
| Process manager | systemd unit `ohm-rfc-app.service`, runs as `ohm-rfc-app` system user |
|
||||||
| TLS | Let's Encrypt via certbot |
|
| TLS | Let's Encrypt via certbot |
|
||||||
| Git backend | Gitea at `git.wiggleverse.org`, bot service account `rfc-bot` |
|
| Content Gitea (the bot's writes) | Gitea at `git.wiggleverse.org`, org `wiggleverse`, meta repo `ohm-content` (`wiggleverse/ohm-content`), bot service account `rfc-bot` |
|
||||||
|
| Code-deploy source (the VM's git origin) | **`https://git.benstull.org/benstull/rfc-app.git`** — a *different* Gitea from the content one. See the two-remote note under "Deploying a New Version." |
|
||||||
| Email | Google Workspace SMTP relay (`smtp-relay.gmail.com:587`), AUTH'd as `ben@wiggleverse.org`, From `notifications@wiggleverse.org` |
|
| Email | Google Workspace SMTP relay (`smtp-relay.gmail.com:587`), AUTH'd as `ben@wiggleverse.org`, From `notifications@wiggleverse.org` |
|
||||||
|
|
||||||
### Key Paths on the VM
|
### Key Paths on the VM
|
||||||
|
|
||||||
| Path | Contents |
|
| Path | Contents |
|
||||||
|------|---------|
|
|------|---------|
|
||||||
| `/opt/rfc-app/` | App root (owned by `rfc-app` user) |
|
| `/opt/ohm-rfc-app/` | App root (owned by `ohm-rfc-app` user) |
|
||||||
| `/opt/rfc-app/backend/.env` | All secrets and config (mode 0600) |
|
| `/opt/ohm-rfc-app/backend/.env` | All secrets and config (mode 0600) |
|
||||||
| `/opt/rfc-app/backend/data/rfc-app.db` | SQLite database |
|
| `/opt/ohm-rfc-app/backend/data/rfc-app.db` | SQLite database |
|
||||||
| `/opt/rfc-app/frontend/dist/` | Built React SPA (served by nginx) |
|
| `/opt/ohm-rfc-app/frontend/dist/` | Built React SPA (served by nginx) |
|
||||||
| `/etc/nginx/sites-available/ohm.wiggleverse.org` | nginx vhost config |
|
| `/etc/nginx/sites-available/ohm.wiggleverse.org` | nginx vhost config |
|
||||||
| `/etc/systemd/system/rfc-app.service` | systemd unit |
|
| `/etc/systemd/system/ohm-rfc-app.service` | systemd unit |
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -91,7 +101,7 @@ Created in Gitea as `rfc-bot`. Token scopes: `write:repository`, `write:user`, `
|
|||||||
|
|
||||||
### Meta repo
|
### Meta repo
|
||||||
|
|
||||||
`wiggleverse/meta` — seeded by `scripts/seed_meta_repo.py`. Contains `PHILOSOPHY.md`, `README.md`, `CONTRIBUTING.md`, and `rfcs/` directory. Gitea webhook registered to `https://ohm.wiggleverse.org/api/webhooks/gitea`.
|
`wiggleverse/ohm-content` (the `META_REPO` value is `ohm-content`) — seeded by `scripts/seed_meta_repo.py`. Contains `PHILOSOPHY.md`, `README.md`, `CONTRIBUTING.md`, and `rfcs/` directory. Gitea webhook registered to `https://ohm.wiggleverse.org/api/webhooks/gitea`.
|
||||||
|
|
||||||
### OAuth2 app
|
### OAuth2 app
|
||||||
|
|
||||||
@@ -167,23 +177,52 @@ HYGIENE_TICK_SECONDS=3600
|
|||||||
|
|
||||||
## Deploying a New Version
|
## Deploying a New Version
|
||||||
|
|
||||||
SSH into the VM:
|
> **⚠️ Two-remote step — do this FIRST.** The framework's release flow
|
||||||
|
> (branches, PRs, version tags) happens on **`git.wiggleverse.org`**
|
||||||
|
> (`ben.stull/rfc-app`). But the VM's git origin is a *separate* Gitea,
|
||||||
|
> **`git.benstull.org/benstull/rfc-app`**, which does **not** auto-mirror
|
||||||
|
> from the release Gitea. So after a release is merged + tagged on
|
||||||
|
> `git.wiggleverse.org`, you must push `main` and the new tag to the
|
||||||
|
> `benstull` remote before the VM can fetch them:
|
||||||
|
> ```bash
|
||||||
|
> # from your local rfc-app clone, on main at the merged release tip:
|
||||||
|
> git push benstull main vX.Y.Z # benstull = git@git.benstull.org:benstull/rfc-app.git
|
||||||
|
> ```
|
||||||
|
> If `git ls-remote benstull vX.Y.Z` comes back empty, the VM cannot see
|
||||||
|
> the release yet — push it first. (Wiring the two Gitea instances to
|
||||||
|
> mirror would remove this step; until then it's manual.)
|
||||||
|
|
||||||
|
SSH into the VM (IAP-only — the `--tunnel-through-iap` flag is required):
|
||||||
```bash
|
```bash
|
||||||
gcloud compute ssh rfc-app --zone=us-central1-a --project=wiggleverse-rfc
|
gcloud compute ssh ohm-rfc-app --zone=us-central1-a --project=wiggleverse-ohm --tunnel-through-iap
|
||||||
```
|
```
|
||||||
|
|
||||||
Pull the latest code, reinstall deps, restart:
|
Fetch + check out the release tag (the VM tracks a **detached** tag, not
|
||||||
|
a branch), then restart. Backend deps only need reinstalling when
|
||||||
|
`requirements.txt` changed:
|
||||||
```bash
|
```bash
|
||||||
sudo -u rfc-app git -C /opt/rfc-app pull
|
sudo -u ohm-rfc-app git -C /opt/ohm-rfc-app fetch origin --tags
|
||||||
sudo -u rfc-app /opt/rfc-app/backend/.venv/bin/pip install \
|
sudo -u ohm-rfc-app git -C /opt/ohm-rfc-app checkout vX.Y.Z
|
||||||
-r /opt/rfc-app/backend/requirements.txt
|
# only if backend deps changed:
|
||||||
sudo systemctl restart rfc-app
|
sudo -u ohm-rfc-app /opt/ohm-rfc-app/backend/.venv/bin/pip install \
|
||||||
|
-r /opt/ohm-rfc-app/backend/requirements.txt
|
||||||
|
sudo systemctl restart ohm-rfc-app
|
||||||
```
|
```
|
||||||
|
|
||||||
For frontend changes, build on the VM directly (Node 20+ is already there):
|
For frontend changes, build on the VM directly (Node 20+ is already there):
|
||||||
```bash
|
```bash
|
||||||
cd /opt/rfc-app/frontend && sudo -u rfc-app npm ci
|
cd /opt/ohm-rfc-app/frontend && sudo -u ohm-rfc-app npm ci
|
||||||
sudo -u rfc-app npm run build
|
sudo -u ohm-rfc-app npm run build
|
||||||
|
```
|
||||||
|
|
||||||
|
Smoke test (asset hashes change on every rebuild, so a match proves the
|
||||||
|
new bundle is live):
|
||||||
|
```bash
|
||||||
|
# public:
|
||||||
|
curl -s -o /dev/null -w '%{http_code} %{remote_ip}\n' https://ohm.wiggleverse.org/
|
||||||
|
curl -s https://ohm.wiggleverse.org/ | grep -oE 'assets/index-[A-Za-z0-9_-]+\.(js|css)'
|
||||||
|
# backend startup line, on the VM:
|
||||||
|
sudo journalctl -u ohm-rfc-app -n 20 --no-pager | grep 'RFC app started'
|
||||||
```
|
```
|
||||||
|
|
||||||
`npm ci` installs strictly from the committed `package-lock.json` and
|
`npm ci` installs strictly from the committed `package-lock.json` and
|
||||||
@@ -192,7 +231,7 @@ to rewrite the lockfile in place (notably stripping `libc` fields on
|
|||||||
optional rollup native packages), which then conflicts with `git
|
optional rollup native packages), which then conflicts with `git
|
||||||
checkout <tag>` on the next deploy.
|
checkout <tag>` on the next deploy.
|
||||||
|
|
||||||
The output lands in `/opt/rfc-app/frontend/dist/` owned by `rfc-app` — nginx serves it directly, no copy step needed.
|
The output lands in `/opt/ohm-rfc-app/frontend/dist/` owned by `ohm-rfc-app` — nginx serves it directly, no copy step needed.
|
||||||
|
|
||||||
(Building locally and `gcloud compute scp`-ing the dist also works. Plain `rsync -e ssh` from the Mac fails because OS Login uses short-lived SSH certs that only the gcloud wrapper can mint interactively.)
|
(Building locally and `gcloud compute scp`-ing the dist also works. Plain `rsync -e ssh` from the Mac fails because OS Login uses short-lived SSH certs that only the gcloud wrapper can mint interactively.)
|
||||||
|
|
||||||
@@ -202,6 +241,15 @@ Schema migrations run automatically on restart (append-only, safe to re-run).
|
|||||||
|
|
||||||
## First-Time Deployment (new server)
|
## First-Time Deployment (new server)
|
||||||
|
|
||||||
|
> **Note on names:** the command blocks in this section predate the GCP
|
||||||
|
> name-alignment and still spell the pre-alignment project/VM/path/user
|
||||||
|
> (`wiggleverse-rfc` / `rfc-app` / `/opt/rfc-app` / `rfc-app` /
|
||||||
|
> `34.132.29.41`). They're kept as the structural reference. When standing
|
||||||
|
> up a box today, substitute the current values from the Host/Paths tables
|
||||||
|
> at the top: project `wiggleverse-ohm`, VM `ohm-rfc-app`, install path
|
||||||
|
> `/opt/ohm-rfc-app`, system user `ohm-rfc-app`, service `ohm-rfc-app`, IP
|
||||||
|
> `136.116.40.66`, and SSH via `--tunnel-through-iap`.
|
||||||
|
|
||||||
### 1. Add DNS record
|
### 1. Add DNS record
|
||||||
Add `ohm.wiggleverse.org` → 34.132.29.41 as an A record in Cloudflare, **DNS only (gray cloud)**. Do not proxy — certbot needs to reach the VM directly.
|
Add `ohm.wiggleverse.org` → 34.132.29.41 as an A record in Cloudflare, **DNS only (gray cloud)**. Do not proxy — certbot needs to reach the VM directly.
|
||||||
|
|
||||||
@@ -307,7 +355,7 @@ Paste the following into a new Claude session to continue development:
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
> I'm working on the **Wiggleverse RFC App** — a FastAPI + SQLite + React + Vite application deployed at `ohm.wiggleverse.org` on a GCP e2-small VM (`rfc-app` in the `wiggleverse-rfc` project; separate from the `gitea` VM in `wiggleverse` that runs Gitea at `git.wiggleverse.org`). The app is the primary interface for the Open Human Model (OHM) RFC working group.
|
> I'm working on the **Wiggleverse RFC App** — a FastAPI + SQLite + React + Vite application deployed at `ohm.wiggleverse.org` on a GCP e2-small VM (`ohm-rfc-app` in the `wiggleverse-ohm` project; separate from the `gitea` VM in `wiggleverse` that runs Gitea at `git.wiggleverse.org`). The app is the primary interface for the Open Human Model (OHM) RFC working group.
|
||||||
>
|
>
|
||||||
> **Stack:**
|
> **Stack:**
|
||||||
> - Backend: Python 3.11, FastAPI, uvicorn (single process), SQLite WAL mode
|
> - Backend: Python 3.11, FastAPI, uvicorn (single process), SQLite WAL mode
|
||||||
@@ -323,11 +371,12 @@ Paste the following into a new Claude session to continue development:
|
|||||||
> - 10 append-only schema migrations in `backend/migrations/`
|
> - 10 append-only schema migrations in `backend/migrations/`
|
||||||
>
|
>
|
||||||
> **Deployment:**
|
> **Deployment:**
|
||||||
> - SSH: `gcloud compute ssh rfc-app --zone=us-central1-a --project=wiggleverse-rfc`
|
> - SSH (IAP-only): `gcloud compute ssh ohm-rfc-app --zone=us-central1-a --project=wiggleverse-ohm --tunnel-through-iap`
|
||||||
> - Code at `/opt/rfc-app/` on the VM, owned by `rfc-app` system user
|
> - Code at `/opt/ohm-rfc-app/` on the VM, owned by `ohm-rfc-app` system user; tracks a detached release **tag**
|
||||||
> - `.env` at `/opt/rfc-app/backend/.env` (mode 0600)
|
> - The VM's git origin is `git.benstull.org/benstull/rfc-app` — a *different* Gitea from the release one (`git.wiggleverse.org`); push `main` + the new tag to the `benstull` remote before deploying
|
||||||
> - Frontend built **on the VM** (Node 20 is installed there) with `npm run build` directly into `/opt/rfc-app/frontend/dist/`
|
> - `.env` at `/opt/ohm-rfc-app/backend/.env` (mode 0600)
|
||||||
> - Restart to deploy: `sudo systemctl restart rfc-app`
|
> - Frontend built **on the VM** (Node 20 is installed there) with `npm run build` directly into `/opt/ohm-rfc-app/frontend/dist/`
|
||||||
|
> - Restart to deploy: `sudo systemctl restart ohm-rfc-app`
|
||||||
> - Migrations run automatically on startup
|
> - Migrations run automatically on startup
|
||||||
>
|
>
|
||||||
> **Source is at `~/git/rfc-app/`.**
|
> **Source is at `~/git/rfc-app/`.**
|
||||||
|
|||||||
+45
-10
@@ -1,9 +1,26 @@
|
|||||||
# Runbook
|
# Runbook
|
||||||
|
|
||||||
Single-host deployment of the RFC app at `ohm.wiggleverse.org`, sharing
|
Single-host deployment of the RFC app at `ohm.wiggleverse.org`. The shape
|
||||||
infrastructure with `git.wiggleverse.org` (same Gitea instance, same nginx,
|
matches §4.2: one process, one SQLite file, no separate worker.
|
||||||
same Let's Encrypt). The shape matches §4.2: one process, one SQLite file,
|
|
||||||
no separate worker.
|
> **⚠️ Current deployment names (post GCP name-alignment, ~2026-05).**
|
||||||
|
> The command blocks below were written with the original names and use
|
||||||
|
> `/opt/rfc-app`, system user `rfc-app`, and service `rfc-app`. The live
|
||||||
|
> OHM box uses the realigned names — substitute throughout:
|
||||||
|
>
|
||||||
|
> | Was | Now |
|
||||||
|
> | --- | --- |
|
||||||
|
> | GCP project `wiggleverse-rfc` | `wiggleverse-ohm` |
|
||||||
|
> | VM `rfc-app` | `ohm-rfc-app` |
|
||||||
|
> | install path `/opt/rfc-app` | `/opt/ohm-rfc-app` |
|
||||||
|
> | system user `rfc-app` | `ohm-rfc-app` |
|
||||||
|
> | service `rfc-app.service` | `ohm-rfc-app.service` |
|
||||||
|
> | SSH | IAP-only: `gcloud compute ssh ohm-rfc-app --zone=us-central1-a --project=wiggleverse-ohm --tunnel-through-iap` |
|
||||||
|
> | meta repo `wiggleverse/meta` | `wiggleverse/ohm-content` |
|
||||||
|
>
|
||||||
|
> The VM's git origin is **`git.benstull.org/benstull/rfc-app`** — a
|
||||||
|
> *different* Gitea from the release one (`git.wiggleverse.org`). See §2.5.
|
||||||
|
> The full current infra table lives in `DEPLOY-NEW-SESSION-PROMPT.md`.
|
||||||
|
|
||||||
Bring-up order: host prep → Gitea side (bot, OAuth, meta repo) → app side
|
Bring-up order: host prep → Gitea side (bot, OAuth, meta repo) → app side
|
||||||
(code, venv, build, .env) → web server side (nginx, certbot) → systemd →
|
(code, venv, build, .env) → web server side (nginx, certbot) → systemd →
|
||||||
@@ -345,16 +362,34 @@ pinned = 1 WHERE rfc_slug = ? AND branch_name = ?`).
|
|||||||
|
|
||||||
### 2.5 Updating after a push
|
### 2.5 Updating after a push
|
||||||
|
|
||||||
|
The live OHM box uses the realigned names (see the callout at the top)
|
||||||
|
and deploys by checking out a **release tag** (detached HEAD), not by
|
||||||
|
pulling a branch. Its git origin is `git.benstull.org/benstull/rfc-app`,
|
||||||
|
which does **not** auto-mirror from the release Gitea
|
||||||
|
(`git.wiggleverse.org`) — so first push `main` + the new tag there:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
sudo -u rfc-app git -C /opt/rfc-app pull
|
# from your local rfc-app clone, on main at the merged release tip:
|
||||||
sudo -u rfc-app /opt/rfc-app/backend/.venv/bin/pip install \
|
git push benstull main vX.Y.Z # benstull = git@git.benstull.org:benstull/rfc-app.git
|
||||||
-r /opt/rfc-app/backend/requirements.txt
|
```
|
||||||
# Rebuild the frontend locally and rsync dist/ as in 1.3.2.
|
|
||||||
sudo systemctl restart rfc-app
|
Then on the VM (SSH is IAP-only):
|
||||||
|
|
||||||
|
```sh
|
||||||
|
gcloud compute ssh ohm-rfc-app --zone=us-central1-a --project=wiggleverse-ohm --tunnel-through-iap
|
||||||
|
sudo -u ohm-rfc-app git -C /opt/ohm-rfc-app fetch origin --tags
|
||||||
|
sudo -u ohm-rfc-app git -C /opt/ohm-rfc-app checkout vX.Y.Z
|
||||||
|
# only when backend deps changed:
|
||||||
|
sudo -u ohm-rfc-app /opt/ohm-rfc-app/backend/.venv/bin/pip install \
|
||||||
|
-r /opt/ohm-rfc-app/backend/requirements.txt
|
||||||
|
# frontend changes: build on the VM (Node 20+ is there) — output is served directly by nginx:
|
||||||
|
cd /opt/ohm-rfc-app/frontend && sudo -u ohm-rfc-app npm ci && sudo -u ohm-rfc-app npm run build
|
||||||
|
sudo systemctl restart ohm-rfc-app
|
||||||
```
|
```
|
||||||
|
|
||||||
The §5 schema migrations run on startup and are append-only. A restart
|
The §5 schema migrations run on startup and are append-only. A restart
|
||||||
is the entire deploy.
|
is the entire backend deploy; a frontend-only change is live as soon as
|
||||||
|
the new `dist/` is built (nginx serves it directly).
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user