feat(deploy): a Railway deployment of the analysed cases, behind one credential
Three services -- Postgres, API, UI -- with the API on Railway's private network only, so the UI's /api proxy is the single public entry point and there is no CORS. The pipeline cannot run there. Nextflow shells out to `docker run` for VEP and bcftools, and Railway gives you a container, not a Docker daemon. Rather than leave a button that always fails, cases are annotated locally and copied up by scripts/seed-remote.sh, and PUBLIC_PIPELINE_ENABLED=false hides the analyse/score actions and the create-case form. DATABASE_IDLE_CONNECTIONS=false is what makes idling work. Railway decides a service is idle from its *outbound* traffic and sleeps it after ~5-10 minutes; a pooled database connection is outbound traffic, so SQLAlchemy's default pool would have kept the API awake and billable for ever. Setting it false switches to NullPool, which costs a connection per request -- nothing at demo traffic, the wrong trade under real load, hence the flag rather than a rewrite. BASIC_AUTH_USER / BASIC_AUTH_PASSWORD put one shared credential in front of the site. Nothing deployed is patient data, so this stops the URL being wandered into rather than protecting anyone's privacy; unset, the site is open, which is what local development wants. Compared in constant time, and both halves of the credential are checked even when the first fails.
This commit is contained in:
@@ -109,6 +109,43 @@ propagation does not.
|
||||
Local Kubernetes: `make kind` builds the images, loads them into a kind cluster and applies
|
||||
`infra/k8s/overlays/local`.
|
||||
|
||||
## Deploying to Railway
|
||||
|
||||
The quickest way to put it in front of people. Three services — Postgres, the API, the UI — with
|
||||
the API reachable only over Railway's private network, so the UI's `/api` proxy is the single
|
||||
public entry point and there is no CORS.
|
||||
|
||||
```bash
|
||||
railway link --project <id> --environment production --service api
|
||||
cd api && railway up --service api # the repo is on Gitea, so deploy from the working copy
|
||||
cd ../web && railway up --service web
|
||||
```
|
||||
|
||||
Set on the API: `DATABASE_URL` (pointing at `postgres.railway.internal`) and
|
||||
`DATABASE_IDLE_CONNECTIONS=false`. On the UI: `API_INTERNAL_URL=http://api.railway.internal:8000`,
|
||||
`PUBLIC_PIPELINE_ENABLED=false`, and `BASIC_AUTH_USER` / `BASIC_AUTH_PASSWORD`.
|
||||
|
||||
Three things are worth knowing before copying this:
|
||||
|
||||
- **The pipeline cannot run there.** Nextflow shells out to `docker run` for VEP and bcftools, and
|
||||
Railway gives you a container, not a Docker daemon. So the cases are annotated here and copied
|
||||
up with `scripts/seed-remote.sh`, and `PUBLIC_PIPELINE_ENABLED=false` hides the buttons that
|
||||
would otherwise be left to fail. Visitors explore real analysed cases; they do not run VEP.
|
||||
- **`DATABASE_IDLE_CONNECTIONS=false` is what makes sleeping work.** Railway decides a service is
|
||||
idle from its *outbound* traffic, and a pooled database connection is outbound traffic, so the
|
||||
default pool would keep the API awake and billable for ever. It uses `NullPool` instead, which
|
||||
costs a connection per request and is the wrong trade under real load.
|
||||
- **Serverless must be enabled per service and only takes effect on the next deploy.** Leave it off
|
||||
for Postgres, which holds the volume.
|
||||
|
||||
`BASIC_AUTH_USER`/`BASIC_AUTH_PASSWORD` put one shared credential in front of the whole site
|
||||
(`web/src/hooks.server.ts`); unset, the site is open, which is what local development wants.
|
||||
Nothing here is patient data, so this stops the URL being wandered into rather than protecting
|
||||
anyone's privacy.
|
||||
|
||||
Cost: Railway's Hobby plan is $5/month flat including $5 of usage, so it costs that whether or not
|
||||
anyone visits — more at rest than the GCP track below, and much less to operate.
|
||||
|
||||
## Deploying to GCP
|
||||
|
||||
Two tracks, same code. The serverless one is the default because it costs about £1/month idle;
|
||||
|
||||
Reference in New Issue
Block a user