okengine 0.9.1 → 0.10.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +1 -1
- package/manifest.v1.schema.json +9 -1
- package/package.json +3 -3
- package/site/content/docs/console/runs.mdx +10 -0
- package/site/content/docs/console/traces.mdx +4 -0
- package/site/content/docs/elements/ai.mdx +54 -32
- package/site/content/docs/elements/channel.mdx +97 -9
- package/site/content/docs/elements/clock.mdx +1 -0
- package/site/content/docs/elements/flow.mdx +42 -8
- package/site/content/docs/get-started/basic-usage.mdx +5 -1
- package/site/content/docs/get-started/installation.mdx +9 -5
- package/site/content/docs/meta.json +2 -0
- package/site/content/docs/providers/azure-redis.mdx +85 -0
- package/site/content/docs/providers/cockroachdb.mdx +86 -0
- package/site/content/docs/providers/digitalocean-caching.mdx +88 -0
- package/site/content/docs/providers/dragonfly-cloud.mdx +82 -0
- package/site/content/docs/providers/elasticache.mdx +92 -0
- package/site/content/docs/providers/index.mdx +101 -0
- package/site/content/docs/providers/memorystore.mdx +89 -0
- package/site/content/docs/providers/meta.json +20 -0
- package/site/content/docs/providers/neon.mdx +115 -0
- package/site/content/docs/providers/redis-cloud.mdx +93 -0
- package/site/content/docs/providers/supabase.mdx +117 -0
- package/site/content/docs/providers/upstash.mdx +91 -0
- package/site/content/docs/providers/yugabytedb.mdx +95 -0
- package/site/content/docs/recipes/caddy.mdx +128 -0
- package/site/content/docs/recipes/cockroachdb.mdx +127 -0
- package/site/content/docs/recipes/dragonfly.mdx +125 -0
- package/site/content/docs/recipes/index.mdx +146 -0
- package/site/content/docs/recipes/llama-cpp.mdx +153 -0
- package/site/content/docs/recipes/mailpit.mdx +136 -0
- package/site/content/docs/recipes/meilisearch.mdx +139 -0
- package/site/content/docs/recipes/meta.json +31 -0
- package/site/content/docs/recipes/ollama.mdx +142 -0
- package/site/content/docs/recipes/openbao.mdx +141 -0
- package/site/content/docs/recipes/pgdog.mdx +137 -0
- package/site/content/docs/recipes/postgres.mdx +136 -0
- package/site/content/docs/recipes/redis.mdx +130 -0
- package/site/content/docs/recipes/rustfs.mdx +148 -0
- package/site/content/docs/recipes/sglang.mdx +105 -0
- package/site/content/docs/recipes/supabase-docker.mdx +145 -0
- package/site/content/docs/recipes/timescale.mdx +129 -0
- package/site/content/docs/recipes/traefik.mdx +136 -0
- package/site/content/docs/recipes/valkey.mdx +121 -0
- package/site/content/docs/recipes/vllm.mdx +106 -0
- package/site/content/docs/recipes/yugabytedb.mdx +135 -0
- package/site/content/docs/reference/cli.md +42 -6
- package/site/content/docs/reference/configuration.mdx +5 -3
- package/site/content/docs/reference/environment-variables.mdx +12 -12
- package/site/content/docs/reference/fx.mdx +38 -4
- package/src/cli/ai-setup/ai-setup.test.ts +32 -12
- package/src/cli/ai-setup/apply.ts +65 -23
- package/src/cli/ai-setup/catalog.ts +1316 -35
- package/src/cli/ai-setup/detect-ollama.ts +47 -0
- package/src/cli/ai-setup/index.ts +44 -7
- package/src/cli/ai-setup/prompts.ts +430 -486
- package/src/cli/ai-setup/recommend.test.ts +150 -50
- package/src/cli/ai-setup/recommend.ts +118 -101
- package/src/cli/ask-seed.test.ts +68 -0
- package/src/cli/ask-seed.ts +79 -0
- package/src/cli/db-seed-redact.test.ts +25 -0
- package/src/cli/db-seed.ts +36 -7
- package/src/cli/db.test.ts +1 -1
- package/src/cli/db.ts +2 -2
- package/src/cli/dev-app-runner.ts +6 -0
- package/src/cli/dev-controls.test.ts +107 -0
- package/src/cli/dev-controls.ts +354 -0
- package/src/cli/dev-schema-sync.ts +12 -4
- package/src/cli/dev.test.ts +50 -30
- package/src/cli/dev.ts +633 -66
- package/src/cli/docker-cli.test.ts +15 -0
- package/src/cli/drizzle-env.test.ts +40 -6
- package/src/cli/drizzle-env.ts +22 -1
- package/src/cli/ensure-drizzle-config.ts +6 -4
- package/src/cli/hero-meta.test.ts +13 -1
- package/src/cli/hero-meta.ts +28 -6
- package/src/cli/index.ts +5 -0
- package/src/cli/registry.ts +24 -0
- package/src/cli/replay.test.ts +105 -0
- package/src/cli/replay.ts +206 -0
- package/src/cli/start.ts +12 -1
- package/src/compiler/effects-infer.ts +37 -8
- package/src/compiler/extract.test.ts +125 -0
- package/src/compiler/extract.ts +31 -6
- package/src/config/index.ts +3 -3
- package/src/console/server/claim.ts +3 -1
- package/src/console/ui/dist/assets/{index-ClX0ZCe5.js → index-D-9KFce5.js} +2 -2
- package/src/console/ui/dist/assets/panel-overview-CW0CQEc2.js +1 -0
- package/src/console/ui/dist/assets/panel-runs-BxuyDI3x.js +1 -0
- package/src/console/ui/dist/assets/{panel-signals-Dsxdu_AR.js → panel-signals-BXofbj7v.js} +1 -1
- package/src/console/ui/dist/assets/{panel-store-hy7O8HOs.js → panel-store-B8mH-arU.js} +1 -1
- package/src/console/ui/dist/assets/{panel-traces-CBiAe5go.js → panel-traces-DSA-ZWnf.js} +1 -1
- package/src/console/ui/dist/index.html +1 -1
- package/src/console/ui/overview/slo.ts +31 -3
- package/src/console/ui/overview/types.ts +6 -0
- package/src/console/ui/runs/errors.test.ts +53 -0
- package/src/console/ui/runs/errors.ts +88 -0
- package/src/console/ui/runs/index.ts +8 -0
- package/src/console/ui/runs/search.ts +16 -0
- package/src/console/ui/shell/panels/runs/RunsPanel.tsx +72 -1
- package/src/docker/ai-model-status.test.ts +101 -0
- package/src/docker/ai-model-status.ts +276 -0
- package/src/docker/compose-health.test.ts +115 -0
- package/src/docker/compose-health.ts +234 -0
- package/src/docker/compose.ts +24 -8
- package/src/docker/derive.ts +35 -9
- package/src/docker/docker.test.ts +304 -12
- package/src/docker/helpers.ts +56 -0
- package/src/docker/index.ts +52 -0
- package/src/docker/ollama-pull.ts +232 -0
- package/src/docker/recipes/cockroach.ts +24 -0
- package/src/docker/recipes/index.ts +32 -0
- package/src/docker/recipes/llama-cpp.ts +273 -0
- package/src/docker/recipes/ollama.ts +19 -23
- package/src/docker/recipes/pgdog.ts +4 -1
- package/src/docker/recipes/postgres.ts +5 -18
- package/src/docker/recipes/sglang.ts +55 -0
- package/src/docker/recipes/supabase.ts +21 -0
- package/src/docker/recipes/timescale.ts +18 -0
- package/src/docker/recipes/vllm.ts +44 -0
- package/src/docker/recipes/yugabyte.ts +23 -0
- package/src/docker/stack-id.test.ts +22 -0
- package/src/docker/stack-id.ts +38 -4
- package/src/docker/types.ts +15 -0
- package/src/drivers/ai-ollama.integration.test.ts +7 -4
- package/src/drivers/signal-engine.ts +10 -0
- package/src/drivers/signal-postgres.ts +24 -2
- package/src/drivers/signal-types.ts +10 -0
- package/src/elements/channel/fallback.test.ts +91 -0
- package/src/elements/channel/hard-bounce.test.ts +82 -0
- package/src/elements/channel/injection.test.ts +153 -0
- package/src/elements/channel/locale-ar.test.ts +102 -0
- package/src/elements/channel/otp-delivery.ts +5 -2
- package/src/elements/channel/receipts-ledger.test.ts +100 -0
- package/src/elements/channel/runtime.ts +24 -1
- package/src/elements/channel/test-helpers.ts +60 -0
- package/src/elements/channel/whatsapp-compliance.test.ts +124 -0
- package/src/elements/store/cache.test.ts +28 -0
- package/src/elements/store/cache.ts +1 -1
- package/src/elements/store/emit-drizzle.ts +43 -9
- package/src/elements/store/runtime.ts +1 -1
- package/src/elements/store/schema-decl.test.ts +2 -0
- package/src/elements/store/schema-decl.ts +15 -0
- package/src/elements/store/seed.ts +1 -1
- package/src/index.ts +1 -0
- package/src/kernel/app.ts +131 -10
- package/src/kernel/boot-bind/signal.ts +6 -2
- package/src/kernel/boot-bind/store.ts +2 -1
- package/src/kernel/boot.test.ts +6 -5
- package/src/kernel/boot.ts +113 -10
- package/src/kernel/compensate.test.ts +131 -0
- package/src/kernel/correlation.test.ts +108 -0
- package/src/kernel/effect-timing.test.ts +82 -0
- package/src/kernel/effects-stamping.test.ts +207 -0
- package/src/kernel/errors.ts +11 -0
- package/src/kernel/flow.ts +38 -0
- package/src/kernel/fx-runs.test.ts +49 -0
- package/src/kernel/fx.test.ts +14 -0
- package/src/kernel/fx.ts +153 -14
- package/src/manifest/sql-resource.ts +41 -0
- package/src/manifest/types.ts +8 -2
- package/src/runs/collect.ts +3 -0
- package/src/runs/export-otlp.ts +64 -0
- package/src/runs/index.ts +16 -0
- package/src/runs/parquet.ts +9 -0
- package/src/runs/types.ts +5 -0
- package/src/runs/window.test.ts +68 -0
- package/src/runs/window.ts +148 -0
- package/src/runtime/boot-warn.test.ts +45 -0
- package/src/runtime/boot-warn.ts +17 -0
- package/src/runtime/dev-request-log.ts +5 -5
- package/src/term.test.ts +95 -10
- package/src/term.ts +369 -14
- package/src/console/ui/dist/assets/panel-overview-DONDzBd2.js +0 -1
- package/src/console/ui/dist/assets/panel-runs-D5zf-D9c.js +0 -1
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "Meilisearch"
|
|
3
|
+
description: "Full-text store.index image — OKE_STORE_INDEX_URL, OKE_STORE_INDEX_KEY / MEILI_MASTER_KEY, /meili_data volume."
|
|
4
|
+
icon: "Search"
|
|
5
|
+
source: "docs/spec/unified-theory.md"
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
Meilisearch backs the `meilisearch` index driver — typo-tolerant full-text search over
|
|
9
|
+
HTTP. Pin `images["store.index"]` and set `drivers.store.index` to `meilisearch` where
|
|
10
|
+
you need it (index does **not** auto-promote in docker).
|
|
11
|
+
|
|
12
|
+
<Callout title="The one rule">
|
|
13
|
+
Index stays `memory` in every environment until you set the driver map explicitly — there is no
|
|
14
|
+
silent docker fallback to Meilisearch or pgvector.
|
|
15
|
+
</Callout>
|
|
16
|
+
|
|
17
|
+
## Quick start
|
|
18
|
+
|
|
19
|
+
<Steps>
|
|
20
|
+
|
|
21
|
+
<Step>
|
|
22
|
+
### Declare driver + image
|
|
23
|
+
|
|
24
|
+
```typescript title="oke.config.ts"
|
|
25
|
+
drivers: {
|
|
26
|
+
store: {
|
|
27
|
+
index: { local: "memory", docker: "meilisearch", prod: "meilisearch" },
|
|
28
|
+
},
|
|
29
|
+
},
|
|
30
|
+
images: {
|
|
31
|
+
"store.index": "getmeili/meilisearch:v1.14",
|
|
32
|
+
},
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
</Step>
|
|
36
|
+
|
|
37
|
+
<Step>
|
|
38
|
+
### Keys written by oke docker
|
|
39
|
+
|
|
40
|
+
```bash title="docker/.env.docker"
|
|
41
|
+
OKE_STORE_INDEX_URL=http://127.0.0.1:7700
|
|
42
|
+
OKE_STORE_INDEX_KEY=… # also accepted as MEILI_MASTER_KEY
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
Recipe injects into the container:
|
|
46
|
+
|
|
47
|
+
- `MEILI_MASTER_KEY=${OKE_STORE_INDEX_KEY}`
|
|
48
|
+
- `MEILI_ENV=${OKE_MEILI_ENV:-production}`
|
|
49
|
+
- `MEILI_NO_ANALYTICS=true`
|
|
50
|
+
|
|
51
|
+
</Step>
|
|
52
|
+
|
|
53
|
+
<Step>
|
|
54
|
+
### Search from a flow
|
|
55
|
+
|
|
56
|
+
Use `store.index(…)` without `{ dims }` for full-text (vector dims select pgvector /
|
|
57
|
+
libsql). Writes wait on Meilisearch tasks before returning.
|
|
58
|
+
|
|
59
|
+
</Step>
|
|
60
|
+
|
|
61
|
+
</Steps>
|
|
62
|
+
|
|
63
|
+
## Required env
|
|
64
|
+
|
|
65
|
+
| Variable | Required? | Meaning |
|
|
66
|
+
| --------------------- | -------------------- | ------------------------------------------------ |
|
|
67
|
+
| `OKE_STORE_INDEX_URL` | **Yes** | Base URL — boot fails without it |
|
|
68
|
+
| `OKE_STORE_INDEX_KEY` | **Yes** (production) | Master/API key; falls back to `MEILI_MASTER_KEY` |
|
|
69
|
+
| `MEILI_MASTER_KEY` | Alternate | Same secret, container-side name |
|
|
70
|
+
| `OKE_MEILI_ENV` | Optional | Passed as `MEILI_ENV` (default `production`) |
|
|
71
|
+
|
|
72
|
+
## Data and backup
|
|
73
|
+
|
|
74
|
+
| Volume | Path | What it stores |
|
|
75
|
+
| ------------------ | ------------- | ---------------------------- |
|
|
76
|
+
| `store-index-data` | `/meili_data` | Indexes, documents, settings |
|
|
77
|
+
|
|
78
|
+
**Backup means:** snapshot/restore that named volume (or Meilisearch dumps). Recreating
|
|
79
|
+
the container **keeps** data if the volume remains; deleting the volume wipes every index.
|
|
80
|
+
|
|
81
|
+
The master key is **not** inside the volume — it lives in `.env.docker` / secrets.
|
|
82
|
+
Losing the key without a backup blocks admin API access even if data remains.
|
|
83
|
+
|
|
84
|
+
## Production note
|
|
85
|
+
|
|
86
|
+
Always set a non-empty `OKE_STORE_INDEX_KEY` when `MEILI_ENV=production` — Meilisearch
|
|
87
|
+
refuses insecure production mode without a master key. Prefer network isolation (compose
|
|
88
|
+
network only) plus the key; do not publish `:7700` on the public internet without auth.
|
|
89
|
+
|
|
90
|
+
Vector `ai.embed` into a meilisearch index fails loud — embeddings need `pgvector` /
|
|
91
|
+
`libsql`, not FTS. See [Store · Index](/docs/elements/store#index).
|
|
92
|
+
|
|
93
|
+
## What the recipe configures
|
|
94
|
+
|
|
95
|
+
| Field | Value |
|
|
96
|
+
| -------------- | ---------------------------------------------- |
|
|
97
|
+
| Container port | `7700` |
|
|
98
|
+
| Healthcheck | `wget` against `/health`, every 5s, 12 retries |
|
|
99
|
+
| Connection URL | `http://host:7700` |
|
|
100
|
+
|
|
101
|
+
## Troubleshooting
|
|
102
|
+
|
|
103
|
+
<Accordions>
|
|
104
|
+
<Accordion title="oke boot: meilisearch index needs OKE_STORE_INDEX_URL">
|
|
105
|
+
|
|
106
|
+
No silent memory fallback. Re-run `oke dev --docker` or export `OKE_STORE_INDEX_URL`.
|
|
107
|
+
Docker-mode wording asks whether `docker/.env.docker` was written.
|
|
108
|
+
|
|
109
|
+
</Accordion>
|
|
110
|
+
<Accordion title="meilisearch index: GET/POST … failed (403) — or master key errors">
|
|
111
|
+
|
|
112
|
+
`OKE_STORE_INDEX_KEY` does not match `MEILI_MASTER_KEY` inside the container, or the key
|
|
113
|
+
was rotated without updating the app env. Align both sides and restart. Unreachable host
|
|
114
|
+
surfaces as `meilisearch index: unreachable at <url> — …`.
|
|
115
|
+
|
|
116
|
+
</Accordion>
|
|
117
|
+
</Accordions>
|
|
118
|
+
|
|
119
|
+
## Learn more
|
|
120
|
+
|
|
121
|
+
- [Store · Index](/docs/elements/store#index) — FTS vs vector drivers
|
|
122
|
+
- [Environment variables](/docs/reference/environment-variables) — index URL / key
|
|
123
|
+
- [Configuration](/docs/reference/configuration) — `drivers.store.index` union
|
|
124
|
+
|
|
125
|
+
## Next
|
|
126
|
+
|
|
127
|
+
<Cards>
|
|
128
|
+
<Card
|
|
129
|
+
title="llama.cpp"
|
|
130
|
+
description="Default local AI for the same stack."
|
|
131
|
+
href="/docs/recipes/llama-cpp"
|
|
132
|
+
/>
|
|
133
|
+
<Card
|
|
134
|
+
title="Postgres"
|
|
135
|
+
description="pgvector alternative for embeddings."
|
|
136
|
+
href="/docs/recipes/postgres"
|
|
137
|
+
/>
|
|
138
|
+
<Card title="Store" description="Index facet API." href="/docs/elements/store" />
|
|
139
|
+
</Cards>
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
{
|
|
2
|
+
"title": "Recipes",
|
|
3
|
+
"icon": "Container",
|
|
4
|
+
"pages": [
|
|
5
|
+
"index",
|
|
6
|
+
"---SQL---",
|
|
7
|
+
"postgres",
|
|
8
|
+
"supabase-docker",
|
|
9
|
+
"cockroachdb",
|
|
10
|
+
"yugabytedb",
|
|
11
|
+
"timescale",
|
|
12
|
+
"---KV---",
|
|
13
|
+
"redis",
|
|
14
|
+
"valkey",
|
|
15
|
+
"dragonfly",
|
|
16
|
+
"---Proxy---",
|
|
17
|
+
"caddy",
|
|
18
|
+
"traefik",
|
|
19
|
+
"---Services---",
|
|
20
|
+
"pgdog",
|
|
21
|
+
"rustfs",
|
|
22
|
+
"mailpit",
|
|
23
|
+
"openbao",
|
|
24
|
+
"meilisearch",
|
|
25
|
+
"---AI---",
|
|
26
|
+
"llama-cpp",
|
|
27
|
+
"ollama",
|
|
28
|
+
"vllm",
|
|
29
|
+
"sglang"
|
|
30
|
+
]
|
|
31
|
+
}
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "Ollama"
|
|
3
|
+
description: "Fully supported local AI alternative — OKE_AI_URL, pinned ≥ 0.17.1, loopback-only publish, library models only."
|
|
4
|
+
icon: "Bot"
|
|
5
|
+
source: "docs/spec/unified-theory.md"
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
Ollama remains a **fully supported** local model server (not deprecated). The
|
|
9
|
+
default local pin is [llama.cpp](/docs/recipes/llama-cpp); choose Ollama when you
|
|
10
|
+
want its library pull UX. Pin `images.ai` and set `drivers.ai` to `ollama`.
|
|
11
|
+
|
|
12
|
+
<Callout title="The one rule">
|
|
13
|
+
Pin ≥ `0.17.1` (never `latest`), publish only on loopback, and load models only from Ollama’s
|
|
14
|
+
library — never arbitrary untrusted GGUF via `/api/create`.
|
|
15
|
+
</Callout>
|
|
16
|
+
|
|
17
|
+
## Quick start
|
|
18
|
+
|
|
19
|
+
<Steps>
|
|
20
|
+
|
|
21
|
+
<Step>
|
|
22
|
+
### Pin driver + image
|
|
23
|
+
|
|
24
|
+
```typescript title="oke.config.ts"
|
|
25
|
+
drivers: {
|
|
26
|
+
ai: { local: "ollama", docker: "ollama", test: "mock" }, // prod: set deliberately
|
|
27
|
+
},
|
|
28
|
+
images: {
|
|
29
|
+
ai: "ollama/ollama:0.32.6", // never :latest — floor 0.17.1 (CVE-2026-7482)
|
|
30
|
+
},
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
Or run `oke ai setup --provider ollama --yes`.
|
|
34
|
+
|
|
35
|
+
</Step>
|
|
36
|
+
|
|
37
|
+
<Step>
|
|
38
|
+
### Env written by the stack
|
|
39
|
+
|
|
40
|
+
```bash title="docker/.env.docker"
|
|
41
|
+
OKE_AI_URL=http://127.0.0.1:11434
|
|
42
|
+
OKE_AI_MODEL=qwen3.5:9b
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
Host publish is `127.0.0.1:11434:11434`. Inside the container
|
|
46
|
+
`OLLAMA_HOST=0.0.0.0:11434` so Docker networking works.
|
|
47
|
+
|
|
48
|
+
</Step>
|
|
49
|
+
|
|
50
|
+
<Step>
|
|
51
|
+
### Boot pulls against the container API
|
|
52
|
+
|
|
53
|
+
After compose is healthy, `oke dev -d` shows `OKE_AI_MODEL` in the hero / Docker
|
|
54
|
+
summary, POSTs `/api/pull` to **this container’s**
|
|
55
|
+
loopback URL when the recipe is Ollama — never a host `ollama` CLI.
|
|
56
|
+
|
|
57
|
+
</Step>
|
|
58
|
+
|
|
59
|
+
</Steps>
|
|
60
|
+
|
|
61
|
+
## Security (hard requirements)
|
|
62
|
+
|
|
63
|
+
| Control | Requirement |
|
|
64
|
+
| -------------- | -------------------------------------------------------------------------- |
|
|
65
|
+
| Host publish | `127.0.0.1:11434:11434` only — never `0.0.0.0` |
|
|
66
|
+
| Image pin | Explicit tag ≥ **0.17.1** (CVE-2026-7482); never `latest` |
|
|
67
|
+
| Model source | [Ollama library](https://ollama.com/library) only |
|
|
68
|
+
| Untrusted GGUF | **Forbidden** — `/api/create` with crafted files is the CVE-2026-7482 path |
|
|
69
|
+
|
|
70
|
+
Ollama and llama.cpp share GGUF-parser risk; Ollama also has its own Go loader
|
|
71
|
+
CVE. Network exposure of `:11434` turns that into a remote attack.
|
|
72
|
+
|
|
73
|
+
<Callout type="warn" title="Host `ollama` CLI is unrelated">
|
|
74
|
+
A host `ollama pull` often talks to a separately installed daemon. Trust boot ensure against
|
|
75
|
+
`OKE_AI_URL`.
|
|
76
|
+
</Callout>
|
|
77
|
+
|
|
78
|
+
## Required env
|
|
79
|
+
|
|
80
|
+
| Variable | Required? | Meaning |
|
|
81
|
+
| -------------------------------------------- | ----------------- | ------------------------------------------------------------------ |
|
|
82
|
+
| `OKE_AI_URL` | **Yes** in docker | Base URL — `oke boot: ollama driver needs OKE_AI_URL` when missing |
|
|
83
|
+
| `OKE_AI_MODEL` | Recommended | Model tag to pull/serve (default `qwen3.5:9b`) |
|
|
84
|
+
| `OLLAMA_HOST` | Set by recipe | `0.0.0.0:11434` inside the container |
|
|
85
|
+
| `OKE_AI_VISION_MODEL` / `OKE_AI_EMBED_MODEL` | Optional | Written by `oke ai setup` for logical models |
|
|
86
|
+
|
|
87
|
+
## Data and backup
|
|
88
|
+
|
|
89
|
+
| Volume | Path | What it stores |
|
|
90
|
+
| --------- | --------------- | -------------------------------------- |
|
|
91
|
+
| `ai-data` | `/root/.ollama` | Pulled model weights + Ollama metadata |
|
|
92
|
+
|
|
93
|
+
## Production note
|
|
94
|
+
|
|
95
|
+
Local Ollama is for docker/dev (and air-gapped prod you deliberately choose).
|
|
96
|
+
For multi-user GPU self-hosting see [vLLM](/docs/recipes/vllm) /
|
|
97
|
+
[SGLang](/docs/recipes/sglang). Cloud drivers stay separate.
|
|
98
|
+
|
|
99
|
+
PII egress rules treat `ollama` as local — see [AI · PII](/docs/elements/ai).
|
|
100
|
+
|
|
101
|
+
## What the recipe configures
|
|
102
|
+
|
|
103
|
+
| Field | Value |
|
|
104
|
+
| -------------- | ---------------------------------------------- |
|
|
105
|
+
| Container port | `11434` |
|
|
106
|
+
| Host publish | `127.0.0.1:11434:11434` |
|
|
107
|
+
| Entrypoint | Image default (`ollama serve`) |
|
|
108
|
+
| Healthcheck | `ollama list`, every 5s, 24 retries, 10s start |
|
|
109
|
+
| Connection URL | `http://host:11434` |
|
|
110
|
+
| Model pull | Host-side `POST /api/pull` after healthy |
|
|
111
|
+
|
|
112
|
+
## Troubleshooting
|
|
113
|
+
|
|
114
|
+
<Accordions>
|
|
115
|
+
<Accordion title="oke boot: ollama driver needs OKE_AI_URL">
|
|
116
|
+
|
|
117
|
+
Docker mode expects `OKE_AI_URL` from `docker/.env.docker` when `images.ai` is pinned.
|
|
118
|
+
Locally the default is `http://127.0.0.1:11434`. Prefer `oke ai setup` to wire everything
|
|
119
|
+
in one pass.
|
|
120
|
+
|
|
121
|
+
</Accordion>
|
|
122
|
+
<Accordion title="Model missing / I already ran ollama pull on the host">
|
|
123
|
+
|
|
124
|
+
The host CLI likely filled a **different** Ollama. Check `GET $OKE_AI_URL/api/tags`,
|
|
125
|
+
then recreate with `oke dev -d`.
|
|
126
|
+
|
|
127
|
+
</Accordion>
|
|
128
|
+
</Accordions>
|
|
129
|
+
|
|
130
|
+
## Learn more
|
|
131
|
+
|
|
132
|
+
- [llama.cpp](/docs/recipes/llama-cpp) — default local AI
|
|
133
|
+
- [AI](/docs/elements/ai) — `fx.ask`, prompts, evals
|
|
134
|
+
- [CLI · oke ai setup](/docs/reference/cli) — non-interactive provider wiring
|
|
135
|
+
|
|
136
|
+
## Next
|
|
137
|
+
|
|
138
|
+
<Cards>
|
|
139
|
+
<Card title="llama.cpp" description="Default local AI." href="/docs/recipes/llama-cpp" />
|
|
140
|
+
<Card title="Meilisearch" description="Full-text index peer." href="/docs/recipes/meilisearch" />
|
|
141
|
+
<Card title="AI" description="Prompts, models, guardrails." href="/docs/elements/ai" />
|
|
142
|
+
</Cards>
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "OpenBao"
|
|
3
|
+
description: "Durable single-node vault — Raft under /openbao/file, OKE_VAULT_URL / OKE_VAULT_TOKEN, host unseal key SPOF."
|
|
4
|
+
icon: "KeyRound"
|
|
5
|
+
source: "docs/spec/unified-theory.md"
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
OpenBao is the docker/prod Vault driver target — a real secrets service with Raft
|
|
9
|
+
storage, **not** an in-memory `-dev` server. Templates pin
|
|
10
|
+
`vault: "openbao/openbao:2.6.1"` and `drivers.vault.docker/prod: "openbao"`.
|
|
11
|
+
|
|
12
|
+
<Callout title="The one rule">
|
|
13
|
+
Never run OpenBao `-dev` in docker/prod. Data belongs on the Raft volume; init + unseal stay on
|
|
14
|
+
the host under `.oke/openbao/`.
|
|
15
|
+
</Callout>
|
|
16
|
+
|
|
17
|
+
## Quick start
|
|
18
|
+
|
|
19
|
+
<Steps>
|
|
20
|
+
|
|
21
|
+
<Step>
|
|
22
|
+
### Pin driver + image
|
|
23
|
+
|
|
24
|
+
```typescript title="oke.config.ts"
|
|
25
|
+
drivers: {
|
|
26
|
+
vault: { local: "env", docker: "openbao", test: "memory", prod: "openbao" },
|
|
27
|
+
},
|
|
28
|
+
images: {
|
|
29
|
+
vault: "openbao/openbao:2.6.1",
|
|
30
|
+
},
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
</Step>
|
|
34
|
+
|
|
35
|
+
<Step>
|
|
36
|
+
### First boot is automatic
|
|
37
|
+
|
|
38
|
+
`oke dev --docker` initializes OpenBao (Shamir 1-of-1), unseals it, writes a
|
|
39
|
+
least-privilege policy for **declared** secrets only, and mints an app token. You do not
|
|
40
|
+
run raw `bao` commands.
|
|
41
|
+
|
|
42
|
+
</Step>
|
|
43
|
+
|
|
44
|
+
<Step>
|
|
45
|
+
### App sees only the least-privilege token
|
|
46
|
+
|
|
47
|
+
```bash title="docker/.env.docker"
|
|
48
|
+
OKE_VAULT_URL=http://127.0.0.1:8200
|
|
49
|
+
OKE_VAULT_TOKEN=… # app token — not the root token
|
|
50
|
+
OKE_VAULT_MOUNT=secret # KV v2 mount (default)
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
</Step>
|
|
54
|
+
|
|
55
|
+
</Steps>
|
|
56
|
+
|
|
57
|
+
## Required env
|
|
58
|
+
|
|
59
|
+
| Variable | Who holds it | Meaning |
|
|
60
|
+
| ------------------ | ------------------- | ---------------------------------------- |
|
|
61
|
+
| `OKE_VAULT_URL` | App / stack | OpenBao base URL |
|
|
62
|
+
| `OKE_VAULT_TOKEN` | App (`.env.docker`) | Least-privilege app token |
|
|
63
|
+
| `OKE_VAULT_MOUNT` | Optional | KV v2 mount path (default `"secret"`) |
|
|
64
|
+
| `BAO_LOCAL_CONFIG` | Container (recipe) | Listener + Raft JSON — set by the recipe |
|
|
65
|
+
|
|
66
|
+
Host-only material (mode `0600`, gitignored) — **not** in compose YAML:
|
|
67
|
+
|
|
68
|
+
| File | Holds |
|
|
69
|
+
| ------------------------- | ---------------------------------------- |
|
|
70
|
+
| `.oke/openbao/unseal.key` | Single unseal share |
|
|
71
|
+
| `.oke/openbao/root.token` | Root token (CLI policy sync / mint only) |
|
|
72
|
+
| `.oke/openbao/app.token` | Same least-privilege token the app uses |
|
|
73
|
+
|
|
74
|
+
## Data and backup
|
|
75
|
+
|
|
76
|
+
| Volume | Path | What it stores |
|
|
77
|
+
| ------------ | --------------- | ---------------------------- |
|
|
78
|
+
| `vault-data` | `/openbao/file` | Raft storage (node id `oke`) |
|
|
79
|
+
|
|
80
|
+
Recipe note: Raft path is `/openbao/file` (the stock entrypoint chowns that directory).
|
|
81
|
+
Healthcheck hits `/v1/sys/init` — **200 even while sealed**; bootstrap owns unseal.
|
|
82
|
+
|
|
83
|
+
**Backup means two things:**
|
|
84
|
+
|
|
85
|
+
1. The Raft volume (`/openbao/file`) — encrypted secret store
|
|
86
|
+
2. `.oke/openbao/unseal.key` on the host — without it the volume is unrecoverable
|
|
87
|
+
|
|
88
|
+
## Production note
|
|
89
|
+
|
|
90
|
+
<Callout title="Single point of failure — read this once" type="warn">
|
|
91
|
+
Back up `.oke/openbao/unseal.key` to a separate safe location. Losing it means losing every secret
|
|
92
|
+
permanently, with no recovery. Restated from [Vault ·
|
|
93
|
+
OpenBao](/docs/elements/vault#openbao-in-docker-and-prod).
|
|
94
|
+
</Callout>
|
|
95
|
+
|
|
96
|
+
Self-hosted single-node, Shamir 1-of-1, no cloud KMS — by design. If OpenBao is
|
|
97
|
+
initialized but the key is gone, boot fails with an explicit permanent-loss error; it
|
|
98
|
+
never silently starts empty.
|
|
99
|
+
|
|
100
|
+
## What the recipe configures
|
|
101
|
+
|
|
102
|
+
| Field | Value |
|
|
103
|
+
| -------------- | -------------------------------------------------------------------------------------- |
|
|
104
|
+
| Container port | `8200` |
|
|
105
|
+
| Command | `server` (with `BAO_LOCAL_CONFIG`) |
|
|
106
|
+
| TLS | Disabled on the listener for compose (`tls_disable: true`) — rely on network isolation |
|
|
107
|
+
| Healthcheck | `wget` `/v1/sys/init`, every 5s, 12 retries |
|
|
108
|
+
|
|
109
|
+
## Troubleshooting
|
|
110
|
+
|
|
111
|
+
<Accordions>
|
|
112
|
+
<Accordion title="openbao vault: GET … failed (… ) — sealed or unauthorized?">
|
|
113
|
+
|
|
114
|
+
`OpenBaoUnavailableError` — vault sealed, wrong token, or unreachable. Re-run
|
|
115
|
+
`oke dev --docker` so bootstrap unseals with the host key. If the vault is initialized
|
|
116
|
+
but `.oke/openbao/unseal.key` is missing, restore the key from backup.
|
|
117
|
+
|
|
118
|
+
</Accordion>
|
|
119
|
+
<Accordion title="Permanent-loss / initialized but key missing">
|
|
120
|
+
|
|
121
|
+
Starting empty would look like “no secrets.” The CLI refuses that path. Restore
|
|
122
|
+
`unseal.key` or treat the Raft volume as destroyed and re-init only if you accept wiping
|
|
123
|
+
secrets.
|
|
124
|
+
|
|
125
|
+
</Accordion>
|
|
126
|
+
</Accordions>
|
|
127
|
+
|
|
128
|
+
## Learn more
|
|
129
|
+
|
|
130
|
+
- [Vault · OpenBao in docker and prod](/docs/elements/vault#openbao-in-docker-and-prod) —
|
|
131
|
+
full bootstrap, key table, SPOF callout
|
|
132
|
+
- [Errors](/docs/reference/errors) — `OpenBaoUnavailableError`, `OpenBaoBootstrapError`
|
|
133
|
+
- [CLI · oke vault](/docs/reference/cli) — `set` / `list` / `import`
|
|
134
|
+
|
|
135
|
+
## Next
|
|
136
|
+
|
|
137
|
+
<Cards>
|
|
138
|
+
<Card title="Vault" description="Resolution chain and rotation." href="/docs/elements/vault" />
|
|
139
|
+
<Card title="Mailpit" description="Local email catcher." href="/docs/recipes/mailpit" />
|
|
140
|
+
<Card title="RustFS" description="S3-compatible files." href="/docs/recipes/rustfs" />
|
|
141
|
+
</Cards>
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "PgDog"
|
|
3
|
+
description: "Postgres wire-protocol pooler — transaction mode on :6432, generated pgdog.toml / users.toml, DATABASE_URL rewrite."
|
|
4
|
+
icon: "Package"
|
|
5
|
+
source: "docs/spec/unified-theory.md"
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
Bun.SQL defaults to **10** connections per process. Scale to several app instances and
|
|
9
|
+
`N × pool` can exceed Postgres `max_connections`. PgDog sits in front of `store.sql` as a
|
|
10
|
+
transaction-pooling proxy — same wire protocol, no app code changes.
|
|
11
|
+
|
|
12
|
+
<Callout title="The one rule">
|
|
13
|
+
Pin `pgdog` alongside `store.sql` and `DATABASE_URL` automatically points at the pooler on `:6432`
|
|
14
|
+
instead of Postgres directly — Bun.SQL and Drizzle see no difference.
|
|
15
|
+
</Callout>
|
|
16
|
+
|
|
17
|
+
## Quick start
|
|
18
|
+
|
|
19
|
+
<Steps>
|
|
20
|
+
|
|
21
|
+
<Step>
|
|
22
|
+
### Pin both images
|
|
23
|
+
|
|
24
|
+
```typescript title="oke.config.ts"
|
|
25
|
+
images: {
|
|
26
|
+
"store.sql": "postgres:18-alpine",
|
|
27
|
+
pgdog: "ghcr.io/pgdogdev/pgdog:v0.1.51",
|
|
28
|
+
},
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
</Step>
|
|
32
|
+
|
|
33
|
+
<Step>
|
|
34
|
+
### Derive compose
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
oke docker
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
Writes `./pgdog.toml` (listen + one primary database) and `./users.toml` (same
|
|
41
|
+
user/password/database as Postgres). The pooler waits on `store-sql` health before start.
|
|
42
|
+
|
|
43
|
+
</Step>
|
|
44
|
+
|
|
45
|
+
<Step>
|
|
46
|
+
### Confirm the rewrite
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
echo "$DATABASE_URL"
|
|
50
|
+
# …@host:6432/db ← pooler, not :5432
|
|
51
|
+
echo "$OKE_STORE_SQL_URL" # still the direct Postgres URL when you need it
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
</Step>
|
|
55
|
+
|
|
56
|
+
</Steps>
|
|
57
|
+
|
|
58
|
+
## Required env
|
|
59
|
+
|
|
60
|
+
| Variable | Role |
|
|
61
|
+
| ---------------------------------------- | ---------------------------------------------------------------- |
|
|
62
|
+
| `OKE_STORE_SQL_USER` / `PASSWORD` / `DB` | Copied into `users.toml` for client + server auth |
|
|
63
|
+
| `DATABASE_URL` | Rewritten to the pooler URL (`:6432`) when PgDog is in the stack |
|
|
64
|
+
| `OKE_PGDOG_URL` | Same value as pooled `DATABASE_URL` when both are present |
|
|
65
|
+
| `OKE_STORE_SQL_URL` | Direct Postgres host — bypass the pooler for admin / migrations |
|
|
66
|
+
|
|
67
|
+
PgDog itself has no separate credential env — it mounts the generated TOML files read-only.
|
|
68
|
+
|
|
69
|
+
## Data and backup
|
|
70
|
+
|
|
71
|
+
| Mount | What it is |
|
|
72
|
+
| ----------------------------------- | ------------------------------------------------------------------ |
|
|
73
|
+
| `./pgdog.toml:/pgdog/pgdog.toml:ro` | Generated listen + `[[databases]]` (host `store-sql`, port `5432`) |
|
|
74
|
+
| `./users.toml:/pgdog/users.toml:ro` | Generated `[[users]]` credentials |
|
|
75
|
+
|
|
76
|
+
**No database state lives in the PgDog container.** Backing up PgDog means keeping those
|
|
77
|
+
two config files (they are regenerated by `oke docker`). Durable data stays on the
|
|
78
|
+
[Postgres](/docs/recipes/postgres) volume / dump.
|
|
79
|
+
|
|
80
|
+
## Production note
|
|
81
|
+
|
|
82
|
+
Pooling mode is `transaction` — set explicitly (also PgDog's upstream default). Naive
|
|
83
|
+
poolers can leak session state (`SET`, RLS vars, `LISTEN`/`NOTIFY`) across clients;
|
|
84
|
+
PgDog re-applies that state per transaction.
|
|
85
|
+
|
|
86
|
+
**Do not stack** PgDog in front of a managed pooler (Neon `-pooler`, Supabase Supavisor
|
|
87
|
+
`:6543`). Pick one pooler. Use `OKE_STORE_SQL_URL` (direct) for migrations and anything
|
|
88
|
+
that needs session features.
|
|
89
|
+
|
|
90
|
+
Read-replica routing (`BEGIN READ ONLY` → replica) is documented readiness in PgDog —
|
|
91
|
+
not wired into the generated stack yet.
|
|
92
|
+
|
|
93
|
+
## What the recipe configures
|
|
94
|
+
|
|
95
|
+
| Field | Value |
|
|
96
|
+
| -------------- | ------------------------------------------------------- |
|
|
97
|
+
| Container port | `6432` |
|
|
98
|
+
| `dependsOn` | `store-sql` healthy |
|
|
99
|
+
| Healthcheck | `pg_isready -h 127.0.0.1 -p 6432`, every 5s, 12 retries |
|
|
100
|
+
| Connection URL | `postgres://user:pass@host:6432/db` |
|
|
101
|
+
|
|
102
|
+
## Troubleshooting
|
|
103
|
+
|
|
104
|
+
<Accordions>
|
|
105
|
+
<Accordion title="pgdog unhealthy — pg_isready on :6432 fails">
|
|
106
|
+
|
|
107
|
+
Usually the backend is not ready, or `users.toml` credentials do not match Postgres.
|
|
108
|
+
Confirm `store-sql` is healthy first, then re-run `oke docker` so TOML matches
|
|
109
|
+
`OKE_STORE_SQL_*`. Logs often show auth failures against `store-sql:5432`.
|
|
110
|
+
|
|
111
|
+
</Accordion>
|
|
112
|
+
<Accordion title="Session features break through the pooler">
|
|
113
|
+
|
|
114
|
+
Transaction mode does not preserve session-scoped state the way a direct connection
|
|
115
|
+
does. Point migrations / `LISTEN` / session `SET` at `OKE_STORE_SQL_URL` (direct
|
|
116
|
+
Postgres), keep `DATABASE_URL` on the pooler for app traffic.
|
|
117
|
+
|
|
118
|
+
</Accordion>
|
|
119
|
+
</Accordions>
|
|
120
|
+
|
|
121
|
+
## Learn more
|
|
122
|
+
|
|
123
|
+
- [Docker · PgDog pooling](/docs/deployment/docker#pgdog-pooling) — compose `-f` layer order
|
|
124
|
+
- [Postgres](/docs/recipes/postgres) — the backend PgDog fronts
|
|
125
|
+
- [Store · SQL](/docs/elements/store#sql) — “Connection pooling is infrastructure”
|
|
126
|
+
|
|
127
|
+
## Next
|
|
128
|
+
|
|
129
|
+
<Cards>
|
|
130
|
+
<Card title="Postgres" description="The backend PgDog fronts." href="/docs/recipes/postgres" />
|
|
131
|
+
<Card
|
|
132
|
+
title="Supabase"
|
|
133
|
+
description="Also Postgres wire — same pooler applies."
|
|
134
|
+
href="/docs/recipes/supabase-docker"
|
|
135
|
+
/>
|
|
136
|
+
<Card title="Caddy" description="TLS at the edge, once you need it." href="/docs/recipes/caddy" />
|
|
137
|
+
</Cards>
|