Files
bible/infra/README.md
T
2026-09-19 13:10:34 -04:00

2.8 KiB

Infrastructure

The site on Railway: one project, bible, with a production and a dev environment, and one service, site, that runs the repo's Dockerfile in Virginia (us-east4-eqdc4a). Railway holds the certificates; server.py does the routing there as it does locally. DNS stays on Cloudflare.

env Railway environment URL
prod production https://bible-2.aerlinn.net
dev dev https://bible-dev.aerlinn.net
railway/       project, environments, service, custom domains, and their
               CNAME + TXT records on Cloudflare
railway-cli/   Railway's CLI as a pinned image (theirs is x86-only)

Tools

Nothing to install but Docker. Terraform and Railway's CLI are services in compose.yaml (profile tools), reading tokens from .env. From the repo root:

docker compose run --rm terraform -chdir=infra/railway plan
docker compose run --rm railway status

Commit .terraform.lock.hcl; it pins the provider builds.

First-time setup

  1. Tokens. A Railway workspace token (account settings -> Tokens, with the workspace selected; a project token cannot make projects) and the Cloudflare token. cp .env.example .env and fill both in.

  2. Project and domains.

    docker compose run --rm terraform -chdir=infra/railway init
    docker compose run --rm terraform -chdir=infra/railway apply
    
  3. Deploy, below. Railway issues each certificate once it sees the CNAME; the first HTTPS requests can fail for a minute or two until then.

Deploying

python3 utils/compile_bible.py    # only when source/ changes
./deploy.sh dev
./deploy.sh prod

deploy.sh copies what the Dockerfile needs into .build/ and uploads that with railway up; Railway builds it and switches over when the new container is running. Not the repo itself: the CLI skips gitignored paths, which includes bible/, and telling it not to would send .env and source/ too. The build logs stream to the terminal, and the dashboard has them as well.

Terraform never deploys, and the provider cannot set anything Railway calls config-as-code (healthchecks, start commands); Railway's defaults do.

State

Local: infra/railway/terraform.tfstate, gitignored. Back it up. If it is lost, nothing on Railway goes away; terraform import each resource back (IDs from the dashboard URLs; the Cloudflare records as <zone_id>/<id>).

Cost

Hobby plan: $5 a month, which includes $5 of usage. The service idles at a few tens of MB and next to no CPU in each environment ($10 per GB-month of memory, $20 per vCPU-month), so both fit in the included usage. Egress is $0.05/GB, about $0.0001 per new reader (the whole library, ~2.2 MB).