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.
oll-memory
Coolify app · Dockerfile build · internal service- Repo
- the monorepo (oll-am / Jun2026)
- Branch
feat/bible-verse-reingestdeploy AS-IS — a Coolify preview points at a branch; no merge needed- Base Directory
services/oll-memorythe one field that scopes the build to this service in the monorepo- Dockerfile
- its own
services/oll-memory/Dockerfilebuild-verified clean tonight — image 899 MB, exit 0 - Network alias
oll-memoryon the sharedollamDocker network the frontend reaches it athttp://oll-memory:5008— Docker DNS, no public hop- Port
PORT=5008(app) · Coolify upstream / health port3000- 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
| Var | Value | Note |
|---|---|---|
OLL_MEMORY_SERVICE_TOKEN | secret | must MATCH the frontend's OLL_MEMORY_SERVICE_TOKEN exactly |
DATABASE_URL | required | a 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
| Var | Default | Note |
|---|---|---|
DEFAULT_TOP_K | 8 | candidates returned per query |
CANDIDATE_POOL | 50 | wide retrieval pool before fusion |
RRF_K | 60 | reciprocal-rank-fusion constant |
EMBED_DIM | 768 | matches nomic-embed-text |
CHUNK_SIZE | 512 | tokens per chunk |
EXTRACT_PROVIDER | mock | keyless — 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.
CiteBible frontend
Coolify app · public domain · thin Core/Memory client- Repo
bytesbysamu/ollwrite- Branch
feat/citebible-one-boxself-contained: memory-sidecar + the citation fix + the/carrypage- Base Directory
/- Dockerfile
Dockerfilebuild-verified clean tonight — image 446 MB, exit 0- Public domain
citebible.oll.amDNS wildcards to the VPS → Let's Encrypt auto-TLS. The CiteBible page is the/carryroute.
Env on the /carry path — the two pairs that must MATCH
| Var | Value | Note |
|---|---|---|
OLL_MEMORY_BASE | http://oll-memory:5008 | the App 1 network alias — private hop over ollam |
OLL_MEMORY_SERVICE_TOKEN | MATCH App 1 | same secret as oll-memory's token |
OLL_MODEL_BASE | http://oll-model:5000 | the already-live Model gateway (for the step-back rewrite) |
OLL_MODEL_SERVICE_TOKEN | MATCH oll-model | same 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.
Provision the two dependencies
Neon console · VPSCreate 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).
Create the oll-memory Coolify app → deploy → healthy
branch · base dir · env · network aliasNew 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.
Run the Bible ingester against the Neon DB
python scripts/ingest_bible.pyFrom inside the deployed oll-memory container (Coolify → Terminal), run the ingester — all 66 books, verse + chapter, nomic-prefixed.
/carry-style query returns verses (not empty). Until this runs, retrieval is empty.Create the frontend app → deploy
branch · domain · env → oll-memory + oll-modelNew 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.
The acceptance click
citebible.oll.am/carryOpen 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.
→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.
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.