Ops Runbook · Coolify Console · 2026-07-05

CiteBible — Coolify Preview Runbook.

Two apps, deploy-as-is: the console fields Sam fills in, and the two dependencies he provisions. CiteBible is a thin frontend over the shared oll-memory RAG engine — so the preview is two Coolify apps, both build-verified clean tonight, deployed straight from their feat branches. No merge, no code changes.

2 Coolify apps both Dockerfiles build-verified · exit 0 2 dependencies Sam provisions

What this is — and why two apps, not one

A precise Coolify-console checklist to stand up a live CiteBible preview at citebible.oll.am. CiteBible is a thin frontend over the shared oll-memory RAG engine — so bundling them into one container would break the house one-service-per-container, reuse-not-rebuild rule. It's two Coolify apps: the engine (internal-only) and the face (public). Both Dockerfiles were build-verified clean tonight — the oll-memory image at 899 MB and the frontend at 446 MB, both exiting 0 — so they deploy AS-IS from their feat branches (a Coolify preview points at a branch; no merge needed). oll-model (model.oll.am) is already live — nothing to do there.

App 1 · the engine

oll-memory — the shared RAG engine. Internal-only, no public domain. Reached by the frontend over the private ollam Docker network at http://oll-memory:5008.

App 2 · the face

CiteBible frontend — the thin client. Public domain citebible.oll.am; its /carry route is the CiteBible page.

The rest of this page is: the two config cards (every console field) · the one real decision (embeddings) · the two dependencies Sam provisions · the numbered order of operations · the acceptance click.

App 1oll-memory — the RAG engine (internal-only)

No public domain. It lives on the shared ollam Docker network under the alias oll-memory; the frontend reaches it at http://oll-memory:5008 with no public hop.

1

oll-memory

Coolify app · Dockerfile build · internal service
Repo
the monorepo (oll-am / Jun2026)
Branch
feat/bible-verse-reingest deploy AS-IS — a Coolify preview points at a branch; no merge needed
Base Directory
services/oll-memory the one field that scopes the build to this service in the monorepo
Dockerfile
its own services/oll-memory/Dockerfile build-verified clean tonight — image 899 MB, exit 0
Network alias
oll-memory on the shared ollam Docker network the frontend reaches it at http://oll-memory:5008 — Docker DNS, no public hop
Port
PORT=5008 (app) · Coolify upstream / health port 3000
Public domain
none — internal-only do NOT bind a domain; it is only ever called service-to-service

Required env — fails fast at boot if missing

VarValueNote
OLL_MEMORY_SERVICE_TOKENsecretmust MATCH the frontend's OLL_MEMORY_SERVICE_TOKEN exactly
DATABASE_URLrequireda private Neon oll_memory DB — the vector extension + tables are auto-created by LlamaIndex on first use

The one real choice — the embedding provider

This is the single decision that shapes whether the preview proves the experience or only proves the wiring. Everything else has a sane default.

✦ Recommended · real quality

EMBED_PROVIDER=ollama

OLLAMA_EMBED_BASE_URL=<VPS Ollama>

OLLAMA_EMBED_MODEL=nomic-embed-text

Real semantic quality — exactly what we've been testing. Requires a self-hosted Ollama reachable on the VPS (dependency 2 below).

Fallback · wiring-only

EMBED_PROVIDER=local (default)

Keyless deterministic HASH embedding. Deploys anywhere, no Ollama needed — but poor retrieval quality. Proves the plumbing works, not the experience.

Recommendation: use ollama for a meaningful preview. Ship local only if you just want to confirm the two apps talk before standing up Ollama.

Optional knobs — sane defaults, leave them alone

VarDefaultNote
DEFAULT_TOP_K8candidates returned per query
CANDIDATE_POOL50wide retrieval pool before fusion
RRF_K60reciprocal-rank-fusion constant
EMBED_DIM768matches nomic-embed-text
CHUNK_SIZE512tokens per chunk
EXTRACT_PROVIDERmockkeyless — fine for CiteBible (retrieval only, no extraction needed)

Post-deploy, one-time — the DB starts empty

A fresh Neon oll_memory has no verses in it, so /carry returns nothing until you ingest. Once App 1 is healthy, run the Bible ingester against the deployed Neon DB:

python scripts/ingest_bible.py

All 66 books, verse + chapter granularity, nomic-prefixed. Run it from inside the deployed oll-memory container (Coolify → Terminal) — or a one-off container with the same DATABASE_URL + Ollama env. Until this runs, /carry returns nothing.

App 2CiteBible frontend → citebible.oll.am

The thin client. Self-contained on its branch — memory-sidecar, the citation fix, and the /carry page all in one place.

2

CiteBible frontend

Coolify app · public domain · thin Core/Memory client
Repo
bytesbysamu/ollwrite
Branch
feat/citebible-one-box self-contained: memory-sidecar + the citation fix + the /carry page
Base Directory
/
Dockerfile
Dockerfile build-verified clean tonight — image 446 MB, exit 0
Public domain
citebible.oll.am DNS wildcards to the VPS → Let's Encrypt auto-TLS. The CiteBible page is the /carry route.

Env on the /carry path — the two pairs that must MATCH

VarValueNote
OLL_MEMORY_BASEhttp://oll-memory:5008the App 1 network alias — private hop over ollam
OLL_MEMORY_SERVICE_TOKENMATCH App 1same secret as oll-memory's token
OLL_MODEL_BASEhttp://oll-model:5000the already-live Model gateway (for the step-back rewrite)
OLL_MODEL_SERVICE_TOKENMATCH oll-modelsame secret the live oll-model expects

Boot-required vars beyond the /carry path — flag & set

The full ollwrite app also reads CORE_API_BASE · GROQ_* · UPLOADTHING_* etc. for its writing features. For a CiteBible-only preview only the OLL_MEMORY_* + OLL_MODEL_* pair is on the /carry path. But if any of the others are boot-required (the app refuses to start without them), set them — a harmless placeholder value is fine, since the writing features aren't exercised in this preview. Sanity: after deploy, if the container crash-loops, read the boot log for the missing var and give it a placeholder.

Benign build warning — safe to ignore

The build emits AUTH_ENABLED set via ENV triggers a Docker SecretsUsedInArgOrEnv lint. It is not a secret — safe to ignore. The build still exits 0.

SamThe two dependencies Sam provisions

Both are console acts. Everything else — oll-model, the shared ollam network, wildcard DNS + TLS — already exists.

Provision these two — nothing else is new infra

Dependency 1 · the database

A Neon oll_memory database (pgvector) for oll-memory's DATABASE_URL.

The vector extension + tables auto-create on first use — you only create the empty DB and paste its connection string.

Dependency 2 · real embeddings

Ollama with nomic-embed-text reachable on the VPS — the one infra piece for real semantic quality.

Skip only if shipping EMBED_PROVIDER=local to prove wiring, not the experience.

Already live, no action: oll-model (model.oll.am) · the shared ollam Docker network · wildcard DNS → the VPS → Let's Encrypt auto-TLS.

StepsOrder of operations

Dependency-ordered: the engine and its data come up first, then the face points at it.

1

Provision the two dependencies

Neon console · VPS

Create the Neon oll_memory database (grab its connection string), and stand up VPS Ollama with nomic-embed-text (unless you're proving wiring only with EMBED_PROVIDER=local).

2

Create the oll-memory Coolify app → deploy → healthy

branch · base dir · env · network alias

New Coolify app off feat/bible-verse-reingest, Base Directory services/oll-memory, its Dockerfile, network alias oll-memory on ollam, PORT=5008 / health 3000. Set the required env (OLL_MEMORY_SERVICE_TOKEN, DATABASE_URL) + the embedding choice. No public domain. Deploy.

Gate: the app is healthy in Coolify before moving on.
3

Run the Bible ingester against the Neon DB

python scripts/ingest_bible.py

From inside the deployed oll-memory container (Coolify → Terminal), run the ingester — all 66 books, verse + chapter, nomic-prefixed.

Gate: a test /carry-style query returns verses (not empty). Until this runs, retrieval is empty.
4

Create the frontend app → deploy

branch · domain · env → oll-memory + oll-model

New Coolify app off bytesbysamu/ollwrite feat/citebible-one-box, domain citebible.oll.am, env pointing at oll-memory (OLL_MEMORY_BASE + matching token) and the live oll-model (OLL_MODEL_BASE + matching token) — plus any boot-required placeholders. Deploy; Let's Encrypt issues TLS automatically.

5

The acceptance click

citebible.oll.am/carry

Open citebible.oll.am/carry, type "my mother is dying and I'm angry at God", and confirm grounded pastoral verses come back — lament and comfort (Psalm 88 · 2 Corinthians 1 · Psalm 42), not topical noise.

Done = a real stranger could type into the box and get comfort, cited, over the deployed engine.

An honest note on branches

These are unmerged feat branches — which is correct for a preview (a Coolify preview points at a branch; you get a live URL without touching main). The branch model says the real deploy path is feat → PR → green CI → merge to main → deliberate tag/deploy, never a preview. And CiteBible getting its own repo is a clean follow-up — it's "just a branch" of ollwrite for now (per Sam), which is exactly the right amount of structure to prove the experience before investing in a home.

Two apps, deploy-as-is — the engine, then the face.

Status: OPS RUNBOOK — ready for Sam's console, 2026-07-05. Two Coolify apps, both Dockerfiles build-verified clean tonight (oll-memory 899 MB · frontend 446 MB · both exit 0), deployed AS-IS from their feat branches. Sam provisions two dependencies (Neon oll_memory pgvector + VPS Ollama nomic-embed-text); everything else (oll-model, the ollam network, wildcard DNS/TLS) already exists. Order: provision deps → deploy oll-memory → ingest the Bible → deploy the frontend to citebible.oll.am → type the flagship query at /carry and confirm grounded pastoral verses. The engineering behind it: the rewrite-first retrieval plan. The face & naming: the branding & design study.